static inline int matcher_run(const struct cli_matcher *root, const unsigned char *buffer, uint32_t length, const char **virname, struct cli_ac_data *mdata, uint32_t offset, const struct cli_target_info *tinfo, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, fmap_t *map, struct cli_bm_off *offdata, uint32_t *viroffset, cli_ctx *ctx) { int ret; int32_t pos = 0; struct filter_match_info info; uint32_t orig_length, orig_offset; const unsigned char* orig_buffer; unsigned int viruses_found = 0; if (root->filter) { if(filter_search_ext(root->filter, buffer, length, &info) == -1) { /* for safety always scan last maxpatlen bytes */ pos = length - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } else { /* must not cut buffer for 64[4-4]6161, because we must be able to check * 64! */ pos = info.first_match - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } } else { PERF_LOG_FILTER(0, length, root->type); } orig_length = length; orig_buffer = buffer; orig_offset = offset; length -= pos; buffer += pos; offset += pos; if (!root->ac_only) { PERF_LOG_TRIES(0, 1, length); if (root->bm_offmode) { /* Don't use prefiltering for BM offset mode, since BM keeps tracks * of offsets itself, and doesn't work if we skip chunks of input * data */ ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, viroffset); } else { ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, viroffset); } if (ret == CL_VIRUS) { if (ctx) { cli_append_virus(ctx, *virname); if (SCAN_ALL) viruses_found++; else return ret; } } } PERF_LOG_TRIES(acmode, 0, length); ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, ctx); if (ctx && !SCAN_ALL && ret == CL_VIRUS) cli_append_virus(ctx, *virname); if (ctx && SCAN_ALL && viruses_found) return CL_VIRUS; return ret; }
static inline int matcher_run(const struct cli_matcher *root, const unsigned char *buffer, uint32_t length, const char **virname, struct cli_ac_data *mdata, uint32_t offset, const struct cli_target_info *tinfo, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned int pcremode, struct cli_ac_result **acres, fmap_t *map, struct cli_bm_off *offdata, struct cli_pcre_off *poffdata, cli_ctx *ctx) { int ret, saved_ret = CL_CLEAN; int32_t pos = 0; struct filter_match_info info; uint32_t orig_length, orig_offset; const unsigned char* orig_buffer; unsigned int viruses_found = 0; if (root->filter) { if(filter_search_ext(root->filter, buffer, length, &info) == -1) { /* for safety always scan last maxpatlen bytes */ pos = length - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } else { /* must not cut buffer for 64[4-4]6161, because we must be able to check * 64! */ pos = info.first_match - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } } else { PERF_LOG_FILTER(0, length, root->type); } orig_length = length; orig_buffer = buffer; orig_offset = offset; length -= pos; buffer += pos; offset += pos; if (!root->ac_only) { PERF_LOG_TRIES(0, 1, length); if (root->bm_offmode) { /* Don't use prefiltering for BM offset mode, since BM keeps tracks * of offsets itself, and doesn't work if we skip chunks of input * data */ ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, ctx); } else { ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, ctx); } if (ret != CL_CLEAN) { if (ret != CL_VIRUS) return ret; /* else (ret == CL_VIRUS) */ if (SCAN_ALL) viruses_found = 1; else { cli_append_virus(ctx, *virname); return ret; } } } PERF_LOG_TRIES(acmode, 0, length); ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, ctx); if (ret != CL_CLEAN) { if (ret == CL_VIRUS) { if (SCAN_ALL) viruses_found = 1; else { cli_append_virus(ctx, *virname); return ret; } } else if (ret > CL_TYPENO && acmode & AC_SCAN_VIR) saved_ret = ret; else return ret; } /* due to logical triggered, pcres cannot be evaluated until after full subsig matching */ /* cannot save pcre execution state without possible evasion; must scan entire buffer */ /* however, scanning the whole buffer may require the whole buffer being loaded into memory */ #if HAVE_PCRE if (root->pcre_metas) { int rc; uint64_t maxfilesize; if (map && (pcremode == PCRE_SCAN_FMAP)) { if (offset+length >= map->len) { /* check that scanned map does not exceed pcre maxfilesize limit */ maxfilesize = (uint64_t)cl_engine_get_num(ctx->engine, CL_ENGINE_PCRE_MAX_FILESIZE, &rc); if (rc != CL_SUCCESS) return rc; if (maxfilesize && (map->len > maxfilesize)) { cli_dbgmsg("matcher_run: pcre max filesize (map) exceeded (limit: %llu, needed: %llu)\n", (long long unsigned)maxfilesize, (long long unsigned)map->len); return CL_EMAXSIZE; } cli_dbgmsg("matcher_run: performing regex matching on full map: %u+%u(%u) >= %zu\n", offset, length, offset+length, map->len); buffer = fmap_need_off_once(map, 0, map->len); if (!buffer) return CL_EMEM; /* scan the full buffer */ ret = cli_pcre_scanbuf(buffer, map->len, virname, acres, root, mdata, poffdata, ctx); } } else if (pcremode == PCRE_SCAN_BUFF) { /* check that scanned buffer does not exceed pcre maxfilesize limit */ maxfilesize = (uint64_t)cl_engine_get_num(ctx->engine, CL_ENGINE_PCRE_MAX_FILESIZE, &rc); if (rc != CL_SUCCESS) return rc; if (maxfilesize && (length > maxfilesize)) { cli_dbgmsg("matcher_run: pcre max filesize (buf) exceeded (limit: %llu, needed: %u)\n", (long long unsigned)maxfilesize, length); return CL_EMAXSIZE; } cli_dbgmsg("matcher_run: performing regex matching on buffer with no map: %u+%u(%u)\n", offset, length, offset+length); /* scan the specified buffer */ ret = cli_pcre_scanbuf(buffer, length, virname, acres, root, mdata, poffdata, ctx); } } #endif /* HAVE_PCRE */ /* end experimental fragment */ if (ctx && !SCAN_ALL && ret == CL_VIRUS) cli_append_virus(ctx, *virname); if (ctx && SCAN_ALL && viruses_found) return CL_VIRUS; if (saved_ret && ret == CL_CLEAN) return saved_ret; return ret; }
static inline int matcher_run(const struct cli_matcher *root, const unsigned char *buffer, uint32_t length, const char **virname, struct cli_ac_data *mdata, uint32_t offset, const struct cli_target_info *tinfo, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int acmode, struct cli_ac_result **acres, fmap_t *map, struct cli_bm_off *offdata, uint32_t *viroffset, cli_ctx *ctx) { cli_infomsg(NULL,"DEBUG: in matcher_run\n");//CHR int ret; int32_t pos = 0; struct filter_match_info info; uint32_t orig_length, orig_offset; const unsigned char* orig_buffer; unsigned int viruses_found = 0; if (root->filter) { cli_infomsg(NULL,"DEBUG: has filter\n");//CHR // CHR function filter_search_ext will do pre-matchon prefix for a given pattern if(filter_search_ext(root->filter, buffer, length, &info) == -1) { cli_infomsg(NULL,"DEBUG: filter and in if\n");//CHR /* for safety always scan last maxpatlen bytes */ pos = length - root->maxpatlen - 1; if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } else { // CHR FSM match cli_infomsg(NULL,"DEBUG: filter and in else\n");//CHR /* must not cut buffer for 64[4-4]6161, because we must be able to check * 64! */ //CHR if first_match is far more beyond max pattern length //CHR we need to move forward a little bit to speed up the following scan pos = info.first_match - root->maxpatlen - 1; cli_infomsg(NULL,"DEBUG: pos=%d\n",pos);//CHR if (pos < 0) pos = 0; PERF_LOG_FILTER(pos, length, root->type); } } else { PERF_LOG_FILTER(0, length, root->type); } orig_length = length; orig_buffer = buffer; orig_offset = offset; //CHR pos is 0 in this case length -= pos; buffer += pos; offset += pos; if (!root->ac_only) { cli_infomsg(NULL,"DEBUG: !ac_only, bm scan first\n");//CHR PERF_LOG_TRIES(0, 1, length); if (root->bm_offmode) { /* Don't use prefiltering for BM offset mode, since BM keeps tracks * of offsets itself, and doesn't work if we skip chunks of input * data */ cli_infomsg(NULL,"DEBUG: scan in bm_offmode=1 mode\n"); //CHR ret = cli_bm_scanbuff(orig_buffer, orig_length, virname, NULL, root, orig_offset, tinfo, offdata, viroffset); } else { cli_infomsg(NULL,"DEBUG: scan in bm_offmode=0 mode\n"); //CHR cli_infomsg(NULL,"DEBUG: pass into cli_bm_scanbuff with length=%d,offset=%d\n",length,offset);//CHR ret = cli_bm_scanbuff(buffer, length, virname, NULL, root, offset, tinfo, offdata, viroffset); } if (ret == CL_VIRUS) { cli_infomsg(NULL,"DEBUG: bm scan find virus, won't do ac scan\n");//CHR if (ctx) { cli_append_virus(ctx, *virname); if (SCAN_ALL) viruses_found++; else return ret; } } } PERF_LOG_TRIES(acmode, 0, length); cli_infomsg(NULL,"DEBUG: ac scan\n");//CHR ret = cli_ac_scanbuff(buffer, length, virname, NULL, acres, root, mdata, offset, ftype, ftoffset, acmode, NULL); if (ctx && ret == CL_VIRUS) cli_append_virus(ctx, *virname); if (ctx && SCAN_ALL && viruses_found) return CL_VIRUS; return ret; }