git-svn: trunk@3998
Tomasz Kojm authored on 2008/07/27 00:48:08... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Sat Jul 26 17:30:02 CEST 2008 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav: lsigs: handle extended block modifiers (bb#896) |
|
4 |
+ |
|
1 | 5 |
Fri Jul 25 20:41:21 CEST 2008 (tk) |
2 | 6 |
---------------------------------- |
3 | 7 |
* libclamav: add initial support for logical signatures (bb#896) |
... | ... |
@@ -377,10 +377,11 @@ void cli_ac_free(struct cli_matcher *root) |
377 | 377 |
/* |
378 | 378 |
* In parse_only mode this function returns -1 on error or the max subsig id |
379 | 379 |
*/ |
380 |
-int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, unsigned int parse_only) |
|
380 |
+int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, uint64_t *ids, unsigned int parse_only) |
|
381 | 381 |
{ |
382 | 382 |
unsigned int i, len = end - expr, pth = 0, opoff = 0, op1off = 0, val; |
383 |
- unsigned int blkend = 0, id, modval, lcnt = 0, rcnt = 0, tcnt, modoff = 0; |
|
383 |
+ unsigned int blkend = 0, id, modval1, modval2 = 0, lcnt = 0, rcnt = 0, tcnt, modoff = 0; |
|
384 |
+ uint64_t lids = 0, rids = 0, tids; |
|
384 | 385 |
int ret, lval, rval; |
385 | 386 |
char op = 0, op1 = 0, mod = 0, blkmod = 0; |
386 | 387 |
const char *lstart = expr, *lend = NULL, *rstart = NULL, *rend = end, *pt; |
... | ... |
@@ -425,12 +426,14 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne |
425 | 425 |
blkend = i; |
426 | 426 |
if(expr[i + 1] == '>' || expr[i + 1] == '<' || expr[i + 1] == '=') { |
427 | 427 |
blkmod = expr[i + 1]; |
428 |
- ret = sscanf(&expr[i + 2], "%u", &modval); |
|
428 |
+ ret = sscanf(&expr[i + 2], "%u,%u", &modval1, &modval2); |
|
429 |
+ if(ret != 2) |
|
430 |
+ ret = sscanf(&expr[i + 2], "%u", &modval1); |
|
429 | 431 |
if(!ret || ret == EOF) { |
430 | 432 |
cli_errmsg("chklexpr: Syntax error: Missing number after '%c'\n", expr[i + 1]); |
431 | 433 |
return -1; |
432 | 434 |
} |
433 |
- for(i += 2; i + 1 < len && isdigit(expr[i + 1]); i++); |
|
435 |
+ for(i += 2; i + 1 < len && (isdigit(expr[i + 1]) || expr[i + 1] == ','); i++); |
|
434 | 436 |
} |
435 | 437 |
|
436 | 438 |
if(&expr[i + 1] == rend) |
... | ... |
@@ -447,7 +450,7 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne |
447 | 447 |
|
448 | 448 |
if(!op && !op1) { |
449 | 449 |
if(expr[0] == '(') |
450 |
- return cli_ac_chklsig(++expr, --end, lsigcnt, cnt, parse_only); |
|
450 |
+ return cli_ac_chklsig(++expr, --end, lsigcnt, cnt, ids, parse_only); |
|
451 | 451 |
|
452 | 452 |
ret = sscanf(expr, "%u", &id); |
453 | 453 |
if(!ret || ret == EOF) { |
... | ... |
@@ -462,43 +465,44 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne |
462 | 462 |
|
463 | 463 |
if(mod) { |
464 | 464 |
pt = strchr(expr, mod) + modoff; |
465 |
- ret = sscanf(pt, "%u", &modval); |
|
465 |
+ ret = sscanf(pt, "%u", &modval1); |
|
466 | 466 |
if(!ret || ret == EOF) { |
467 | 467 |
cli_errmsg("chklexpr: Syntax error: Missing number after '%c'\n", mod); |
468 | 468 |
return -1; |
469 | 469 |
} |
470 |
- if(!parse_only) switch(mod) { |
|
471 |
- case '=': |
|
472 |
- if(val == modval) { |
|
473 |
- *cnt += val; |
|
474 |
- return 1; |
|
475 |
- } else { |
|
470 |
+ if(!parse_only) { |
|
471 |
+ switch(mod) { |
|
472 |
+ case '=': |
|
473 |
+ if(val != modval1) |
|
474 |
+ return 0; |
|
475 |
+ break; |
|
476 |
+ case '<': |
|
477 |
+ if(val >= modval1) |
|
478 |
+ return 0; |
|
479 |
+ break; |
|
480 |
+ case '>': |
|
481 |
+ if(val <= modval1) |
|
482 |
+ return 0; |
|
483 |
+ break; |
|
484 |
+ default: |
|
476 | 485 |
return 0; |
477 |
- } |
|
478 |
- break; |
|
479 |
- case '<': |
|
480 |
- if(val < modval) { |
|
481 |
- *cnt += val; |
|
482 |
- return 1; |
|
483 |
- } else { |
|
484 |
- return 0; |
|
485 |
- } |
|
486 |
- break; |
|
487 |
- case '>': |
|
488 |
- if(val > modval) { |
|
489 |
- *cnt += val; |
|
490 |
- return 1; |
|
491 |
- } else { |
|
492 |
- return 0; |
|
493 |
- } |
|
486 |
+ } |
|
487 |
+ *cnt += val; |
|
488 |
+ *ids |= (uint64_t) 1 << id; |
|
489 |
+ return 1; |
|
494 | 490 |
} |
495 | 491 |
} |
496 | 492 |
|
497 | 493 |
if(parse_only) { |
498 | 494 |
return val; |
499 | 495 |
} else { |
500 |
- *cnt += val; |
|
501 |
- return val ? 1 : 0; |
|
496 |
+ if(val) { |
|
497 |
+ *cnt += val; |
|
498 |
+ *ids |= (uint64_t) 1 << id; |
|
499 |
+ return 1; |
|
500 |
+ } else { |
|
501 |
+ return 0; |
|
502 |
+ } |
|
502 | 503 |
} |
503 | 504 |
} |
504 | 505 |
|
... | ... |
@@ -520,13 +524,13 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne |
520 | 520 |
} |
521 | 521 |
rstart = &expr[opoff + 1]; |
522 | 522 |
|
523 |
- lval = cli_ac_chklsig(lstart, lend, lsigcnt, &lcnt, parse_only); |
|
523 |
+ lval = cli_ac_chklsig(lstart, lend, lsigcnt, &lcnt, &lids, parse_only); |
|
524 | 524 |
if(lval == -1) { |
525 | 525 |
cli_errmsg("cli_ac_chklsig: Calculation of lval failed\n"); |
526 | 526 |
return -1; |
527 | 527 |
} |
528 | 528 |
|
529 |
- rval = cli_ac_chklsig(rstart, rend, lsigcnt, &rcnt, parse_only); |
|
529 |
+ rval = cli_ac_chklsig(rstart, rend, lsigcnt, &rcnt, &rids, parse_only); |
|
530 | 530 |
if(rval == -1) { |
531 | 531 |
cli_errmsg("cli_ac_chklsig: Calculation of rval failed\n"); |
532 | 532 |
return -1; |
... | ... |
@@ -555,43 +559,48 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne |
555 | 555 |
} |
556 | 556 |
|
557 | 557 |
if(!blkmod) { |
558 |
- if(ret) |
|
558 |
+ if(ret) { |
|
559 | 559 |
*cnt += lcnt + rcnt; |
560 |
- |
|
560 |
+ *ids |= lids | rids; |
|
561 |
+ } |
|
561 | 562 |
return ret; |
562 | 563 |
} else { |
563 |
- if(ret) |
|
564 |
+ if(ret) { |
|
564 | 565 |
tcnt = lcnt + rcnt; |
565 |
- else |
|
566 |
+ tids = lids | rids; |
|
567 |
+ } else { |
|
566 | 568 |
tcnt = 0; |
569 |
+ tids = 0; |
|
570 |
+ } |
|
567 | 571 |
|
568 | 572 |
switch(blkmod) { |
569 | 573 |
case '=': |
570 |
- if(tcnt == modval) { |
|
571 |
- *cnt += tcnt; |
|
572 |
- return 1; |
|
573 |
- } else { |
|
574 |
+ if(tcnt != modval1) |
|
574 | 575 |
return 0; |
575 |
- } |
|
576 | 576 |
break; |
577 | 577 |
case '<': |
578 |
- if(tcnt < modval) { |
|
579 |
- *cnt += tcnt; |
|
580 |
- return 1; |
|
581 |
- } else { |
|
578 |
+ if(tcnt >= modval1) |
|
582 | 579 |
return 0; |
583 |
- } |
|
584 | 580 |
break; |
585 | 581 |
case '>': |
586 |
- if(tcnt > modval) { |
|
587 |
- *cnt += tcnt; |
|
588 |
- return 1; |
|
589 |
- } else { |
|
582 |
+ if(tcnt <= modval1) |
|
590 | 583 |
return 0; |
591 |
- } |
|
584 |
+ break; |
|
592 | 585 |
default: |
593 | 586 |
return 0; |
594 | 587 |
} |
588 |
+ |
|
589 |
+ if(modval2) { |
|
590 |
+ val = 0; |
|
591 |
+ while(tids) { |
|
592 |
+ val += tids & (uint64_t) 1; |
|
593 |
+ tids >>= 1; |
|
594 |
+ } |
|
595 |
+ if(val < modval2) |
|
596 |
+ return 0; |
|
597 |
+ } |
|
598 |
+ *cnt += tcnt; |
|
599 |
+ return 1; |
|
595 | 600 |
} |
596 | 601 |
} |
597 | 602 |
} |
... | ... |
@@ -76,7 +76,7 @@ struct cli_ac_node { |
76 | 76 |
|
77 | 77 |
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern); |
78 | 78 |
int cli_ac_initdata(struct cli_ac_data *data, uint32_t partsigs, uint32_t lsigs, uint8_t tracklen); |
79 |
-int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, unsigned int parse_only); |
|
79 |
+int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigned int *cnt, uint64_t *ids, unsigned int parse_only); |
|
80 | 80 |
void cli_ac_freedata(struct cli_ac_data *data); |
81 | 81 |
int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, int fd, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx); |
82 | 82 |
int cli_ac_buildtrie(struct cli_matcher *root); |
... | ... |
@@ -254,6 +254,7 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
254 | 254 |
int ret = CL_CLEAN, type = CL_CLEAN, bytes; |
255 | 255 |
unsigned int i, evalcnt; |
256 | 256 |
uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0; |
257 |
+ uint64_t evalids; |
|
257 | 258 |
struct cli_ac_data gdata, tdata; |
258 | 259 |
cli_md5_ctx md5ctx; |
259 | 260 |
unsigned char digest[16]; |
... | ... |
@@ -386,7 +387,8 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
386 | 386 |
if(troot) { |
387 | 387 |
for(i = 0; i < troot->ac_lsigs; i++) { |
388 | 388 |
evalcnt = 0; |
389 |
- if(cli_ac_chklsig(troot->ac_lsigtable[i]->logic, troot->ac_lsigtable[i]->logic + strlen(troot->ac_lsigtable[i]->logic), tdata.lsigcnt[i], &evalcnt, 0) == 1) { |
|
389 |
+ evalids = 0; |
|
390 |
+ if(cli_ac_chklsig(troot->ac_lsigtable[i]->logic, troot->ac_lsigtable[i]->logic + strlen(troot->ac_lsigtable[i]->logic), tdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) { |
|
390 | 391 |
if(ctx->virname) |
391 | 392 |
*ctx->virname = troot->ac_lsigtable[i]->virname; |
392 | 393 |
ret = CL_VIRUS; |
... | ... |
@@ -399,7 +401,8 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc |
399 | 399 |
if(groot) { |
400 | 400 |
if(ret != CL_VIRUS) for(i = 0; i < groot->ac_lsigs; i++) { |
401 | 401 |
evalcnt = 0; |
402 |
- if(cli_ac_chklsig(groot->ac_lsigtable[i]->logic, groot->ac_lsigtable[i]->logic + strlen(groot->ac_lsigtable[i]->logic), gdata.lsigcnt[i], &evalcnt, 0) == 1) { |
|
402 |
+ evalids = 0; |
|
403 |
+ if(cli_ac_chklsig(groot->ac_lsigtable[i]->logic, groot->ac_lsigtable[i]->logic + strlen(groot->ac_lsigtable[i]->logic), gdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) { |
|
403 | 404 |
if(ctx->virname) |
404 | 405 |
*ctx->virname = groot->ac_lsigtable[i]->virname; |
405 | 406 |
ret = CL_VIRUS; |
... | ... |
@@ -899,7 +899,7 @@ static int cli_loadldb(FILE *fs, struct cl_engine **engine, unsigned int *signo, |
899 | 899 |
break; |
900 | 900 |
} |
901 | 901 |
|
902 |
- subsigs = cli_ac_chklsig(logic, logic + strlen(logic), NULL, NULL, 1); |
|
902 |
+ subsigs = cli_ac_chklsig(logic, logic + strlen(logic), NULL, NULL, NULL, 1); |
|
903 | 903 |
if(subsigs == -1) { |
904 | 904 |
ret = CL_EMALFDB; |
905 | 905 |
break; |