Browse code

libclamav/str.c: return token count in cli_strtokenize() libclamav/readdb.c: use tokens_count (bb#1331); make the parser more strict

git-svn: trunk@4593

Tomasz Kojm authored on 2009/01/06 04:57:47
Showing 5 changed files
... ...
@@ -1,3 +1,9 @@
1
+Mon Jan  5 20:33:04 CET 2009 (tk)
2
+---------------------------------
3
+ * libclamav/str.c: return token count in cli_strtokenize()
4
+ * libclamav/readdb.c: use tokens_count (bb#1331); make the parser more
5
+		       strict
6
+
1 7
 Mon Jan  5 19:54:13 CET 2009 (tk)
2 8
 ---------------------------------
3 9
  * libclamav/mpool.c: fix old free() call in cli_mp_hex2ui()
... ...
@@ -470,7 +470,7 @@ static void scope_free_all(struct scope *p)
470 470
 	} while(p);
471 471
 }
472 472
 
473
-void cli_strtokenize(char *buffer, const char delim, const size_t token_count, const char **tokens);
473
+size_t cli_strtokenize(char *buffer, const char delim, const size_t token_count, const char **tokens);
474 474
 static int match_parameters(const yystype *tokens, const char ** param_names, size_t count)
475 475
 {
476 476
 	size_t i,j=0;
... ...
@@ -519,11 +519,11 @@ static int cli_loadpdb(FILE *fs, struct cl_engine *engine, unsigned int options,
519 519
 #define NDB_TOKENS 6
520 520
 static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned short sdb, unsigned int options, struct cli_dbio *dbio, const char *dbname)
521 521
 {
522
-	const char *tokens[NDB_TOKENS];
522
+	const char *tokens[NDB_TOKENS + 1];
523 523
 	char buffer[FILEBUFF];
524 524
 	const char *sig, *virname, *offset, *pt;
525 525
 	struct cli_matcher *root;
526
-	int line = 0, sigs = 0, ret = 0;
526
+	int line = 0, sigs = 0, ret = 0, tokens_count;
527 527
 	unsigned short target;
528 528
 	unsigned int phish = options & CL_DB_PHISHING;
529 529
 
... ...
@@ -543,13 +543,15 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
543 543
 
544 544
 	cli_chomp(buffer);
545 545
 
546
-	cli_strtokenize(buffer, ':', NDB_TOKENS, tokens);
547
-
548
-	if(!(virname = tokens[0])) {
546
+	tokens_count = cli_strtokenize(buffer, ':', NDB_TOKENS + 1, tokens);
547
+	/* FIXME: re-enable after fixing invalid sig @ main.ndb:53467 */
548
+	if(tokens_count < 4 /*|| tokens_count > 6*/) {
549 549
 	    ret = CL_EMALFDB;
550 550
 	    break;
551 551
 	}
552 552
 
553
+	virname = tokens[0];
554
+
553 555
 	if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
554 556
 	    if(cli_chkpua(virname, engine->pua_cats, options))
555 557
 		continue;
... ...
@@ -557,7 +559,8 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
557 557
 	if(engine->ignored && cli_chkign(engine->ignored, dbname, line, virname))
558 558
 	    continue;
559 559
 
560
-	if((pt = tokens[4])) { /* min version */
560
+	if(tokens_count > 4) { /* min version */
561
+	    pt = tokens[4];
561 562
 	    if(!isdigit(*pt)) {
562 563
 		ret = CL_EMALFDB;
563 564
 		break;
... ...
@@ -568,8 +571,8 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
568 568
 		continue;
569 569
 	    }
570 570
 
571
-
572
-	    if((pt = tokens[5])) { /* max version */
571
+	    if(tokens_count == 6) { /* max version */
572
+		pt = tokens[5];
573 573
 		if(!isdigit(*pt)) {
574 574
 		    ret = CL_EMALFDB;
575 575
 		    break;
... ...
@@ -578,7 +581,6 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
578 578
 		if((unsigned int) atoi(pt) < cl_retflevel()) {
579 579
 		    continue;
580 580
 		}
581
-
582 581
 	    }
583 582
 	}
584 583
 
... ...
@@ -595,17 +597,11 @@ static int cli_loadndb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
595 595
 
596 596
 	root = engine->root[target];
597 597
 
598
-	if(!(offset = tokens[2])) {
599
-	    ret = CL_EMALFDB;
600
-	    break;
601
-	} else if(!strcmp(offset, "*")) {
598
+	offset = tokens[2];
599
+	if(!strcmp(offset, "*"))
602 600
 	    offset = NULL;
603
-	}
604 601
 
605
-	if(!(sig = tokens[3])) {
606
-	    ret = CL_EMALFDB;
607
-	    break;
608
-	}
602
+	sig = tokens[3];
609 603
 
610 604
 	if((ret = cli_parse_add(root, virname, sig, 0, 0, offset, target, NULL, options))) {
611 605
 	    ret = CL_EMALFDB;
... ...
@@ -665,13 +661,13 @@ static int lsigattribs(char *attribs, struct cli_lsig_tdb *tdb)
665 665
 	};
666 666
 	struct lsig_attrib *apt;
667 667
 	char *tokens[ATTRIB_TOKENS], *pt, *pt2;
668
-	unsigned int v1, v2, v3, i, j;
668
+	unsigned int v1, v2, v3, i, j, tokens_count;
669 669
 	uint32_t cnt, off[ATTRIB_TOKENS];
670 670
 
671 671
 
672
-    cli_strtokenize(attribs, ',', ATTRIB_TOKENS, (const char **) tokens);
672
+    tokens_count = cli_strtokenize(attribs, ',', ATTRIB_TOKENS, (const char **) tokens);
673 673
 
674
-    for(i = 0; tokens[i]; i++) {
674
+    for(i = 0; i < tokens_count; i++) {
675 675
 	if(!(pt = strchr(tokens[i], ':'))) {
676 676
 	    cli_errmsg("lsigattribs: Incorrect format of attribute '%s'\n", tokens[i]);
677 677
 	    return -1;
... ...
@@ -759,7 +755,7 @@ static int lsigattribs(char *attribs, struct cli_lsig_tdb *tdb)
759 759
 	return -1;
760 760
     }
761 761
 
762
-    for(i = 0; tokens[i]; i++) {
762
+    for(i = 0; i < tokens_count; i++) {
763 763
 	for(j = 0; attrtab[j].name; j++) {
764 764
 	    if(!strcmp(attrtab[j].name, tokens[i])) {
765 765
 		apt = &attrtab[j];
... ...
@@ -807,7 +803,7 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
807 807
 	unsigned short target = 0;
808 808
 	struct cli_ac_lsig **newtable, *lsig;
809 809
 	uint32_t lsigid[2];
810
-	int ret = CL_SUCCESS, i, subsigs;
810
+	int ret = CL_SUCCESS, i, subsigs, tokens_count;
811 811
 	struct cli_lsig_tdb tdb;
812 812
 
813 813
 
... ...
@@ -819,13 +815,15 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
819 819
 	sigs++;
820 820
 	cli_chomp(buffer);
821 821
 
822
-	cli_strtokenize(buffer, ';', LDB_TOKENS, (const char **) tokens);
823
-
824
-	if(!(virname = tokens[0])) {
822
+	tokens_count = cli_strtokenize(buffer, ';', LDB_TOKENS, (const char **) tokens);
823
+	if(tokens_count < 4) {
825 824
 	    ret = CL_EMALFDB;
826 825
 	    break;
827 826
 	}
828 827
 
828
+	virname = tokens[0];
829
+	logic = tokens[2];
830
+
829 831
 	if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
830 832
 	    if(cli_chkpua(virname, engine->pua_cats, options))
831 833
 		continue;
... ...
@@ -833,11 +831,6 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
833 833
 	if(engine->ignored && cli_chkign(engine->ignored, dbname, line, virname))
834 834
 	    continue;
835 835
 
836
-	if(!(logic = tokens[2])) {
837
-	    ret = CL_EMALFDB;
838
-	    break;
839
-	}
840
-
841 836
 	subsigs = cli_ac_chklsig(logic, logic + strlen(logic), NULL, NULL, NULL, 1);
842 837
 	if(subsigs == -1) {
843 838
 	    ret = CL_EMALFDB;
... ...
@@ -924,7 +917,7 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
924 924
 	root->ac_lsigtable = newtable;
925 925
 
926 926
 	for(i = 0; i < subsigs; i++) {
927
-	    if(!tokens[3 + i]) {
927
+	    if(i >= tokens_count) {
928 928
 		cli_errmsg("cli_loadldb: Missing subsignature id %u\n", i);
929 929
 		ret = CL_EMALFDB;
930 930
 		break;
... ...
@@ -968,12 +961,12 @@ static int cli_loadldb(FILE *fs, struct cl_engine *engine, unsigned int *signo,
968 968
     return CL_SUCCESS;
969 969
 }
970 970
 
971
-#define FTM_TOKENS 8	
971
+#define FTM_TOKENS 8
972 972
 static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options, unsigned int internal, struct cli_dbio *dbio)
973 973
 {
974
-	const char *tokens[FTM_TOKENS], *pt;
974
+	const char *tokens[FTM_TOKENS + 1], *pt;
975 975
 	char buffer[FILEBUFF];
976
-	unsigned int line = 0, sigs = 0;
976
+	unsigned int line = 0, sigs = 0, tokens_count;
977 977
 	struct cli_ftype *new;
978 978
 	cli_file_t rtype, type;
979 979
 	int ret;
... ...
@@ -994,14 +987,15 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
994 994
 	    cli_chomp(buffer);
995 995
 	}
996 996
 	line++;
997
-	cli_strtokenize(buffer, ':', FTM_TOKENS, tokens);
997
+	tokens_count = cli_strtokenize(buffer, ':', FTM_TOKENS + 1, tokens);
998 998
 
999
-	if(!tokens[0] || !tokens[1] || !tokens[2] || !tokens[3] || !tokens[4] || !tokens[5]) {
999
+	if(tokens_count < 6 || tokens_count > 8) {
1000 1000
 	    ret = CL_EMALFDB;
1001 1001
 	    break;
1002 1002
 	}
1003 1003
 
1004
-	if((pt = tokens[6])) { /* min version */
1004
+	if(tokens_count > 6) { /* min version */
1005
+	    pt = tokens[6];
1005 1006
 	    if(!cli_isnumber(pt)) {
1006 1007
 		ret = CL_EMALFDB;
1007 1008
 		break;
... ...
@@ -1010,7 +1004,8 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
1010 1010
 		cli_dbgmsg("cli_loadftm: File type signature for %s not loaded (required f-level: %u)\n", tokens[3], atoi(pt));
1011 1011
 		continue;
1012 1012
 	    }
1013
-	    if((pt = tokens[7])) { /* max version */
1013
+	    if(tokens_count == 8) { /* max version */
1014
+		pt = tokens[7];
1014 1015
 		if(!cli_isnumber(pt)) {
1015 1016
 		    ret = CL_EMALFDB;
1016 1017
 		    break;
... ...
@@ -1081,9 +1076,9 @@ static int cli_loadftm(FILE *fs, struct cl_engine *engine, unsigned int options,
1081 1081
 #define IGN_TOKENS 3
1082 1082
 static int cli_loadign(FILE *fs, struct cl_engine *engine, unsigned int options, struct cli_dbio *dbio)
1083 1083
 {
1084
-	const char *tokens[IGN_TOKENS];
1084
+	const char *tokens[IGN_TOKENS + 1];
1085 1085
 	char buffer[FILEBUFF];
1086
-	unsigned int line = 0;
1086
+	unsigned int line = 0, tokens_count;
1087 1087
 	struct cli_ignsig *new;
1088 1088
 	int ret = CL_SUCCESS;
1089 1089
 
... ...
@@ -1097,7 +1092,11 @@ static int cli_loadign(FILE *fs, struct cl_engine *engine, unsigned int options,
1097 1097
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
1098 1098
 	line++;
1099 1099
 	cli_chomp(buffer);
1100
-	cli_strtokenize(buffer, ':', IGN_TOKENS, tokens);
1100
+	tokens_count = cli_strtokenize(buffer, ':', IGN_TOKENS + 1, tokens);
1101
+	if(tokens_count != IGN_TOKENS) {
1102
+	    ret = CL_EMALFDB;
1103
+	    break;
1104
+	}
1101 1105
 
1102 1106
 	new = (struct cli_ignsig *) mp_calloc(engine->mempool, 1, sizeof(struct cli_ignsig));
1103 1107
 	if(!new) {
... ...
@@ -1204,11 +1203,11 @@ static int cli_md5db_init(struct cl_engine *engine, unsigned int mode)
1204 1204
 #define MD5_TOKENS 3
1205 1205
 static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo, unsigned int mode, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1206 1206
 {
1207
-	const char *tokens[MD5_TOKENS];
1207
+	const char *tokens[MD5_TOKENS + 1];
1208 1208
 	char buffer[FILEBUFF];
1209 1209
 	const char *pt;
1210 1210
 	int ret = CL_SUCCESS;
1211
-	unsigned int size_field = 1, md5_field = 0, line = 0, sigs = 0;
1211
+	unsigned int size_field = 1, md5_field = 0, line = 0, sigs = 0, tokens_count;
1212 1212
 	uint32_t size;
1213 1213
 	struct cli_bm_patt *new;
1214 1214
 	struct cli_matcher *db = NULL;
... ...
@@ -1222,13 +1221,13 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1222 1222
     while(cli_dbgets(buffer, FILEBUFF, fs, dbio)) {
1223 1223
 	line++;
1224 1224
 	cli_chomp(buffer);
1225
-	cli_strtokenize(buffer, ':', MD5_TOKENS, tokens);
1226
-
1227
-	if(!(pt = tokens[2])) { /* virname */
1225
+	tokens_count = cli_strtokenize(buffer, ':', MD5_TOKENS + 1, tokens);
1226
+	if(tokens_count != MD5_TOKENS) {
1228 1227
 	    ret = CL_EMALFDB;
1229 1228
 	    break;
1230 1229
 	}
1231 1230
 
1231
+	pt = tokens[2]; /* virname */
1232 1232
 	if(engine->pua_cats && (options & CL_DB_PUA_MODE) && (options & (CL_DB_PUA_INCLUDE | CL_DB_PUA_EXCLUDE)))
1233 1233
 	    if(cli_chkpua(pt, engine->pua_cats, options))
1234 1234
 		continue;
... ...
@@ -1242,12 +1241,7 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1242 1242
 	    break;
1243 1243
 	}
1244 1244
 
1245
-	if(!(pt = tokens[md5_field])) {
1246
-	    mp_free(engine->mempool, new);
1247
-	    ret = CL_EMALFDB;
1248
-	    break;
1249
-	}
1250
-
1245
+	pt = tokens[md5_field]; /* md5 */
1251 1246
 	if(strlen(pt) != 32 || !(new->pattern = (unsigned char *) cli_mp_hex2str(engine->mempool, pt))) {
1252 1247
 	    cli_errmsg("cli_loadmd5: Malformed MD5 string at line %u\n", line);
1253 1248
 	    mp_free(engine->mempool, new);
... ...
@@ -1256,13 +1250,7 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1256 1256
 	}
1257 1257
 	new->length = 16;
1258 1258
 
1259
-	if(!(pt = tokens[size_field])) {
1260
-	    mp_free(engine->mempool, new->pattern);
1261
-	    mp_free(engine->mempool, new);
1262
-	    ret = CL_EMALFDB;
1263
-	    break;
1264
-	}
1265
-	size = atoi(pt);
1259
+	size = atoi(tokens[size_field]);
1266 1260
 
1267 1261
 	new->virname = cli_mp_virname(engine->mempool, (char *) tokens[2], options & CL_DB_OFFICIAL);
1268 1262
 	if(!new->virname) {
... ...
@@ -1319,9 +1307,9 @@ static int cli_loadmd5(FILE *fs, struct cl_engine *engine, unsigned int *signo,
1319 1319
 #define MD_TOKENS 9
1320 1320
 static int cli_loadmd(FILE *fs, struct cl_engine *engine, unsigned int *signo, int type, unsigned int options, struct cli_dbio *dbio, const char *dbname)
1321 1321
 {
1322
-	const char *tokens[MD_TOKENS];
1322
+	const char *tokens[MD_TOKENS + 1];
1323 1323
 	char buffer[FILEBUFF];
1324
-	unsigned int line = 0, sigs = 0;
1324
+	unsigned int line = 0, sigs = 0, tokens_count;
1325 1325
 	int ret = CL_SUCCESS, crc;
1326 1326
 	struct cli_meta_node *new;
1327 1327
 
... ...
@@ -1332,7 +1320,11 @@ static int cli_loadmd(FILE *fs, struct cl_engine *engine, unsigned int *signo, i
1332 1332
 	    continue;
1333 1333
 
1334 1334
 	cli_chomp(buffer);
1335
-	cli_strtokenize(buffer, ':', MD_TOKENS, tokens);
1335
+	tokens_count = cli_strtokenize(buffer, ':', MD_TOKENS + 1, tokens);
1336
+	if(tokens_count != MD_TOKENS) {
1337
+	    ret = CL_EMALFDB;
1338
+	    break;
1339
+	}
1336 1340
 
1337 1341
 	new = (struct cli_meta_node *) mp_calloc(engine->mempool, 1, sizeof(struct cli_meta_node));
1338 1342
 	if(!new) {
... ...
@@ -429,9 +429,9 @@ const char* cli_strcasestr(const char* a, const char *b)
429 429
 }
430 430
 #endif
431 431
 
432
-void cli_strtokenize(char *buffer, const char delim, const size_t token_count, const char **tokens)
432
+size_t cli_strtokenize(char *buffer, const char delim, const size_t token_count, const char **tokens)
433 433
 {
434
-	size_t tokens_found;
434
+	size_t tokens_found, i;
435 435
 
436 436
 
437 437
     for(tokens_found = 0; tokens_found < token_count; ) {
... ...
@@ -440,12 +440,14 @@ void cli_strtokenize(char *buffer, const char delim, const size_t token_count, c
440 440
 	if(buffer) {
441 441
 	    *buffer++ = '\0';
442 442
 	} else {
443
-	    while(tokens_found < token_count)
444
-		tokens[tokens_found++] = NULL;
443
+	    i = tokens_found;
444
+	    while(i < token_count)
445
+		tokens[i++] = NULL;
445 446
 
446
-	    return;
447
+	    return tokens_found;
447 448
 	}
448 449
     }
450
+    return tokens_found;
449 451
 }
450 452
 
451 453
 int cli_isnumber(const char *str)
... ...
@@ -43,7 +43,7 @@ char *cli_utf16toascii(const char *str, unsigned int length);
43 43
 char *cli_strtokbuf(const char *input, int fieldno, const char *delim, char *output);
44 44
 const char *cli_memstr(const char *haystack, int hs, const char *needle, int ns);
45 45
 char *cli_strrcpy(char *dest, const char *source);
46
-void cli_strtokenize(char *buffer, const char delim, const size_t token_count, const char **tokens);
46
+size_t cli_strtokenize(char *buffer, const char delim, const size_t token_count, const char **tokens);
47 47
 int cli_isnumber(const char *str);
48 48
 char *cli_unescape(const char *str);
49 49
 struct text_buffer;