Browse code

libclamav/matcher-ac.c: implement word delimiter (B) as requested in bb#1631

Tomasz Kojm authored on 2009/09/18 05:49:45
Showing 4 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu Sep 17 22:36:30 CEST 2009 (tk)
2
+----------------------------------
3
+ * libclamav/matcher-ac.c: implement word delimiter (B) as requested in bb#1631
4
+
1 5
 Mon Sep 14 19:52:01 CEST 2009 (tk)
2 6
 ----------------------------------
3 7
  * freshclam: return 0 instead of 1 when database is up-to-date (bb#1312)
... ...
@@ -51,6 +51,30 @@
51 51
 #define AC_SPECIAL_LINE_END	4
52 52
 #define AC_SPECIAL_BOUNDARY	5
53 53
 
54
+#define AC_BOUNDARY_LEFT	    1
55
+#define AC_BOUNDARY_LEFT_NEGATIVE   2
56
+#define AC_BOUNDARY_RIGHT	    4
57
+#define AC_BOUNDARY_RIGHT_NEGATIVE  8
58
+
59
+static char boundary[256] = {
60
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 
61
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
62
+    3, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 3, 
63
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, 
64
+    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
65
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 
66
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
67
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
68
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
69
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
70
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
71
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
72
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
73
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
74
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
75
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
76
+};
77
+
54 78
 int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
55 79
 {
56 80
 	struct cli_ac_node *pt, *next;
... ...
@@ -698,7 +722,7 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne
698 698
 		    break;								\
699 699
 											\
700 700
 		case AC_SPECIAL_BOUNDARY:						\
701
-		    if(memchr("\x22\x27\x20\x2f\x3d\x2d\x5f\x3e\x0a\x0d", b, 10))	\
701
+		    if(boundary[b])							\
702 702
 			match = !special->negative;					\
703 703
 		    break;								\
704 704
 											\
... ...
@@ -724,7 +748,7 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne
724 724
 	    match = 0;									\
725 725
     }
726 726
 
727
-inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
727
+inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
728 728
 {
729 729
 	uint32_t bp, match;
730 730
 	uint16_t wc, i, j, specialcnt = pattern->special_pattern;
... ...
@@ -745,6 +769,22 @@ inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uin
745 745
     }
746 746
     *end = bp;
747 747
 
748
+    if(pattern->boundary & AC_BOUNDARY_LEFT) {
749
+	match = !!(pattern->boundary & AC_BOUNDARY_LEFT_NEGATIVE);
750
+	if(!fileoffset || (offset && (boundary[buffer[offset - 1]] == 1 || boundary[buffer[offset - 1]] == 3)))
751
+	    match = !match;
752
+	if(!match)
753
+	    return 0;
754
+    }
755
+
756
+    if(pattern->boundary & AC_BOUNDARY_RIGHT) {
757
+	match = !!(pattern->boundary & AC_BOUNDARY_RIGHT_NEGATIVE);
758
+	if((length <= SCANBUFF) && (bp == length || boundary[buffer[bp]] >= 2))
759
+	    match = !match;
760
+	if(!match)
761
+	    return 0;
762
+    }
763
+
748 764
     if(!(pattern->ch[1] & CLI_MATCH_IGNORE)) {
749 765
 	bp += pattern->ch_mindist[1];
750 766
 	for(i = pattern->ch_mindist[1]; i <= pattern->ch_maxdist[1]; i++) {
... ...
@@ -1001,7 +1041,7 @@ int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **v
1001 1001
 		    }
1002 1002
 		}
1003 1003
 		pt = patt;
1004
-		if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
1004
+		if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend)) {
1005 1005
 		    while(pt) {
1006 1006
 			if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
1007 1007
 			    pt = pt->next_same;
... ...
@@ -1340,7 +1380,6 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1340 1340
 		}
1341 1341
 	    }
1342 1342
 	    strcat(hexnew, start);
1343
-	    strcat(hexnew, "()");
1344 1343
 
1345 1344
 	    if(!(start = strchr(pt, ')'))) {
1346 1345
 		mpool_free(root->mempool, newspecial);
... ...
@@ -1353,6 +1392,24 @@ int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hex
1353 1353
 		error = CL_EMALFDB;
1354 1354
 		break;
1355 1355
 	    }
1356
+
1357
+	    if(!strcmp(pt, "B")) {
1358
+		if(!*start) {
1359
+		    new->boundary |= AC_BOUNDARY_RIGHT;
1360
+		    if(newspecial->negative)
1361
+			new->boundary |= AC_BOUNDARY_RIGHT_NEGATIVE;
1362
+		    mpool_free(root->mempool, newspecial);
1363
+		    continue;
1364
+		} else if(pt - 1 == hexcpy) {
1365
+		    new->boundary |= AC_BOUNDARY_LEFT;
1366
+		    if(newspecial->negative)
1367
+			new->boundary |= AC_BOUNDARY_LEFT_NEGATIVE;
1368
+		    mpool_free(root->mempool, newspecial);
1369
+		    continue;
1370
+		}
1371
+	    }
1372
+
1373
+	    strcat(hexnew, "()");
1356 1374
 	    new->special++;
1357 1375
 	    newtable = (struct cli_ac_special **) mpool_realloc(root->mempool, new->special_table, new->special * sizeof(struct cli_ac_special *));
1358 1376
 	    if(!newtable) {
... ...
@@ -61,6 +61,7 @@ struct cli_ac_patt {
61 61
     uint8_t depth;
62 62
     uint16_t rtype, type;
63 63
     uint32_t offdata[4], offset_min, offset_max;
64
+    uint32_t boundary;
64 65
 };
65 66
 
66 67
 struct cli_ac_node {
... ...
@@ -50,7 +50,7 @@
50 50
  * in re-enabling affected modules.
51 51
  */
52 52
 
53
-#define CL_FLEVEL 47
53
+#define CL_FLEVEL 48
54 54
 #define CL_FLEVEL_DCONF	CL_FLEVEL
55 55
 
56 56
 extern uint8_t cli_debug_flag;