git-svn: trunk@3985
Török Edvin authored on 2008/07/25 03:48:31... | ... |
@@ -88,8 +88,9 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \ |
88 | 88 |
regerror.lo regexec.lo regfree.lo unarj.lo bzlib.lo nulsft.lo \ |
89 | 89 |
infblock.lo pdf.lo spin.lo yc.lo elf.lo sis.lo uuencode.lo \ |
90 | 90 |
phishcheck.lo phish_domaincheck_db.lo phish_whitelist.lo \ |
91 |
- regex_list.lo mspack.lo cab.lo entconv.lo hashtab.lo dconf.lo \ |
|
92 |
- lzma_iface.lo explode.lo textnorm.lo dlp.lo js-norm.lo |
|
91 |
+ regex_list.lo regex_suffix.lo mspack.lo cab.lo entconv.lo \ |
|
92 |
+ hashtab.lo dconf.lo lzma_iface.lo explode.lo textnorm.lo \ |
|
93 |
+ dlp.lo js-norm.lo |
|
93 | 94 |
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS) |
94 | 95 |
libclamav_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ |
95 | 96 |
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ |
... | ... |
@@ -410,6 +411,8 @@ libclamav_la_SOURCES = \ |
410 | 410 |
iana_tld.h \ |
411 | 411 |
regex_list.c \ |
412 | 412 |
regex_list.h \ |
413 |
+ regex_suffix.c \ |
|
414 |
+ regex_suffix.h \ |
|
413 | 415 |
mspack.c \ |
414 | 416 |
mspack.h \ |
415 | 417 |
cab.c \ |
... | ... |
@@ -582,6 +585,7 @@ distclean-compile: |
582 | 582 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regcomp.Plo@am__quote@ |
583 | 583 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regerror.Plo@am__quote@ |
584 | 584 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_list.Plo@am__quote@ |
585 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_suffix.Plo@am__quote@ |
|
585 | 586 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexec.Plo@am__quote@ |
586 | 587 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regfree.Plo@am__quote@ |
587 | 588 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtf.Plo@am__quote@ |
... | ... |
@@ -56,380 +56,14 @@ |
56 | 56 |
#include "str.h" |
57 | 57 |
#include "readdb.h" |
58 | 58 |
#include "jsparse/textbuf.h" |
59 |
- |
|
60 |
-/* ------- parse a regular expression, and extract a static suffix ------*/ |
|
61 |
-enum node_type { |
|
62 |
- root=0, |
|
63 |
- concat, |
|
64 |
- alternate, /* | */ |
|
65 |
- optional,/* ?, * */ |
|
66 |
- leaf, /* a character */ |
|
67 |
- leaf_class /* character class */ |
|
68 |
- /* (x)+ is transformed into (x)*(x) */ |
|
69 |
-}; |
|
70 |
- |
|
71 |
-struct node { |
|
72 |
- enum node_type type; |
|
73 |
- struct node *parent; |
|
74 |
- union { |
|
75 |
- struct { |
|
76 |
- struct node* left; |
|
77 |
- struct node* right; |
|
78 |
- } children; |
|
79 |
- uint8_t* leaf_class_bitmap; |
|
80 |
- uint8_t leaf_char; |
|
81 |
- } u; |
|
82 |
-}; |
|
83 |
- |
|
59 |
+#include "regex_suffix.h" |
|
84 | 60 |
/* Prototypes */ |
85 | 61 |
static size_t reverse_string(char *pattern); |
86 | 62 |
static int add_pattern(struct regex_matcher *matcher, char *pattern); |
87 |
-static int add_pattern_suffix(struct regex_matcher *matcher, char *suffix, size_t suffix_len, struct regex_list *regex); |
|
63 |
+static int add_pattern_suffix(void *cbdata, const char *suffix, size_t suffix_len, struct regex_list *regex); |
|
88 | 64 |
static int add_static_pattern(struct regex_matcher *matcher, char* pattern); |
89 |
-static int build_suffixtree_descend(struct regex_matcher *matcher, struct regex_list *regex, struct node *n, struct text_buffer *buf); |
|
90 | 65 |
/* ---------- */ |
91 | 66 |
|
92 |
-static uint8_t dot_bitmap[32]; |
|
93 |
- |
|
94 |
-static struct node* make_node(enum node_type type, struct node *left, struct node *right) |
|
95 |
-{ |
|
96 |
- struct node *n; |
|
97 |
- if(type == concat) { |
|
98 |
- if(left == NULL) |
|
99 |
- return right; |
|
100 |
- if(right == NULL) |
|
101 |
- return left; |
|
102 |
- } |
|
103 |
- n = cli_malloc(sizeof(*n)); |
|
104 |
- if(!n) |
|
105 |
- return NULL; |
|
106 |
- n->type = type; |
|
107 |
- n->parent = NULL; |
|
108 |
- n->u.children.left = left; |
|
109 |
- n->u.children.right = right; |
|
110 |
- if(left) |
|
111 |
- left->parent = n; |
|
112 |
- if(right) |
|
113 |
- right->parent = n; |
|
114 |
- return n; |
|
115 |
-} |
|
116 |
- |
|
117 |
-static struct node *dup_node(struct node *p) |
|
118 |
-{ |
|
119 |
- struct node *node_left, *node_right; |
|
120 |
- struct node *d; |
|
121 |
- |
|
122 |
- if(!p) |
|
123 |
- return NULL; |
|
124 |
- d = cli_malloc(sizeof(*d)); |
|
125 |
- if(!d) |
|
126 |
- return NULL; |
|
127 |
- d->type = p->type; |
|
128 |
- d->parent = NULL; |
|
129 |
- switch(p->type) { |
|
130 |
- case leaf: |
|
131 |
- d->u.leaf_char = p->u.leaf_char; |
|
132 |
- break; |
|
133 |
- case leaf_class: |
|
134 |
- d->u.leaf_class_bitmap = cli_malloc(32); |
|
135 |
- if(!d->u.leaf_class_bitmap) |
|
136 |
- return NULL; |
|
137 |
- memcpy(d->u.leaf_class_bitmap, p->u.leaf_class_bitmap, 32); |
|
138 |
- break; |
|
139 |
- default: |
|
140 |
- node_left = dup_node(p->u.children.left); |
|
141 |
- node_right = dup_node(p->u.children.right); |
|
142 |
- d->u.children.left = node_left; |
|
143 |
- d->u.children.right = node_right; |
|
144 |
- if(node_left) |
|
145 |
- node_left->parent = d; |
|
146 |
- if(node_right) |
|
147 |
- node_right->parent = d; |
|
148 |
- break; |
|
149 |
- } |
|
150 |
- return d; |
|
151 |
-} |
|
152 |
- |
|
153 |
-static struct node *make_charclass(uint8_t *bitmap) |
|
154 |
-{ |
|
155 |
- struct node *v = cli_malloc(sizeof(*v)); |
|
156 |
- if(!v) |
|
157 |
- return NULL; |
|
158 |
- v->type = leaf_class; |
|
159 |
- v->parent = NULL; |
|
160 |
- v->u.leaf_class_bitmap = bitmap; |
|
161 |
- return v; |
|
162 |
-} |
|
163 |
- |
|
164 |
-static struct node *make_leaf(char c) |
|
165 |
-{ |
|
166 |
- struct node *v = cli_malloc(sizeof(*v)); |
|
167 |
- if(!v) |
|
168 |
- return NULL; |
|
169 |
- v->type = leaf; |
|
170 |
- v->parent = NULL; |
|
171 |
- v->u.leaf_char = c; |
|
172 |
- return v; |
|
173 |
-} |
|
174 |
- |
|
175 |
-static void destroy_tree(struct node *n) |
|
176 |
-{ |
|
177 |
- if(!n) |
|
178 |
- return; |
|
179 |
- switch(n->type) { |
|
180 |
- case concat: |
|
181 |
- case alternate: |
|
182 |
- case optional: |
|
183 |
- destroy_tree(n->u.children.left); |
|
184 |
- destroy_tree(n->u.children.right); |
|
185 |
- break; |
|
186 |
- case leaf_class: |
|
187 |
- if(n->u.leaf_class_bitmap != dot_bitmap) |
|
188 |
- free(n->u.leaf_class_bitmap); |
|
189 |
- break; |
|
190 |
- case root: |
|
191 |
- case leaf: |
|
192 |
- break; |
|
193 |
- } |
|
194 |
- free(n); |
|
195 |
-} |
|
196 |
- |
|
197 |
-static uint8_t* parse_char_class(const char *pat, size_t *pos) |
|
198 |
-{ |
|
199 |
- unsigned char range_start=0; |
|
200 |
- int hasprev = 0; |
|
201 |
- uint8_t* bitmap = cli_malloc(32); |
|
202 |
- if(!bitmap) |
|
203 |
- return NULL; |
|
204 |
- if (pat[*pos]=='^') { |
|
205 |
- memset(bitmap,0xFF,32);/*match chars not in brackets*/ |
|
206 |
- ++*pos; |
|
207 |
- } |
|
208 |
- else |
|
209 |
- memset(bitmap,0x00,32); |
|
210 |
- do { |
|
211 |
- /* literal ] can be first character, so test for it at the end of the loop, for example: []] */ |
|
212 |
- if (pat[*pos]=='-' && hasprev) { |
|
213 |
- /* it is a range*/ |
|
214 |
- unsigned char range_end; |
|
215 |
- unsigned int c; |
|
216 |
- assert(range_start); |
|
217 |
- ++*pos; |
|
218 |
- if (pat[*pos]=='[') |
|
219 |
- if (pat[*pos+1]=='.') { |
|
220 |
- /* collating sequence not handled */ |
|
221 |
- free(bitmap); |
|
222 |
- /* we are parsing the regex for a |
|
223 |
- * filter, be conservative and |
|
224 |
- * tell the filter that anything could |
|
225 |
- * match here */ |
|
226 |
- while(pat[*pos] != ']') ++*pos; |
|
227 |
- ++*pos; |
|
228 |
- while(pat[*pos] != ']') ++*pos; |
|
229 |
- return dot_bitmap; |
|
230 |
- } |
|
231 |
- else |
|
232 |
- range_end = pat[*pos]; |
|
233 |
- else |
|
234 |
- range_end = pat[*pos]; |
|
235 |
- for(c=range_start+1;c<=range_end;c++) |
|
236 |
- bitmap[c>>3] ^= 1<<(c&0x7); |
|
237 |
- hasprev = 0; |
|
238 |
- } |
|
239 |
- else if (pat[*pos]=='[' && pat[*pos]==':') { |
|
240 |
- /* char class */ |
|
241 |
- free(bitmap); |
|
242 |
- while(pat[*pos] != ']') ++*pos; |
|
243 |
- ++*pos; |
|
244 |
- while(pat[*pos] != ']') ++*pos; |
|
245 |
- return dot_bitmap; |
|
246 |
- } else { |
|
247 |
- bitmap[pat[*pos]>>3] ^= 1<<(pat[*pos]&0x7); |
|
248 |
- ++*pos; |
|
249 |
- range_start = pat[*pos]; |
|
250 |
- hasprev = 1; |
|
251 |
- } |
|
252 |
- } while(pat[*pos]!=']'); |
|
253 |
- return bitmap; |
|
254 |
-} |
|
255 |
- |
|
256 |
-static struct node* parse_regex(const char *p, size_t *last) |
|
257 |
-{ |
|
258 |
- struct node *v = NULL; |
|
259 |
- struct node *right; |
|
260 |
- struct node *tmp; |
|
261 |
- |
|
262 |
- while(p[*last] != '$' && p[*last] != '\0') { |
|
263 |
- switch(p[*last]) { |
|
264 |
- case '|': |
|
265 |
- ++*last; |
|
266 |
- right = parse_regex(p, last); |
|
267 |
- v = make_node(alternate, v, right); |
|
268 |
- if(!v) |
|
269 |
- return NULL; |
|
270 |
- break; |
|
271 |
- case '*': |
|
272 |
- case '?': |
|
273 |
- v = make_node(optional, v, NULL); |
|
274 |
- if(!v) |
|
275 |
- return NULL; |
|
276 |
- ++*last; |
|
277 |
- break; |
|
278 |
- case '+': |
|
279 |
- /* (x)* */ |
|
280 |
- tmp = make_node(optional, v, NULL); |
|
281 |
- if(!tmp) |
|
282 |
- return NULL; |
|
283 |
- /* (x) */ |
|
284 |
- right = dup_node(v); |
|
285 |
- if(!right) |
|
286 |
- return NULL; |
|
287 |
- /* (x)*(x) => (x)+ */ |
|
288 |
- v = make_node(concat, tmp, right); |
|
289 |
- if(!v) |
|
290 |
- return NULL; |
|
291 |
- ++*last; |
|
292 |
- break; |
|
293 |
- case '(': |
|
294 |
- ++*last; |
|
295 |
- right = parse_regex(p, last); |
|
296 |
- if(!right) |
|
297 |
- return NULL; |
|
298 |
- ++*last; |
|
299 |
- v = make_node(concat, v, right); |
|
300 |
- break; |
|
301 |
- case ')': |
|
302 |
- return v; |
|
303 |
- case '.': |
|
304 |
- right = make_charclass(dot_bitmap); |
|
305 |
- if(!right) |
|
306 |
- return NULL; |
|
307 |
- v = make_node(concat, v, right); |
|
308 |
- if(!v) |
|
309 |
- return NULL; |
|
310 |
- ++*last; |
|
311 |
- break; |
|
312 |
- case '[': |
|
313 |
- right = make_charclass( parse_char_class(p, last) ); |
|
314 |
- if(!right) |
|
315 |
- return NULL; |
|
316 |
- v = make_node(concat, v, right); |
|
317 |
- if(!v) |
|
318 |
- return NULL; |
|
319 |
- case '\\': |
|
320 |
- /* next char is escaped, advance pointer |
|
321 |
- * and let fall-through handle it */ |
|
322 |
- ++*last; |
|
323 |
- default: |
|
324 |
- right = make_leaf(p[*last]); |
|
325 |
- v = make_node(concat, v, right); |
|
326 |
- if(!v) |
|
327 |
- return NULL; |
|
328 |
- ++*last; |
|
329 |
- break; |
|
330 |
- } |
|
331 |
- } |
|
332 |
- return v; |
|
333 |
-} |
|
334 |
- |
|
335 |
-#define BITMAP_HASSET(b, i) (b[i>>3] & (1<<(i&7))) |
|
336 |
- |
|
337 |
-static int build_suffixtree_ascend(struct regex_matcher *matcher, struct regex_list *regex, struct node *n, struct text_buffer *buf, struct node *prev) |
|
338 |
-{ |
|
339 |
- size_t i; |
|
340 |
- while(n) { |
|
341 |
- struct node *q = n; |
|
342 |
- switch(n->type) { |
|
343 |
- case root: |
|
344 |
- textbuffer_putc(buf, '\0'); |
|
345 |
- if(add_pattern_suffix(matcher, buf->data, buf->pos, regex) < 0) |
|
346 |
- return CL_EMEM; |
|
347 |
- return 0; |
|
348 |
- case leaf: |
|
349 |
- textbuffer_putc(buf, n->u.leaf_char); |
|
350 |
- n = n->parent; |
|
351 |
- break; |
|
352 |
- case leaf_class: |
|
353 |
- if(memcmp(n->u.leaf_class_bitmap, dot_bitmap, sizeof(dot_bitmap)) == 0) { |
|
354 |
- textbuffer_putc(buf, '\0'); |
|
355 |
- if(add_pattern_suffix(matcher, buf->data, buf->pos, regex) < 0) |
|
356 |
- return CL_EMEM; |
|
357 |
- return 0; |
|
358 |
- } |
|
359 |
- for(i=0;i<255;i++) { |
|
360 |
- if(BITMAP_HASSET(n->u.leaf_class_bitmap, i)) { |
|
361 |
- size_t pos; |
|
362 |
- pos = buf->pos; |
|
363 |
- textbuffer_putc(buf, i); |
|
364 |
- if(build_suffixtree_ascend(matcher, regex, n->parent, buf, n) < 0) |
|
365 |
- return CL_EMEM; |
|
366 |
- buf->pos = pos; |
|
367 |
- } |
|
368 |
- } |
|
369 |
- return 0; |
|
370 |
- case concat: |
|
371 |
- if(prev != n->u.children.left) { |
|
372 |
- if(build_suffixtree_descend(matcher, regex, n->u.children.left, buf) < 0) |
|
373 |
- return CL_EMEM; |
|
374 |
- /* we're done here, descend will call |
|
375 |
- * ascend if needed */ |
|
376 |
- return 0; |
|
377 |
- } else { |
|
378 |
- n = n->parent; |
|
379 |
- } |
|
380 |
- break; |
|
381 |
- case alternate: |
|
382 |
- n = n->parent; |
|
383 |
- break; |
|
384 |
- case optional: |
|
385 |
- textbuffer_putc(buf, '\0'); |
|
386 |
- if(add_pattern_suffix(matcher, buf->data, buf->pos, regex) < 0) |
|
387 |
- return CL_EMEM; |
|
388 |
- return 0; |
|
389 |
- } |
|
390 |
- prev = q; |
|
391 |
- } |
|
392 |
- return 0; |
|
393 |
-} |
|
394 |
- |
|
395 |
-static int build_suffixtree_descend(struct regex_matcher *matcher, struct regex_list *regex, struct node *n, struct text_buffer *buf) |
|
396 |
-{ |
|
397 |
- size_t pos; |
|
398 |
- while(n && n->type == concat) { |
|
399 |
- n = n->u.children.right; |
|
400 |
- } |
|
401 |
- if(!n) |
|
402 |
- return 0; |
|
403 |
- /* find out end of the regular expression, |
|
404 |
- * if it ends with a static pattern */ |
|
405 |
- switch(n->type) { |
|
406 |
- case alternate: |
|
407 |
- /* save pos as restart point */ |
|
408 |
- pos = buf->pos; |
|
409 |
- if(build_suffixtree_descend(matcher, regex, n->u.children.left, buf) < 0) |
|
410 |
- return CL_EMEM; |
|
411 |
- buf->pos = pos; |
|
412 |
- if(build_suffixtree_descend(matcher, regex, n->u.children.right, buf) < 0) |
|
413 |
- return CL_EMEM; |
|
414 |
- buf->pos = pos; |
|
415 |
- break; |
|
416 |
- case optional: |
|
417 |
- textbuffer_putc(buf, '\0'); |
|
418 |
- if(add_pattern_suffix(matcher, buf->data, buf->pos, regex) < 0) |
|
419 |
- return CL_EMEM; |
|
420 |
- return 0; |
|
421 |
- case leaf: |
|
422 |
- case leaf_class: |
|
423 |
- if(build_suffixtree_ascend(matcher, regex, n, buf, NULL) < 0) |
|
424 |
- return CL_EMEM; |
|
425 |
- return 0; |
|
426 |
- default: |
|
427 |
- break; |
|
428 |
- } |
|
429 |
- return 0; |
|
430 |
-} |
|
431 |
- |
|
432 |
- |
|
433 | 67 |
/* ----- shift-or filtering -------------- */ |
434 | 68 |
|
435 | 69 |
#define BITMAP_CONTAINS(bmap, val) ((bmap)[(val) >> 5] & (1 << ((val) & 0x1f))) |
... | ... |
@@ -557,7 +191,6 @@ static inline size_t get_char_at_pos_with_skip(const struct pre_fixup_info* info |
557 | 557 |
static int validate_subdomain(const struct regex_list *regex, const struct pre_fixup_info *pre_fixup, const char *buffer, size_t buffer_len, char *real_url, size_t real_len, char *orig_real_url) |
558 | 558 |
{ |
559 | 559 |
char c; |
560 |
- const char *matched; |
|
561 | 560 |
size_t match_len; |
562 | 561 |
|
563 | 562 |
if(!regex || !regex->pattern) |
... | ... |
@@ -626,7 +259,6 @@ int regex_list_match(struct regex_matcher* matcher,char* real_url,const char* di |
626 | 626 |
size_t buffer_len = (hostOnly && !is_whitelist) ? real_len + 1 : real_len + display_len + 1 + 1; |
627 | 627 |
char *buffer = cli_malloc(buffer_len+1); |
628 | 628 |
char *bufrev; |
629 |
- size_t i; |
|
630 | 629 |
int rc = 0; |
631 | 630 |
struct cli_ac_data mdata; |
632 | 631 |
|
... | ... |
@@ -662,7 +294,7 @@ int regex_list_match(struct regex_matcher* matcher,char* real_url,const char* di |
662 | 662 |
|
663 | 663 |
if(rc) { |
664 | 664 |
/* TODO loop over multiple virusnames here */ |
665 |
- regex = (struct regex_list*)vinfo; |
|
665 |
+ regex = (const struct regex_list*)vinfo; |
|
666 | 666 |
do { |
667 | 667 |
/* loop over multiple regexes corresponding to |
668 | 668 |
* this suffix */ |
... | ... |
@@ -903,7 +535,7 @@ int is_regex_ok(struct regex_matcher* matcher) |
903 | 903 |
return (!matcher->list_inited || matcher->list_inited!=-1);/* either we don't have a regexlist, or we initialized it successfully */ |
904 | 904 |
} |
905 | 905 |
|
906 |
-static int add_newsuffix(struct regex_matcher *matcher, struct regex_list *info, char *suffix, size_t len) |
|
906 |
+static int add_newsuffix(struct regex_matcher *matcher, struct regex_list *info, const char *suffix, size_t len) |
|
907 | 907 |
{ |
908 | 908 |
struct cli_matcher *root = &matcher->suffixes; |
909 | 909 |
struct cli_ac_patt *new = cli_calloc(1,sizeof(*new)); |
... | ... |
@@ -951,8 +583,9 @@ static int add_newsuffix(struct regex_matcher *matcher, struct regex_list *info, |
951 | 951 |
/* ------ load a regex, determine suffix, determine suffix2regexlist map ---- */ |
952 | 952 |
|
953 | 953 |
/* returns 0 on success, clamav error code otherwise */ |
954 |
-static int add_pattern_suffix(struct regex_matcher *matcher, char *suffix, size_t suffix_len, struct regex_list *regex) |
|
954 |
+static int add_pattern_suffix(void *cbdata, const char *suffix, size_t suffix_len, struct regex_list *regex) |
|
955 | 955 |
{ |
956 |
+ struct regex_matcher *matcher = cbdata; |
|
956 | 957 |
const struct element *el; |
957 | 958 |
|
958 | 959 |
assert(matcher); |
... | ... |
@@ -1006,12 +639,8 @@ static int add_static_pattern(struct regex_matcher *matcher, char* pattern) |
1006 | 1006 |
|
1007 | 1007 |
static int add_pattern(struct regex_matcher *matcher, char *pattern) |
1008 | 1008 |
{ |
1009 |
- struct text_buffer buf; |
|
1010 |
- struct node *n; |
|
1011 |
- size_t last=0; |
|
1012 | 1009 |
int rc; |
1013 | 1010 |
struct regex_list *regex = cli_malloc(sizeof(*regex)); |
1014 |
- struct node root_node; |
|
1015 | 1011 |
size_t len; |
1016 | 1012 |
/* we only match the host, so remove useless stuff */ |
1017 | 1013 |
const char remove_end[] = "([/?].*)?/"; |
... | ... |
@@ -1032,32 +661,11 @@ static int add_pattern(struct regex_matcher *matcher, char *pattern) |
1032 | 1032 |
} |
1033 | 1033 |
pattern[len] = '\0'; |
1034 | 1034 |
|
1035 |
- |
|
1036 |
- rc = cli_regcomp(®ex->preg, pattern, REG_EXTENDED); |
|
1035 |
+ rc = cli_regex2suffix(pattern, regex, add_pattern_suffix, matcher); |
|
1037 | 1036 |
if(rc) { |
1038 |
- size_t buflen = cli_regerror(rc, ®ex->preg, NULL, 0); |
|
1039 |
- char *errbuf = cli_malloc(buflen); |
|
1040 |
- if(errbuf) { |
|
1041 |
- cli_regerror(rc, ®ex->preg, errbuf, buflen); |
|
1042 |
- cli_errmsg(MODULE "Error compiling regular expression %s: %s\n", pattern, errbuf); |
|
1043 |
- free(errbuf); |
|
1044 |
- } else { |
|
1045 |
- cli_errmsg(MODULE "Error compiling regular expression: %s\n", pattern); |
|
1046 |
- } |
|
1047 |
- return rc; |
|
1048 | 1037 |
cli_regfree(®ex->preg); |
1049 | 1038 |
free(regex); |
1050 |
- return CL_EMALFDB; |
|
1051 | 1039 |
} |
1052 |
- regex->pattern = cli_strdup(pattern); |
|
1053 |
- regex->nxt = NULL; |
|
1054 |
- |
|
1055 |
- n = parse_regex(pattern, &last); |
|
1056 |
- memset(&buf, 0, sizeof(buf)); |
|
1057 |
- memset(&root_node, 0, sizeof(buf)); |
|
1058 |
- n->parent = &root_node; |
|
1059 | 1040 |
|
1060 |
- rc = build_suffixtree_descend(matcher, regex, n, &buf); |
|
1061 |
- destroy_tree(n); |
|
1062 | 1041 |
return rc; |
1063 | 1042 |
} |
41 | 35 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,448 @@ |
0 |
+/* |
|
1 |
+ * Parse a regular expression, and extract a static suffix. |
|
2 |
+ * |
|
3 |
+ * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
4 |
+ * |
|
5 |
+ * Authors: Török Edvin |
|
6 |
+ * |
|
7 |
+ * This program is free software; you can redistribute it and/or modify |
|
8 |
+ * it under the terms of the GNU General Public License version 2 as |
|
9 |
+ * published by the Free Software Foundation. |
|
10 |
+ * |
|
11 |
+ * This program is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
+ * GNU General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU General Public License |
|
17 |
+ * along with this program; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
+ * MA 02110-1301, USA. |
|
20 |
+ */ |
|
21 |
+#if HAVE_CONFIG_H |
|
22 |
+#include "clamav-config.h" |
|
23 |
+#endif |
|
24 |
+ |
|
25 |
+#ifndef CL_DEBUG |
|
26 |
+#define NDEBUG |
|
27 |
+#endif |
|
28 |
+ |
|
29 |
+#include <stdio.h> |
|
30 |
+#include <stdlib.h> |
|
31 |
+#include <string.h> |
|
32 |
+#include <assert.h> |
|
33 |
+ |
|
34 |
+#include "others.h" |
|
35 |
+#include "jsparse/textbuf.h" |
|
36 |
+#include "regex_suffix.h" |
|
37 |
+#define MODULE "regex_suffix: " |
|
38 |
+ |
|
39 |
+ |
|
40 |
+enum node_type { |
|
41 |
+ root=0, |
|
42 |
+ concat, |
|
43 |
+ alternate, /* | */ |
|
44 |
+ optional,/* ?, * */ |
|
45 |
+ leaf, /* a character */ |
|
46 |
+ leaf_class /* character class */ |
|
47 |
+ /* (x)+ is transformed into (x)*(x) */ |
|
48 |
+}; |
|
49 |
+ |
|
50 |
+struct node { |
|
51 |
+ enum node_type type; |
|
52 |
+ struct node *parent; |
|
53 |
+ union { |
|
54 |
+ struct { |
|
55 |
+ struct node* left; |
|
56 |
+ struct node* right; |
|
57 |
+ } children; |
|
58 |
+ uint8_t* leaf_class_bitmap; |
|
59 |
+ uint8_t leaf_char; |
|
60 |
+ } u; |
|
61 |
+}; |
|
62 |
+ |
|
63 |
+/* --- Prototypes --*/ |
|
64 |
+static int build_suffixtree_descend(struct node *n, struct text_buffer *buf, suffix_callback cb, void *cbdata, struct regex_list *regex); |
|
65 |
+/* -----------------*/ |
|
66 |
+ |
|
67 |
+static uint8_t dot_bitmap[32]; |
|
68 |
+ |
|
69 |
+static struct node* make_node(enum node_type type, struct node *left, struct node *right) |
|
70 |
+{ |
|
71 |
+ struct node *n; |
|
72 |
+ if(type == concat) { |
|
73 |
+ if(left == NULL) |
|
74 |
+ return right; |
|
75 |
+ if(right == NULL) |
|
76 |
+ return left; |
|
77 |
+ } |
|
78 |
+ n = cli_malloc(sizeof(*n)); |
|
79 |
+ if(!n) |
|
80 |
+ return NULL; |
|
81 |
+ n->type = type; |
|
82 |
+ n->parent = NULL; |
|
83 |
+ n->u.children.left = left; |
|
84 |
+ n->u.children.right = right; |
|
85 |
+ if(left) |
|
86 |
+ left->parent = n; |
|
87 |
+ if(right) |
|
88 |
+ right->parent = n; |
|
89 |
+ return n; |
|
90 |
+} |
|
91 |
+ |
|
92 |
+static struct node *dup_node(struct node *p) |
|
93 |
+{ |
|
94 |
+ struct node *node_left, *node_right; |
|
95 |
+ struct node *d; |
|
96 |
+ |
|
97 |
+ if(!p) |
|
98 |
+ return NULL; |
|
99 |
+ d = cli_malloc(sizeof(*d)); |
|
100 |
+ if(!d) |
|
101 |
+ return NULL; |
|
102 |
+ d->type = p->type; |
|
103 |
+ d->parent = NULL; |
|
104 |
+ switch(p->type) { |
|
105 |
+ case leaf: |
|
106 |
+ d->u.leaf_char = p->u.leaf_char; |
|
107 |
+ break; |
|
108 |
+ case leaf_class: |
|
109 |
+ d->u.leaf_class_bitmap = cli_malloc(32); |
|
110 |
+ if(!d->u.leaf_class_bitmap) |
|
111 |
+ return NULL; |
|
112 |
+ memcpy(d->u.leaf_class_bitmap, p->u.leaf_class_bitmap, 32); |
|
113 |
+ break; |
|
114 |
+ default: |
|
115 |
+ node_left = dup_node(p->u.children.left); |
|
116 |
+ node_right = dup_node(p->u.children.right); |
|
117 |
+ d->u.children.left = node_left; |
|
118 |
+ d->u.children.right = node_right; |
|
119 |
+ if(node_left) |
|
120 |
+ node_left->parent = d; |
|
121 |
+ if(node_right) |
|
122 |
+ node_right->parent = d; |
|
123 |
+ break; |
|
124 |
+ } |
|
125 |
+ return d; |
|
126 |
+} |
|
127 |
+ |
|
128 |
+static struct node *make_charclass(uint8_t *bitmap) |
|
129 |
+{ |
|
130 |
+ struct node *v = cli_malloc(sizeof(*v)); |
|
131 |
+ if(!v) |
|
132 |
+ return NULL; |
|
133 |
+ v->type = leaf_class; |
|
134 |
+ v->parent = NULL; |
|
135 |
+ v->u.leaf_class_bitmap = bitmap; |
|
136 |
+ return v; |
|
137 |
+} |
|
138 |
+ |
|
139 |
+static struct node *make_leaf(char c) |
|
140 |
+{ |
|
141 |
+ struct node *v = cli_malloc(sizeof(*v)); |
|
142 |
+ if(!v) |
|
143 |
+ return NULL; |
|
144 |
+ v->type = leaf; |
|
145 |
+ v->parent = NULL; |
|
146 |
+ v->u.leaf_char = c; |
|
147 |
+ return v; |
|
148 |
+} |
|
149 |
+ |
|
150 |
+static void destroy_tree(struct node *n) |
|
151 |
+{ |
|
152 |
+ if(!n) |
|
153 |
+ return; |
|
154 |
+ switch(n->type) { |
|
155 |
+ case concat: |
|
156 |
+ case alternate: |
|
157 |
+ case optional: |
|
158 |
+ destroy_tree(n->u.children.left); |
|
159 |
+ destroy_tree(n->u.children.right); |
|
160 |
+ break; |
|
161 |
+ case leaf_class: |
|
162 |
+ if(n->u.leaf_class_bitmap != dot_bitmap) |
|
163 |
+ free(n->u.leaf_class_bitmap); |
|
164 |
+ break; |
|
165 |
+ case root: |
|
166 |
+ case leaf: |
|
167 |
+ break; |
|
168 |
+ } |
|
169 |
+ free(n); |
|
170 |
+} |
|
171 |
+ |
|
172 |
+static uint8_t* parse_char_class(const char *pat, size_t *pos) |
|
173 |
+{ |
|
174 |
+ unsigned char range_start=0; |
|
175 |
+ int hasprev = 0; |
|
176 |
+ uint8_t* bitmap = cli_malloc(32); |
|
177 |
+ if(!bitmap) |
|
178 |
+ return NULL; |
|
179 |
+ if (pat[*pos]=='^') { |
|
180 |
+ memset(bitmap,0xFF,32);/*match chars not in brackets*/ |
|
181 |
+ ++*pos; |
|
182 |
+ } |
|
183 |
+ else |
|
184 |
+ memset(bitmap,0x00,32); |
|
185 |
+ do { |
|
186 |
+ /* literal ] can be first character, so test for it at the end of the loop, for example: []] */ |
|
187 |
+ if (pat[*pos]=='-' && hasprev) { |
|
188 |
+ /* it is a range*/ |
|
189 |
+ unsigned char range_end; |
|
190 |
+ unsigned int c; |
|
191 |
+ assert(range_start); |
|
192 |
+ ++*pos; |
|
193 |
+ if (pat[*pos]=='[') |
|
194 |
+ if (pat[*pos+1]=='.') { |
|
195 |
+ /* collating sequence not handled */ |
|
196 |
+ free(bitmap); |
|
197 |
+ /* we are parsing the regex for a |
|
198 |
+ * filter, be conservative and |
|
199 |
+ * tell the filter that anything could |
|
200 |
+ * match here */ |
|
201 |
+ while(pat[*pos] != ']') ++*pos; |
|
202 |
+ ++*pos; |
|
203 |
+ while(pat[*pos] != ']') ++*pos; |
|
204 |
+ return dot_bitmap; |
|
205 |
+ } |
|
206 |
+ else |
|
207 |
+ range_end = pat[*pos]; |
|
208 |
+ else |
|
209 |
+ range_end = pat[*pos]; |
|
210 |
+ for(c=range_start+1;c<=range_end;c++) |
|
211 |
+ bitmap[c>>3] ^= 1<<(c&0x7); |
|
212 |
+ hasprev = 0; |
|
213 |
+ } |
|
214 |
+ else if (pat[*pos]=='[' && pat[*pos]==':') { |
|
215 |
+ /* char class */ |
|
216 |
+ free(bitmap); |
|
217 |
+ while(pat[*pos] != ']') ++*pos; |
|
218 |
+ ++*pos; |
|
219 |
+ while(pat[*pos] != ']') ++*pos; |
|
220 |
+ return dot_bitmap; |
|
221 |
+ } else { |
|
222 |
+ bitmap[pat[*pos]>>3] ^= 1<<(pat[*pos]&0x7); |
|
223 |
+ ++*pos; |
|
224 |
+ range_start = pat[*pos]; |
|
225 |
+ hasprev = 1; |
|
226 |
+ } |
|
227 |
+ } while(pat[*pos]!=']'); |
|
228 |
+ return bitmap; |
|
229 |
+} |
|
230 |
+ |
|
231 |
+static struct node* parse_regex(const char *p, size_t *last) |
|
232 |
+{ |
|
233 |
+ struct node *v = NULL; |
|
234 |
+ struct node *right; |
|
235 |
+ struct node *tmp; |
|
236 |
+ |
|
237 |
+ while(p[*last] != '$' && p[*last] != '\0') { |
|
238 |
+ switch(p[*last]) { |
|
239 |
+ case '|': |
|
240 |
+ ++*last; |
|
241 |
+ right = parse_regex(p, last); |
|
242 |
+ v = make_node(alternate, v, right); |
|
243 |
+ if(!v) |
|
244 |
+ return NULL; |
|
245 |
+ break; |
|
246 |
+ case '*': |
|
247 |
+ case '?': |
|
248 |
+ v = make_node(optional, v, NULL); |
|
249 |
+ if(!v) |
|
250 |
+ return NULL; |
|
251 |
+ ++*last; |
|
252 |
+ break; |
|
253 |
+ case '+': |
|
254 |
+ /* (x)* */ |
|
255 |
+ tmp = make_node(optional, v, NULL); |
|
256 |
+ if(!tmp) |
|
257 |
+ return NULL; |
|
258 |
+ /* (x) */ |
|
259 |
+ right = dup_node(v); |
|
260 |
+ if(!right) |
|
261 |
+ return NULL; |
|
262 |
+ /* (x)*(x) => (x)+ */ |
|
263 |
+ v = make_node(concat, tmp, right); |
|
264 |
+ if(!v) |
|
265 |
+ return NULL; |
|
266 |
+ ++*last; |
|
267 |
+ break; |
|
268 |
+ case '(': |
|
269 |
+ ++*last; |
|
270 |
+ right = parse_regex(p, last); |
|
271 |
+ if(!right) |
|
272 |
+ return NULL; |
|
273 |
+ ++*last; |
|
274 |
+ v = make_node(concat, v, right); |
|
275 |
+ break; |
|
276 |
+ case ')': |
|
277 |
+ return v; |
|
278 |
+ case '.': |
|
279 |
+ right = make_charclass(dot_bitmap); |
|
280 |
+ if(!right) |
|
281 |
+ return NULL; |
|
282 |
+ v = make_node(concat, v, right); |
|
283 |
+ if(!v) |
|
284 |
+ return NULL; |
|
285 |
+ ++*last; |
|
286 |
+ break; |
|
287 |
+ case '[': |
|
288 |
+ right = make_charclass( parse_char_class(p, last) ); |
|
289 |
+ if(!right) |
|
290 |
+ return NULL; |
|
291 |
+ v = make_node(concat, v, right); |
|
292 |
+ if(!v) |
|
293 |
+ return NULL; |
|
294 |
+ case '\\': |
|
295 |
+ /* next char is escaped, advance pointer |
|
296 |
+ * and let fall-through handle it */ |
|
297 |
+ ++*last; |
|
298 |
+ default: |
|
299 |
+ right = make_leaf(p[*last]); |
|
300 |
+ v = make_node(concat, v, right); |
|
301 |
+ if(!v) |
|
302 |
+ return NULL; |
|
303 |
+ ++*last; |
|
304 |
+ break; |
|
305 |
+ } |
|
306 |
+ } |
|
307 |
+ return v; |
|
308 |
+} |
|
309 |
+ |
|
310 |
+#define BITMAP_HASSET(b, i) (b[i>>3] & (1<<(i&7))) |
|
311 |
+ |
|
312 |
+static int build_suffixtree_ascend(struct node *n, struct text_buffer *buf, struct node *prev, suffix_callback cb, void *cbdata, struct regex_list *regex) |
|
313 |
+{ |
|
314 |
+ size_t i; |
|
315 |
+ while(n) { |
|
316 |
+ struct node *q = n; |
|
317 |
+ switch(n->type) { |
|
318 |
+ case root: |
|
319 |
+ textbuffer_putc(buf, '\0'); |
|
320 |
+ if(cb(cbdata, buf->data, buf->pos-1, regex) < 0) |
|
321 |
+ return CL_EMEM; |
|
322 |
+ return 0; |
|
323 |
+ case leaf: |
|
324 |
+ textbuffer_putc(buf, n->u.leaf_char); |
|
325 |
+ n = n->parent; |
|
326 |
+ break; |
|
327 |
+ case leaf_class: |
|
328 |
+ if(memcmp(n->u.leaf_class_bitmap, dot_bitmap, sizeof(dot_bitmap)) == 0) { |
|
329 |
+ textbuffer_putc(buf, '\0'); |
|
330 |
+ if(cb(cbdata, buf->data, buf->pos-1, regex) < 0) |
|
331 |
+ return CL_EMEM; |
|
332 |
+ return 0; |
|
333 |
+ } |
|
334 |
+ for(i=0;i<255;i++) { |
|
335 |
+ if(BITMAP_HASSET(n->u.leaf_class_bitmap, i)) { |
|
336 |
+ size_t pos; |
|
337 |
+ pos = buf->pos; |
|
338 |
+ textbuffer_putc(buf, i); |
|
339 |
+ if(build_suffixtree_ascend(n->parent, buf, n, cb, cbdata, regex) < 0) |
|
340 |
+ return CL_EMEM; |
|
341 |
+ buf->pos = pos; |
|
342 |
+ } |
|
343 |
+ } |
|
344 |
+ return 0; |
|
345 |
+ case concat: |
|
346 |
+ if(prev != n->u.children.left) { |
|
347 |
+ if(build_suffixtree_descend(n->u.children.left, buf, cb, cbdata, regex) < 0) |
|
348 |
+ return CL_EMEM; |
|
349 |
+ /* we're done here, descend will call |
|
350 |
+ * ascend if needed */ |
|
351 |
+ return 0; |
|
352 |
+ } else { |
|
353 |
+ n = n->parent; |
|
354 |
+ } |
|
355 |
+ break; |
|
356 |
+ case alternate: |
|
357 |
+ n = n->parent; |
|
358 |
+ break; |
|
359 |
+ case optional: |
|
360 |
+ textbuffer_putc(buf, '\0'); |
|
361 |
+ if(cb(cbdata, buf->data, buf->pos-1, regex) < 0) |
|
362 |
+ return CL_EMEM; |
|
363 |
+ return 0; |
|
364 |
+ } |
|
365 |
+ prev = q; |
|
366 |
+ } |
|
367 |
+ return 0; |
|
368 |
+} |
|
369 |
+ |
|
370 |
+static int build_suffixtree_descend(struct node *n, struct text_buffer *buf, suffix_callback cb, void *cbdata, struct regex_list *regex) |
|
371 |
+{ |
|
372 |
+ size_t pos; |
|
373 |
+ while(n && n->type == concat) { |
|
374 |
+ n = n->u.children.right; |
|
375 |
+ } |
|
376 |
+ if(!n) |
|
377 |
+ return 0; |
|
378 |
+ /* find out end of the regular expression, |
|
379 |
+ * if it ends with a static pattern */ |
|
380 |
+ switch(n->type) { |
|
381 |
+ case alternate: |
|
382 |
+ /* save pos as restart point */ |
|
383 |
+ pos = buf->pos; |
|
384 |
+ if(build_suffixtree_descend(n->u.children.left, buf, cb, cbdata, regex) < 0) |
|
385 |
+ return CL_EMEM; |
|
386 |
+ buf->pos = pos; |
|
387 |
+ if(build_suffixtree_descend(n->u.children.right, buf, cb, cbdata, regex) < 0) |
|
388 |
+ return CL_EMEM; |
|
389 |
+ buf->pos = pos; |
|
390 |
+ break; |
|
391 |
+ case optional: |
|
392 |
+ textbuffer_putc(buf, '\0'); |
|
393 |
+ if(cb(cbdata, buf->data, buf->pos-1, regex) < 0) |
|
394 |
+ return CL_EMEM; |
|
395 |
+ return 0; |
|
396 |
+ case leaf: |
|
397 |
+ case leaf_class: |
|
398 |
+ if(build_suffixtree_ascend(n, buf, NULL, cb, cbdata, regex) < 0) |
|
399 |
+ return CL_EMEM; |
|
400 |
+ return 0; |
|
401 |
+ default: |
|
402 |
+ break; |
|
403 |
+ } |
|
404 |
+ return 0; |
|
405 |
+} |
|
406 |
+ |
|
407 |
+int cli_regex2suffix(const char *pattern, struct regex_list *regex, suffix_callback cb, void *cbdata) |
|
408 |
+{ |
|
409 |
+ struct text_buffer buf; |
|
410 |
+ struct node root_node; |
|
411 |
+ struct node *n; |
|
412 |
+ size_t last = 0; |
|
413 |
+ int rc; |
|
414 |
+ |
|
415 |
+ assert(regex && pattern); |
|
416 |
+ |
|
417 |
+ rc = cli_regcomp(®ex->preg, pattern, REG_EXTENDED); |
|
418 |
+ if(rc) { |
|
419 |
+ size_t buflen = cli_regerror(rc, ®ex->preg, NULL, 0); |
|
420 |
+ char *errbuf = cli_malloc(buflen); |
|
421 |
+ if(errbuf) { |
|
422 |
+ cli_regerror(rc, ®ex->preg, errbuf, buflen); |
|
423 |
+ cli_errmsg(MODULE "Error compiling regular expression %s: %s\n", pattern, errbuf); |
|
424 |
+ free(errbuf); |
|
425 |
+ } else { |
|
426 |
+ cli_errmsg(MODULE "Error compiling regular expression: %s\n", pattern); |
|
427 |
+ } |
|
428 |
+ return rc; |
|
429 |
+ } |
|
430 |
+#ifdef CL_DEBUG |
|
431 |
+ regex->pattern = cli_strdup(pattern); |
|
432 |
+#endif |
|
433 |
+ regex->nxt = NULL; |
|
434 |
+ |
|
435 |
+ n = parse_regex(pattern, &last); |
|
436 |
+ if(!n) |
|
437 |
+ return REG_ESPACE; |
|
438 |
+ memset(&buf, 0, sizeof(buf)); |
|
439 |
+ memset(&root_node, 0, sizeof(buf)); |
|
440 |
+ n->parent = &root_node; |
|
441 |
+ |
|
442 |
+ rc = build_suffixtree_descend(n, &buf, cb, cbdata, regex); |
|
443 |
+ destroy_tree(n); |
|
444 |
+ return rc; |
|
445 |
+} |
|
446 |
+ |
|
447 |
+ |
0 | 448 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,35 @@ |
0 |
+/* |
|
1 |
+ * Parse a regular expression, and extract a static suffix. |
|
2 |
+ * |
|
3 |
+ * Copyright (C) 2007-2008 Sourcefire, Inc. |
|
4 |
+ * |
|
5 |
+ * Authors: Török Edvin |
|
6 |
+ * |
|
7 |
+ * This program is free software; you can redistribute it and/or modify |
|
8 |
+ * it under the terms of the GNU General Public License version 2 as |
|
9 |
+ * published by the Free Software Foundation. |
|
10 |
+ * |
|
11 |
+ * This program is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
+ * GNU General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU General Public License |
|
17 |
+ * along with this program; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
19 |
+ * MA 02110-1301, USA. |
|
20 |
+ */ |
|
21 |
+#ifndef REGEX_SUFFIX_H |
|
22 |
+#define REGEX_SUFFIX_H |
|
23 |
+#include "regex/regex.h" |
|
24 |
+ |
|
25 |
+struct regex_list { |
|
26 |
+#ifdef CL_DEBUG |
|
27 |
+ const char *pattern; |
|
28 |
+#endif |
|
29 |
+ regex_t preg; |
|
30 |
+ struct regex_list *nxt; |
|
31 |
+}; |
|
32 |
+typedef int (*suffix_callback)(void *cbdata, const char *suffix, size_t len, struct regex_list *regex); |
|
33 |
+int cli_regex2suffix(const char *pattern, struct regex_list *regex, suffix_callback cb, void *cbdata); |
|
34 |
+#endif |
... | ... |
@@ -9,7 +9,7 @@ else |
9 | 9 |
check_PROGRAMS = $(programs) |
10 | 10 |
check_SCRIPTS = $(scripts) |
11 | 11 |
endif |
12 |
-check_clamav_SOURCES = check_clamav.c check_jsnorm.c check_str.c checks.h $(top_builddir)/libclamav/clamav.h |
|
12 |
+check_clamav_SOURCES = check_clamav.c check_jsnorm.c check_str.c check_regex.c checks.h $(top_builddir)/libclamav/clamav.h |
|
13 | 13 |
check_clamav_CFLAGS = @CHECK_CFLAGS@ |
14 | 14 |
check_clamav_LDADD = $(top_builddir)/libclamav/libclamav.la @THREAD_LIBS@ @CHECK_LIBS@ |
15 | 15 |
|
... | ... |
@@ -55,7 +55,8 @@ binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) |
55 | 55 |
PROGRAMS = $(bin_PROGRAMS) |
56 | 56 |
am_check_clamav_OBJECTS = check_clamav-check_clamav.$(OBJEXT) \ |
57 | 57 |
check_clamav-check_jsnorm.$(OBJEXT) \ |
58 |
- check_clamav-check_str.$(OBJEXT) |
|
58 |
+ check_clamav-check_str.$(OBJEXT) \ |
|
59 |
+ check_clamav-check_regex.$(OBJEXT) |
|
59 | 60 |
check_clamav_OBJECTS = $(am_check_clamav_OBJECTS) |
60 | 61 |
check_clamav_DEPENDENCIES = $(top_builddir)/libclamav/libclamav.la |
61 | 62 |
check_clamav_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ |
... | ... |
@@ -219,7 +220,7 @@ programs = check_clamav |
219 | 219 |
scripts = check_clamd.sh check_freshclam.sh check_sigtool.sh check_clamscan.sh |
220 | 220 |
@ENABLE_UT_INSTALL_TRUE@dist_bin_SCRIPTS = $(scripts) |
221 | 221 |
@ENABLE_UT_INSTALL_FALSE@check_SCRIPTS = $(scripts) |
222 |
-check_clamav_SOURCES = check_clamav.c check_jsnorm.c check_str.c checks.h $(top_builddir)/libclamav/clamav.h |
|
222 |
+check_clamav_SOURCES = check_clamav.c check_jsnorm.c check_str.c check_regex.c checks.h $(top_builddir)/libclamav/clamav.h |
|
223 | 223 |
check_clamav_CFLAGS = @CHECK_CFLAGS@ |
224 | 224 |
check_clamav_LDADD = $(top_builddir)/libclamav/libclamav.la @THREAD_LIBS@ @CHECK_LIBS@ |
225 | 225 |
EXTRA_DIST = test-clamd.conf test-freshclam.conf |
... | ... |
@@ -329,6 +330,7 @@ distclean-compile: |
329 | 329 |
|
330 | 330 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_clamav-check_clamav.Po@am__quote@ |
331 | 331 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_clamav-check_jsnorm.Po@am__quote@ |
332 |
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_clamav-check_regex.Po@am__quote@ |
|
332 | 333 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_clamav-check_str.Po@am__quote@ |
333 | 334 |
|
334 | 335 |
.c.o: |
... | ... |
@@ -394,6 +396,20 @@ check_clamav-check_str.obj: check_str.c |
394 | 394 |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
395 | 395 |
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_clamav_CFLAGS) $(CFLAGS) -c -o check_clamav-check_str.obj `if test -f 'check_str.c'; then $(CYGPATH_W) 'check_str.c'; else $(CYGPATH_W) '$(srcdir)/check_str.c'; fi` |
396 | 396 |
|
397 |
+check_clamav-check_regex.o: check_regex.c |
|
398 |
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_clamav_CFLAGS) $(CFLAGS) -MT check_clamav-check_regex.o -MD -MP -MF $(DEPDIR)/check_clamav-check_regex.Tpo -c -o check_clamav-check_regex.o `test -f 'check_regex.c' || echo '$(srcdir)/'`check_regex.c |
|
399 |
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/check_clamav-check_regex.Tpo $(DEPDIR)/check_clamav-check_regex.Po |
|
400 |
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='check_regex.c' object='check_clamav-check_regex.o' libtool=no @AMDEPBACKSLASH@ |
|
401 |
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
402 |
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_clamav_CFLAGS) $(CFLAGS) -c -o check_clamav-check_regex.o `test -f 'check_regex.c' || echo '$(srcdir)/'`check_regex.c |
|
403 |
+ |
|
404 |
+check_clamav-check_regex.obj: check_regex.c |
|
405 |
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_clamav_CFLAGS) $(CFLAGS) -MT check_clamav-check_regex.obj -MD -MP -MF $(DEPDIR)/check_clamav-check_regex.Tpo -c -o check_clamav-check_regex.obj `if test -f 'check_regex.c'; then $(CYGPATH_W) 'check_regex.c'; else $(CYGPATH_W) '$(srcdir)/check_regex.c'; fi` |
|
406 |
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/check_clamav-check_regex.Tpo $(DEPDIR)/check_clamav-check_regex.Po |
|
407 |
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='check_regex.c' object='check_clamav-check_regex.obj' libtool=no @AMDEPBACKSLASH@ |
|
408 |
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
409 |
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_clamav_CFLAGS) $(CFLAGS) -c -o check_clamav-check_regex.obj `if test -f 'check_regex.c'; then $(CYGPATH_W) 'check_regex.c'; else $(CYGPATH_W) '$(srcdir)/check_regex.c'; fi` |
|
410 |
+ |
|
397 | 411 |
mostlyclean-libtool: |
398 | 412 |
-rm -f *.lo |
399 | 413 |
|
... | ... |
@@ -298,6 +298,11 @@ static Suite *test_cli_suite(void) |
298 | 298 |
return s; |
299 | 299 |
} |
300 | 300 |
|
301 |
+void errmsg_expected(void) |
|
302 |
+{ |
|
303 |
+ fputs("cli_errmsg() expected here\n", stderr); |
|
304 |
+} |
|
305 |
+ |
|
301 | 306 |
int main(int argc, char **argv) |
302 | 307 |
{ |
303 | 308 |
int nf; |
... | ... |
@@ -306,8 +311,11 @@ int main(int argc, char **argv) |
306 | 306 |
srunner_add_suite(sr, test_cli_suite()); |
307 | 307 |
srunner_add_suite(sr, test_jsnorm_suite()); |
308 | 308 |
srunner_add_suite(sr, test_str_suite()); |
309 |
+ srunner_add_suite(sr, test_regex_suite()); |
|
309 | 310 |
|
310 | 311 |
srunner_set_log(sr, "test.log"); |
312 |
+ freopen("test-stderr.log","w+",stderr); |
|
313 |
+ |
|
311 | 314 |
srunner_run_all(sr, CK_NORMAL); |
312 | 315 |
nf = srunner_ntests_failed(sr); |
313 | 316 |
srunner_free(sr); |
... | ... |
@@ -1,3 +1,24 @@ |
1 |
+/* |
|
2 |
+ * Unit tests for JS normalizer. |
|
3 |
+ * |
|
4 |
+ * Copyright (C) 2008 Sourcefire, Inc. |
|
5 |
+ * |
|
6 |
+ * Authors: Török Edvin |
|
7 |
+ * |
|
8 |
+ * This program is free software; you can redistribute it and/or modify |
|
9 |
+ * it under the terms of the GNU General Public License version 2 as |
|
10 |
+ * published by the Free Software Foundation. |
|
11 |
+ * |
|
12 |
+ * This program is distributed in the hope that it will be useful, |
|
13 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 |
+ * GNU General Public License for more details. |
|
16 |
+ * |
|
17 |
+ * You should have received a copy of the GNU General Public License |
|
18 |
+ * along with this program; if not, write to the Free Software |
|
19 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
20 |
+ * MA 02110-1301, USA. |
|
21 |
+ */ |
|
1 | 22 |
#if HAVE_CONFIG_H |
2 | 23 |
#include "clamav-config.h" |
3 | 24 |
#endif |
... | ... |
@@ -1,3 +1,24 @@ |
1 |
+/* |
|
2 |
+ * Unit tests for string functions. |
|
3 |
+ * |
|
4 |
+ * Copyright (C) 2008 Sourcefire, Inc. |
|
5 |
+ * |
|
6 |
+ * Authors: Török Edvin |
|
7 |
+ * |
|
8 |
+ * This program is free software; you can redistribute it and/or modify |
|
9 |
+ * it under the terms of the GNU General Public License version 2 as |
|
10 |
+ * published by the Free Software Foundation. |
|
11 |
+ * |
|
12 |
+ * This program is distributed in the hope that it will be useful, |
|
13 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 |
+ * GNU General Public License for more details. |
|
16 |
+ * |
|
17 |
+ * You should have received a copy of the GNU General Public License |
|
18 |
+ * along with this program; if not, write to the Free Software |
|
19 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
|
20 |
+ * MA 02110-1301, USA. |
|
21 |
+ */ |
|
1 | 22 |
#if HAVE_CONFIG_H |
2 | 23 |
#include "clamav-config.h" |
3 | 24 |
#endif |