36 changes: 18 additions & 18 deletions libclamav/matcher.c
Expand Up @@ -154,7 +154,7 @@ static inline int matcher_run(const struct cli_matcher *root,
return ret;

/* else (ret == CL_VIRUS) */
if (SCAN_ALL)
if (SCAN_ALLMATCHES)
viruses_found = 1;
else {
ret = cli_append_virus(ctx, *virname);
Expand All @@ -167,7 +167,7 @@ static inline int matcher_run(const struct cli_matcher *root,
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)
if (SCAN_ALLMATCHES)
viruses_found = 1;
else {
ret = cli_append_virus(ctx, *virname);
Expand Down Expand Up @@ -228,9 +228,9 @@ static inline int matcher_run(const struct cli_matcher *root,
#endif /* HAVE_PCRE */
/* end experimental fragment */

if (ctx && !SCAN_ALL && ret == CL_VIRUS)
if (ctx && !SCAN_ALLMATCHES && ret == CL_VIRUS)
return cli_append_virus(ctx, *virname);
if (ctx && SCAN_ALL && viruses_found)
if (ctx && SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;

if (saved_ret && ret == CL_CLEAN)
Expand Down Expand Up @@ -280,7 +280,7 @@ int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset,
return ret;
if(ret == CL_VIRUS) {
viruses_found = 1;
if(ctx && !SCAN_ALL) {
if(ctx && !SCAN_ALLMATCHES) {
return ret;
}
}
Expand Down Expand Up @@ -579,7 +579,7 @@ int cli_checkfp_virus(unsigned char *digest, size_t size, cli_ctx *ctx, const ch
}

#ifdef HAVE__INTERNAL__SHA_COLLECT
if((ctx->options & CL_SCAN_INTERNAL_COLLECT_SHA) && ctx->sha_collect>0) {
if(SCAN_DEV_COLLECT_SHA && (ctx->sha_collect > 0)) {
if((ptr = fmap_need_off_once(map, 0, size))) {
if(!have_sha256)
cl_sha256(ptr, size, shash256+SHA256_HASH_SIZE, NULL);
Expand Down Expand Up @@ -842,7 +842,7 @@ int cli_exp_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *acd
#endif
if (rc == CL_VIRUS) {
viruses_found = 1;
if (SCAN_ALL)
if (SCAN_ALLMATCHES)
continue;
break;
}
Expand Down Expand Up @@ -1053,7 +1053,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
/* virname already appended by matcher_run */
viruses_found = 1;
}
if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
if((ret == CL_VIRUS && !SCAN_ALLMATCHES) || ret == CL_EMEM) {
if(!ftonly) {
cli_ac_freedata(&gdata);
cli_pcre_freeoff(&gpoff);
Expand Down Expand Up @@ -1083,7 +1083,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
/* virname already appended by matcher_run */
viruses_found = 1;
}
if((ret == CL_VIRUS && !SCAN_ALL) || ret == CL_EMEM) {
if((ret == CL_VIRUS && !SCAN_ALLMATCHES) || ret == CL_EMEM) {
cli_ac_freedata(&gdata);
cli_pcre_freeoff(&gpoff);
if(troot) {
Expand Down Expand Up @@ -1158,7 +1158,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
if((ret = cli_hm_scan(digest[hashtype], map->len, &virname, hdb, hashtype)) == CL_VIRUS) {
found += 1;
}
if(!found || SCAN_ALL) {
if(!found || SCAN_ALLMATCHES) {
if ((ret = cli_hm_scan_wild(digest[hashtype], &virname_w, hdb, hashtype)) == CL_VIRUS)
found += 2;
}
Expand All @@ -1185,15 +1185,15 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
if (found % 2) {
viruses_found = 1;
ret = cli_append_virus(ctx, virname);
if (!SCAN_ALL || ret != CL_CLEAN)
if (!SCAN_ALLMATCHES || ret != CL_CLEAN)
break;
virname = NULL;
}
/* If matched size-agnostic hash ... */
if (found > 1) {
viruses_found = 1;
ret = cli_append_virus(ctx, virname_w);
if (!SCAN_ALL || ret != CL_CLEAN)
if (!SCAN_ALLMATCHES || ret != CL_CLEAN)
break;
}
}
Expand All @@ -1204,7 +1204,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
cl_hash_destroy(sha256ctx);

if(troot) {
if(ret != CL_VIRUS || SCAN_ALL)
if(ret != CL_VIRUS || SCAN_ALLMATCHES)
ret = cli_exp_eval(ctx, troot, &tdata, &info, (const char *)refhash);
if (ret == CL_VIRUS)
viruses_found++;
Expand All @@ -1216,7 +1216,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
}

if(groot) {
if(ret != CL_VIRUS || SCAN_ALL)
if(ret != CL_VIRUS || SCAN_ALLMATCHES)
ret = cli_exp_eval(ctx, groot, &gdata, &info, (const char *)refhash);
cli_ac_freedata(&gdata);
cli_pcre_freeoff(&gpoff);
Expand All @@ -1227,7 +1227,7 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli

cli_hashset_destroy(&info.exeinfo.vinfo);

if (SCAN_ALL && viruses_found)
if (SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;
if(ret == CL_VIRUS)
return CL_VIRUS;
Expand All @@ -1251,7 +1251,7 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,

ret = cli_append_virus(ctx, "Detected.By.Callback");
viruses_found++;
if(!SCAN_ALL || ret != CL_CLEAN)
if(!SCAN_ALLMATCHES || ret != CL_CLEAN)
return ret;
}

Expand Down Expand Up @@ -1288,12 +1288,12 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,

ret = cli_append_virus(ctx, cdb->virname);
viruses_found++;
if(!SCAN_ALL || ret != CL_CLEAN)
if(!SCAN_ALLMATCHES || ret != CL_CLEAN)
return ret;

} while((cdb = cdb->next));

if (SCAN_ALL && viruses_found)
if (SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;
return CL_CLEAN;
}
7 changes: 3 additions & 4 deletions libclamav/mbox.c
Expand Up @@ -51,7 +51,6 @@
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include "clamav.h"
#include <dirent.h>
#include <limits.h>
#include <signal.h>
Expand Down Expand Up @@ -166,7 +165,7 @@ typedef enum {
#include <fcntl.h>

/*
* Use CL_SCAN_PARTIAL_MESSAGE to handle messages covered by section 7.3.2 of RFC1341.
* Use CL_SCAN_MAIL_PARTIAL_MESSAGE to handle messages covered by section 7.3.2 of RFC1341.
* This is experimental code so it is up to YOU to (1) ensure it's secure
* (2) periodically trim the directory of old files
*
Expand Down Expand Up @@ -594,7 +593,7 @@ cli_parse_mbox(const char *dir, cli_ctx *ctx)
}

if((retcode == CL_CLEAN) && ctx->found_possibly_unwanted &&
(*ctx->virname == NULL || SCAN_ALL)) {
(*ctx->virname == NULL || SCAN_ALLMATCHES)) {
retcode = cli_append_virus(ctx, "Heuristics.Phishing.Email");
ctx->found_possibly_unwanted = 0;
}
Expand Down Expand Up @@ -2131,7 +2130,7 @@ parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int re
rc = OK;
break;
} else if(strcasecmp(mimeSubtype, "partial") == 0) {
if(mctx->ctx->options&CL_SCAN_PARTIAL_MESSAGE) {
if(mctx->ctx->options->mail & CL_SCAN_MAIL_PARTIAL_MESSAGE) {
/* RFC1341 message split over many emails */
if(rfc1341(mainMessage, mctx->dir) >= 0)
rc = OK;
Expand Down
18 changes: 9 additions & 9 deletions libclamav/mbr.c
Expand Up @@ -186,17 +186,17 @@ int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
/* MBR is valid, examine bootstrap code */
ret = cli_map_scan(*ctx->fmap, 0, sectorsize, ctx, CL_TYPE_ANY);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
}

/* check that the partition table has no intersections - HEURISTICS */
if ((ctx->options & CL_SCAN_PARTITION_INTXN) && (ctx->dconf->other & OTHER_CONF_PRTNINTXN)) {
if (SCAN_HEURISTIC_PARTITION_INTXN && (ctx->dconf->other & OTHER_CONF_PRTNINTXN)) {
ret = mbr_primary_prtn_intxn(ctx, mbr, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -230,7 +230,7 @@ int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
ret = mbr_scanextprtn(ctx, &prtncount, mbr.entries[i].firstLBA,
mbr.entries[i].numLBA, sectorsize);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand All @@ -244,7 +244,7 @@ int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
mbr_parsemsg("cli_map_scan: [%u, +%u)\n", partoff, partsize);
ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -387,7 +387,7 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size

ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
if (ret != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))
if (SCAN_ALLMATCHES && (ret == CL_VIRUS))
detection = CL_VIRUS;
else
return ret;
Expand Down Expand Up @@ -506,7 +506,7 @@ static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size
cli_dbgmsg("cli_scanmbr: detected intersection with partitions "
"[%u, %u]\n", pitxn, i);
ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
if (SCAN_ALL || ret == CL_CLEAN)
if (SCAN_ALLMATCHES || ret == CL_CLEAN)
tmp = 0;
else
goto leave;
Expand All @@ -521,7 +521,7 @@ static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size
tmp = mbr_extended_prtn_intxn(ctx, &prtncount,
mbr.entries[i].firstLBA, sectorsize);
if (tmp != CL_CLEAN) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
if (SCAN_ALLMATCHES && (tmp == CL_VIRUS)) {
ret = tmp;
tmp = 0;
}
Expand Down Expand Up @@ -587,7 +587,7 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
if (ret == CL_VIRUS)
virus_found = 1;
if (SCAN_ALL || ret == CL_CLEAN)
if (SCAN_ALLMATCHES || ret == CL_CLEAN)
tmp = 0;
else
goto leave;
Expand Down
18 changes: 9 additions & 9 deletions libclamav/msxml_parser.c
Expand Up @@ -378,9 +378,9 @@ static int msxml_parse_element(struct msxml_ctx *mxctx, xmlTextReaderPtr reader,
switch (node_type) {
case XML_READER_TYPE_ELEMENT:
ret = msxml_parse_element(mxctx, reader, rlvl+1, thisjobj ? thisjobj : parent);
if (ret != CL_SUCCESS || (!SCAN_ALL && ret == CL_VIRUS)) {
if (ret != CL_SUCCESS || (!SCAN_ALLMATCHES && ret == CL_VIRUS)) {
return ret;
} else if (SCAN_ALL && ret == CL_VIRUS) {
} else if (SCAN_ALLMATCHES && ret == CL_VIRUS) {
virus = 1;
}
break;
Expand Down Expand Up @@ -429,9 +429,9 @@ static int msxml_parse_element(struct msxml_ctx *mxctx, xmlTextReaderPtr reader,
if (!(ctx->engine->keeptmp))
cli_unlink(tempfile);
free(tempfile);
if (ret != CL_SUCCESS && (ret != CL_VIRUS || (!SCAN_ALL && ret == CL_VIRUS))) {
if (ret != CL_SUCCESS && (ret != CL_VIRUS || (!SCAN_ALLMATCHES && ret == CL_VIRUS))) {
return ret;
} else if (SCAN_ALL && ret == CL_VIRUS) {
} else if (SCAN_ALLMATCHES && ret == CL_VIRUS) {
virus = 1;
}
}
Expand Down Expand Up @@ -476,9 +476,9 @@ static int msxml_parse_element(struct msxml_ctx *mxctx, xmlTextReaderPtr reader,
if (!(ctx->engine->keeptmp))
cli_unlink(tempfile);
free(tempfile);
if (ret != CL_SUCCESS && (ret != CL_VIRUS || (!SCAN_ALL && ret == CL_VIRUS))) {
if (ret != CL_SUCCESS && (ret != CL_VIRUS || (!SCAN_ALLMATCHES && ret == CL_VIRUS))) {
return ret;
} else if (SCAN_ALL && ret == CL_VIRUS) {
} else if (SCAN_ALLMATCHES && ret == CL_VIRUS) {
virus = 1;
}
}
Expand All @@ -500,9 +500,9 @@ static int msxml_parse_element(struct msxml_ctx *mxctx, xmlTextReaderPtr reader,
#else
ret = mxctx->comment_cb((const char *)node_value, ctx, NULL, mxctx->comment_data);
#endif
if (ret != CL_SUCCESS && (ret != CL_VIRUS || (!SCAN_ALL && ret == CL_VIRUS))) {
if (ret != CL_SUCCESS && (ret != CL_VIRUS || (!SCAN_ALLMATCHES && ret == CL_VIRUS))) {
return ret;
} else if (SCAN_ALL && ret == CL_VIRUS) {
} else if (SCAN_ALLMATCHES && ret == CL_VIRUS) {
virus = 1;
}

Expand Down Expand Up @@ -615,7 +615,7 @@ int cli_msxml_parse_document(cli_ctx *ctx, xmlTextReaderPtr reader, const struct
ret = msxml_parse_element(mxctx, reader, 0, NULL);
#endif
if (ret == CL_SUCCESS);
else if (SCAN_ALL && ret == CL_VIRUS) {
else if (SCAN_ALLMATCHES && ret == CL_VIRUS) {
/* non-allmatch simply propagates it down to return through ret */
virus = 1;
} else if (ret == CL_VIRUS || ret == CL_ETIMEOUT || ret == CL_BREAK) {
Expand Down
14 changes: 7 additions & 7 deletions libclamav/ole2_extract.c
Expand Up @@ -651,7 +651,7 @@ ole2_walk_property_tree(ole2_header_t * hdr, const char *dir, int32_t prop_index
if ((int)(prop_block[idx].child) != -1) {
ret = ole2_walk_property_tree(hdr, dir, prop_block[idx].child, handler, rec_level + 1, file_count, ctx, scansize);
if (ret != CL_SUCCESS) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS)) {
if (SCAN_ALLMATCHES && (ret == CL_VIRUS)) {
func_ret = ret;
}
else {
Expand Down Expand Up @@ -686,7 +686,7 @@ ole2_walk_property_tree(ole2_header_t * hdr, const char *dir, int32_t prop_index
ole2_listmsg("running file handler\n");
ret = handler(hdr, &prop_block[idx], dir, ctx);
if (ret != CL_SUCCESS) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS)) {
if (SCAN_ALLMATCHES && (ret == CL_VIRUS)) {
func_ret = ret;
}
else {
Expand All @@ -701,7 +701,7 @@ ole2_walk_property_tree(ole2_header_t * hdr, const char *dir, int32_t prop_index
if ((int)(prop_block[idx].child) != -1) {
ret = ole2_walk_property_tree(hdr, dir, prop_block[idx].child, handler, rec_level, file_count, ctx, scansize);
if (ret != CL_SUCCESS) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS)) {
if (SCAN_ALLMATCHES && (ret == CL_VIRUS)) {
func_ret = ret;
}
else {
Expand All @@ -727,7 +727,7 @@ ole2_walk_property_tree(ole2_header_t * hdr, const char *dir, int32_t prop_index
ole2_listmsg("directory node\n");
if (dir) {
#if HAVE_JSON
if ((ctx->options & CL_SCAN_FILE_PROPERTIES) && (ctx->wrkproperty != NULL)) {
if (SCAN_COLLECT_METADATA && (ctx->wrkproperty != NULL)) {
if (!json_object_object_get_ex(ctx->wrkproperty, "DigitalSignatures", NULL)) {
name = get_property_name2(prop_block[idx].name, prop_block[idx].name_size);
if (name) {
Expand Down Expand Up @@ -758,7 +758,7 @@ ole2_walk_property_tree(ole2_header_t * hdr, const char *dir, int32_t prop_index
if ((int)(prop_block[idx].child) != -1) {
ret = ole2_walk_property_tree(hdr, dirname, prop_block[idx].child, handler, rec_level + 1, file_count, ctx, scansize);
if (ret != CL_SUCCESS) {
if ((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS)) {
if (SCAN_ALLMATCHES && (ret == CL_VIRUS)) {
func_ret = ret;
}
else {
Expand Down Expand Up @@ -926,7 +926,7 @@ handler_enum(ole2_header_t * hdr, property_t * prop, const char *dir, cli_ctx *

name = get_property_name2(prop->name, prop->name_size);
if (name) {
if (ctx->options & CL_SCAN_FILE_PROPERTIES && ctx->wrkproperty != NULL) {
if (SCAN_COLLECT_METADATA && ctx->wrkproperty != NULL) {
arrobj = cli_jsonarray(ctx->wrkproperty, "Streams");
if (NULL == arrobj) {
cli_warnmsg("ole2: no memory for streams list or streams is not an array\n");
Expand Down Expand Up @@ -1340,7 +1340,7 @@ handler_otf(ole2_header_t * hdr, property_t * prop, const char *dir, cli_ctx * c

#if HAVE_JSON
/* JSON Output Summary Information */
if (ctx->options & CL_SCAN_FILE_PROPERTIES && ctx->properties != NULL) {
if (SCAN_COLLECT_METADATA && (ctx->properties != NULL)) {
if (!name)
name = get_property_name2(prop->name, prop->name_size);
if (name) {
Expand Down
16 changes: 8 additions & 8 deletions libclamav/others.c
Expand Up @@ -936,8 +936,8 @@ int cl_engine_settings_free(struct cl_settings *settings)

void cli_check_blockmax(cli_ctx *ctx, int rc)
{
if (BLOCKMAX && !ctx->limit_exceeded) {
cli_append_virus (ctx, "Heuristic.Limits.Exceeded");
if (SCAN_HEURISTIC_EXCEEDS_MAX && !ctx->limit_exceeded) {
cli_append_virus (ctx, "Heuristics.Limits.Exceeded");
ctx->limit_exceeded = 1;
cli_dbgmsg ("Limit %s Exceeded: scanning may be incomplete and additional analysis needed for this file.\n",
cl_strerror(rc));
Expand Down Expand Up @@ -1096,9 +1096,9 @@ void cli_virus_found_cb(cli_ctx * ctx)

int cli_append_possibly_unwanted(cli_ctx * ctx, const char * virname)
{
if (SCAN_ALL)
if (SCAN_ALLMATCHES)
return cli_append_virus(ctx, virname);
else if (ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE)
else if (SCAN_HEURISTIC_PRECEDENCE)
return cli_append_virus(ctx, virname);
else if (ctx->num_viruses == 0 && ctx->virname != NULL && *ctx->virname == NULL) {
ctx->found_possibly_unwanted = 1;
Expand All @@ -1114,16 +1114,16 @@ int cli_append_virus(cli_ctx * ctx, const char * virname)
return CL_CLEAN;
if (ctx->fmap != NULL && (*ctx->fmap) != NULL && CL_VIRUS != cli_checkfp_virus((*ctx->fmap)->maphash, (*ctx->fmap)->len, ctx, virname))
return CL_CLEAN;
if (!SCAN_ALL && ctx->num_viruses != 0)
if (ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE)
if (!SCAN_ALLMATCHES && ctx->num_viruses != 0)
if (SCAN_HEURISTIC_PRECEDENCE)
return CL_CLEAN;
if (ctx->limit_exceeded == 0 || SCAN_ALL) {
if (ctx->limit_exceeded == 0 || SCAN_ALLMATCHES) {
ctx->num_viruses++;
*ctx->virname = virname;
cli_virus_found_cb(ctx);
}
#if HAVE_JSON
if (SCAN_PROPERTIES && ctx->wrkproperty) {
if (SCAN_COLLECT_METADATA && ctx->wrkproperty) {
json_object *arrobj, *virobj;
if (!json_object_object_get_ex(ctx->wrkproperty, "Viruses", &arrobj)) {
arrobj = json_object_new_array();
Expand Down
51 changes: 32 additions & 19 deletions libclamav/others.h
Expand Up @@ -160,7 +160,7 @@ typedef struct cli_ctx_tag {
const struct cli_matcher *root;
const struct cl_engine *engine;
unsigned long scansize;
unsigned int options;
struct cl_scan_options *options;
unsigned int recursion;
unsigned int scannedfiles;
unsigned int found_possibly_unwanted;
Expand Down Expand Up @@ -490,24 +490,37 @@ extern int (*cli_unrar_extract_next)(unrar_state_t *state, const char *dirname);
extern void (*cli_unrar_close)(unrar_state_t *state);
extern int have_rar;

#define SCAN_ARCHIVE (ctx->options & CL_SCAN_ARCHIVE)
#define SCAN_MAIL (ctx->options & CL_SCAN_MAIL)
#define SCAN_OLE2 (ctx->options & CL_SCAN_OLE2)
#define SCAN_PDF (ctx->options & CL_SCAN_PDF)
#define SCAN_HTML (ctx->options & CL_SCAN_HTML)
#define SCAN_PE (ctx->options & CL_SCAN_PE)
#define SCAN_ELF (ctx->options & CL_SCAN_ELF)
#define SCAN_ALGO (ctx->options & CL_SCAN_ALGORITHMIC)
#define DETECT_ENCRYPTED (ctx->options & CL_SCAN_BLOCKENCRYPTED)
#define BLOCKMAX (ctx->options & CL_SCAN_BLOCKMAX)
#define DETECT_BROKEN (ctx->options & CL_SCAN_BLOCKBROKEN)
#define BLOCK_MACROS (ctx->options & CL_SCAN_BLOCKMACROS)
#define SCAN_STRUCTURED (ctx->options & CL_SCAN_STRUCTURED)
#define SCAN_ALL (ctx->options & CL_SCAN_ALLMATCHES)
#define SCAN_SWF (ctx->options & CL_SCAN_SWF)
#define SCAN_PROPERTIES (ctx->options & CL_SCAN_FILE_PROPERTIES)
#define SCAN_XMLDOCS (ctx->options & CL_SCAN_XMLDOCS)
#define SCAN_HWP3 (ctx->options & CL_SCAN_HWP3)
#define SCAN_ALLMATCHES (ctx->options->general & CL_SCAN_GENERAL_ALLMATCHES)
#define SCAN_COLLECT_METADATA (ctx->options->general & CL_SCAN_GENERAL_COLLECT_METADATA)
#define SCAN_HEURISTICS (ctx->options->general & CL_SCAN_GENERAL_HEURISTICS)
#define SCAN_HEURISTIC_PRECEDENCE (ctx->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE)

#define SCAN_PARSE_ARCHIVE (ctx->options->parse & CL_SCAN_PARSE_ARCHIVE)
#define SCAN_PARSE_ELF (ctx->options->parse & CL_SCAN_PARSE_ELF)
#define SCAN_PARSE_PDF (ctx->options->parse & CL_SCAN_PARSE_PDF)
#define SCAN_PARSE_SWF (ctx->options->parse & CL_SCAN_PARSE_SWF)
#define SCAN_PARSE_HWP3 (ctx->options->parse & CL_SCAN_PARSE_HWP3)
#define SCAN_PARSE_XMLDOCS (ctx->options->parse & CL_SCAN_PARSE_XMLDOCS)
#define SCAN_PARSE_MAIL (ctx->options->parse & CL_SCAN_PARSE_MAIL)
#define SCAN_PARSE_OLE2 (ctx->options->parse & CL_SCAN_PARSE_OLE2)
#define SCAN_PARSE_HTML (ctx->options->parse & CL_SCAN_PARSE_HTML)
#define SCAN_PARSE_PE (ctx->options->parse & CL_SCAN_PARSE_PE)

#define SCAN_HEURISTIC_BROKEN (ctx->options->heuristic & CL_SCAN_HEURISTIC_BROKEN)
#define SCAN_HEURISTIC_EXCEEDS_MAX (ctx->options->heuristic & CL_SCAN_HEURISTIC_EXCEEDS_MAX)
#define SCAN_HEURISTIC_PHISHING_SSL_MISMATCH (ctx->options->heuristic & CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH)
#define SCAN_HEURISTIC_PHISHING_CLOAK (ctx->options->heuristic & CL_SCAN_HEURISTIC_PHISHING_CLOAK)
#define SCAN_HEURISTIC_MACROS (ctx->options->heuristic & CL_SCAN_HEURISTIC_MACROS)
#define SCAN_HEURISTIC_ENCRYPTED (ctx->options->heuristic & CL_SCAN_HEURISTIC_ENCRYPTED)
#define SCAN_HEURISTIC_PARTITION_INTXN (ctx->options->heuristic & CL_SCAN_HEURISTIC_PARTITION_INTXN)
#define SCAN_HEURISTIC_STRUCTURED (ctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED)
#define SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL (ctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL)
#define SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED (ctx->options->heuristic & CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED)

#define SCAN_MAIL_PARTIAL_MESSAGE (ctx->options->mail & CL_SCAN_MAIL_PARTIAL_MESSAGE)

#define SCAN_DEV_COLLECT_SHA (ctx->options->dev & CL_SCAN_DEV_COLLECT_SHA)
#define SCAN_DEV_COLLECT_PERF_INFO (ctx->options->dev & CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO)

/* based on macros from A. Melnikoff */
#define cbswap16(v) (((v & 0xff) << 8) | (((v) >> 8) & 0xff))
Expand Down
74 changes: 49 additions & 25 deletions libclamav/pdf.c
Expand Up @@ -1362,6 +1362,7 @@ static int pdf_scan_contents(int fd, struct pdf_struct *pdf)

int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj, uint32_t flags)
{
cli_ctx *ctx = pdf->ctx;
char fullname[NAME_MAX + 1];
int fout;
ptrdiff_t sum = 0;
Expand Down Expand Up @@ -1618,7 +1619,7 @@ int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj, uint32_t flags)
if (dparams)
pdf_free_dict(dparams);

if (sum < 0 || (rc == CL_VIRUS && !(pdf->ctx->options & CL_SCAN_ALLMATCHES))) {
if (sum < 0 || ((rc == CL_VIRUS) && !SCAN_ALLMATCHES)) {
sum = 0; /* prevents post-filter scan */
break;
}
Expand Down Expand Up @@ -1725,7 +1726,7 @@ int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj, uint32_t flags)
if (rc2 == CL_VIRUS || rc == CL_SUCCESS)
rc = rc2;

if ((rc == CL_CLEAN) || ((rc == CL_VIRUS) && (pdf->ctx->options & CL_SCAN_ALLMATCHES))) {
if ((rc == CL_CLEAN) || ((rc == CL_VIRUS) && SCAN_ALLMATCHES)) {
unsigned int dumpid = 0;
for (dumpid = 0; dumpid < pdf->nobjs; dumpid++) {
if (pdf->objs[dumpid] == obj)
Expand All @@ -1736,7 +1737,7 @@ int pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj, uint32_t flags)
rc = rc2;
}

if (((rc == CL_CLEAN) || ((rc == CL_VIRUS) && (pdf->ctx->options & CL_SCAN_ALLMATCHES))) && (obj->flags & (1 << OBJ_CONTENTS))) {
if (((rc == CL_CLEAN) || ((rc == CL_VIRUS) && SCAN_ALLMATCHES)) && (obj->flags & (1 << OBJ_CONTENTS))) {
lseek(fout, 0, SEEK_SET);
cli_dbgmsg("pdf_extract_obj: dumping contents %u %u\n", obj->id>>8, obj->id&0xff);

Expand Down Expand Up @@ -2480,9 +2481,10 @@ static char *pdf_readstring(const char *q0, int len, const char *key, unsigned *
return s0;
}

if (*q == '<') {
if ((*q == '<') && (len >= 3)) {
start = ++q;
q = memchr(q+1, '>', len);
len -= 1;
q = memchr(q+1, '>', len-1);
if (!q)
return NULL;

Expand Down Expand Up @@ -3065,6 +3067,7 @@ cl_error_t pdf_find_and_extract_objs(struct pdf_struct *pdf, uint32_t *alerts)
int foundobj = 0;
unsigned int i = 0, j = 0;
uint32_t badobjects = 0;
cli_ctx *ctx = pdf->ctx;

/* parse PDF and find obj offsets */
while (CL_BREAK != (rv = pdf_findobj(pdf))) {
Expand Down Expand Up @@ -3096,7 +3099,7 @@ cl_error_t pdf_find_and_extract_objs(struct pdf_struct *pdf, uint32_t *alerts)
(pdf->flags & (1 << DECRYPTABLE_PDF)) ?
"decryptable" : "not decryptable, stream will probably fail to decompress");

if ((pdf->ctx->options & CL_SCAN_BLOCKENCRYPTED) &&
if (SCAN_HEURISTIC_ENCRYPTED &&
(pdf->flags & (1 << ENCRYPTED_PDF)) &&
!(pdf->flags & (1 << DECRYPTABLE_PDF)))
{
Expand All @@ -3106,7 +3109,7 @@ cl_error_t pdf_find_and_extract_objs(struct pdf_struct *pdf, uint32_t *alerts)
status = cli_append_virus(pdf->ctx, "Heuristics.Encrypted.PDF");
if (status == CL_VIRUS) {
alerts++;
if (pdf->ctx->options & CL_SCAN_ALLMATCHES)
if (SCAN_ALLMATCHES)
status = CL_CLEAN;
}
}
Expand All @@ -3116,7 +3119,7 @@ cl_error_t pdf_find_and_extract_objs(struct pdf_struct *pdf, uint32_t *alerts)
cli_dbgmsg("pdf_find_and_extract_objs: (parsed hooks) returned %d\n", status);
if (status == CL_VIRUS) {
alerts++;
if (pdf->ctx->options & CL_SCAN_ALLMATCHES) {
if (SCAN_ALLMATCHES) {
status = CL_CLEAN;
}
}
Expand Down Expand Up @@ -3144,7 +3147,7 @@ cl_error_t pdf_find_and_extract_objs(struct pdf_struct *pdf, uint32_t *alerts)
break;
case CL_VIRUS:
alerts++;
if (pdf->ctx->options & CL_SCAN_ALLMATCHES) {
if (SCAN_ALLMATCHES) {
status = CL_CLEAN;
}
break;
Expand Down Expand Up @@ -3351,7 +3354,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
pdf.startoff = offset;

rc = run_pdf_hooks(&pdf, PDF_PHASE_PRE, -1, -1);
if ((rc == CL_VIRUS) && SCAN_ALL) {
if ((rc == CL_VIRUS) && SCAN_ALLMATCHES) {
cli_dbgmsg("cli_pdf: (pre hooks) returned %d\n", rc);
alerts++;
rc = CL_CLEAN;
Expand Down Expand Up @@ -3383,12 +3386,12 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
rc = run_pdf_hooks(&pdf, PDF_PHASE_END, -1, -1);
if (rc == CL_VIRUS) {
alerts++;
if (SCAN_ALL) {
if (SCAN_ALLMATCHES) {
rc = CL_CLEAN;
}
}

if (!rc && SCAN_ALGO && (ctx->dconf->other & OTHER_CONF_PDFNAMEOBJ)) {
if (!rc && SCAN_HEURISTICS && (ctx->dconf->other & OTHER_CONF_PDFNAMEOBJ)) {
if (pdf.flags & (1 << ESCAPED_COMMON_PDFNAME)) {
/* for example /Fl#61te#44#65#63#6f#64#65 instead of /FlateDecode */
cli_append_possibly_unwanted(ctx, "Heuristics.PDF.ObfuscatedNameObject");
Expand Down Expand Up @@ -3657,6 +3660,7 @@ static void CCITTFaxDecode_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struc
#if HAVE_JSON
static void JBIG2Decode_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;
struct json_object *pdfobj, *jbig2arr;

UNUSEDPARAM(obj);
Expand All @@ -3665,7 +3669,7 @@ static void JBIG2Decode_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct p
if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->ctx->wrkproperty))
Expand Down Expand Up @@ -3753,14 +3757,15 @@ static void Sig_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_a
#if HAVE_JSON
static void JavaScript_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;
struct json_object *pdfobj, *jbig2arr;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->ctx->wrkproperty))
Expand Down Expand Up @@ -3822,12 +3827,14 @@ static void Page_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_
#if HAVE_JSON
static void Author_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.author)) {
Expand All @@ -3845,12 +3852,14 @@ static void Author_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfnam
#if HAVE_JSON
static void Creator_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.creator)) {
Expand All @@ -3868,12 +3877,14 @@ static void Creator_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfna
#if HAVE_JSON
static void ModificationDate_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.modificationdate)) {
Expand All @@ -3891,12 +3902,14 @@ static void ModificationDate_cb(struct pdf_struct *pdf, struct pdf_obj *obj, str
#if HAVE_JSON
static void CreationDate_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.creationdate)) {
Expand All @@ -3914,12 +3927,14 @@ static void CreationDate_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct
#if HAVE_JSON
static void Producer_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.producer)) {
Expand All @@ -3937,12 +3952,14 @@ static void Producer_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfn
#if HAVE_JSON
static void Title_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.title)) {
Expand All @@ -3960,12 +3977,14 @@ static void Title_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname
#if HAVE_JSON
static void Keywords_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.keywords)) {
Expand All @@ -3983,12 +4002,14 @@ static void Keywords_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfn
#if HAVE_JSON
static void Subject_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;

UNUSEDPARAM(act);

if (!(pdf))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

if (!(pdf->stats.subject)) {
Expand Down Expand Up @@ -4045,6 +4066,7 @@ static void XFA_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_a
#if HAVE_JSON
static void Pages_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;
struct pdf_array *array;
const char *objstart = (obj->objstm) ? (const char *)(obj->start + obj->objstm->streambuf)
: (const char *)(obj->start + pdf->map);
Expand All @@ -4059,7 +4081,7 @@ static void Pages_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname
if (!(pdf) || !(pdf->ctx->wrkproperty))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

objsize = obj_size(pdf, obj, 1);
Expand Down Expand Up @@ -4112,6 +4134,7 @@ static void Pages_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname
#if HAVE_JSON
static void Colors_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfname_action *act)
{
cli_ctx *ctx = pdf->ctx;
json_object *colorsobj, *pdfobj;
unsigned long ncolors;
char *p1;
Expand All @@ -4124,7 +4147,7 @@ static void Colors_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfnam
if (!(pdf) || !(pdf->ctx) || !(pdf->ctx->wrkproperty))
return;

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES))
if (!(SCAN_COLLECT_METADATA))
return;

objsize = obj_size(pdf, obj, 1);
Expand Down Expand Up @@ -4167,6 +4190,7 @@ static void Colors_cb(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdfnam
#if HAVE_JSON
static void pdf_export_json(struct pdf_struct *pdf)
{
cli_ctx *ctx = pdf->ctx;
json_object *pdfobj;
unsigned long i;

Expand All @@ -4177,7 +4201,7 @@ static void pdf_export_json(struct pdf_struct *pdf)
goto cleanup;
}

if (!(pdf->ctx->options & CL_SCAN_FILE_PROPERTIES) || !(pdf->ctx->wrkproperty)) {
if (!(SCAN_COLLECT_METADATA) || !(pdf->ctx->wrkproperty)) {
goto cleanup;
}

Expand Down
3 changes: 2 additions & 1 deletion libclamav/pdfdecode.c
Expand Up @@ -227,6 +227,7 @@ static ptrdiff_t pdf_decodestream_internal(
cl_error_t vir = CL_CLEAN;
cl_error_t retval = CL_SUCCESS;
ptrdiff_t bytes_scanned = -1;
cli_ctx *ctx = pdf->ctx;
const char *filter = NULL;
int i;

Expand Down Expand Up @@ -315,7 +316,7 @@ static ptrdiff_t pdf_decodestream_internal(
}

if (retval != CL_SUCCESS) {
if (retval == CL_VIRUS && pdf->ctx->options & CL_SCAN_ALLMATCHES) {
if (retval == CL_VIRUS && SCAN_ALLMATCHES) {
vir = CL_VIRUS;
} else {
const char* reason;
Expand Down
42 changes: 21 additions & 21 deletions libclamav/pe.c
Expand Up @@ -223,7 +223,7 @@ FSGSTUFF; \
#define CLI_UNPRESULTSFSG1(NAME,EXPR,GOOD,FREEME) CLI_UNPRESULTS_(NAME,FSGCASE(NAME,free(sections)),EXPR,GOOD,FREEME)
#define CLI_UNPRESULTSFSG2(NAME,EXPR,GOOD,FREEME) CLI_UNPRESULTS_(NAME,FSGCASE(NAME,(void)0),EXPR,GOOD,FREEME)

#define DETECT_BROKEN_PE (DETECT_BROKEN && !ctx->corrupted_input)
#define DETECT_BROKEN_PE (SCAN_HEURISTIC_BROKEN && !ctx->corrupted_input)

extern const unsigned int hashlen[];

Expand Down Expand Up @@ -598,7 +598,7 @@ static int scan_pe_mdb (cli_ctx * ctx, struct cli_exe_section *exe_section)
if (ret != CL_CLEAN) {
if (ret != CL_VIRUS)
break;
else if (!SCAN_ALL)
else if (!SCAN_ALLMATCHES)
break;
}
}
Expand All @@ -607,7 +607,7 @@ static int scan_pe_mdb (cli_ctx * ctx, struct cli_exe_section *exe_section)
if (ret != CL_CLEAN) {
if (ret != CL_VIRUS)
break;
else if (!SCAN_ALL)
else if (!SCAN_ALLMATCHES)
break;
}
}
Expand Down Expand Up @@ -2573,7 +2573,7 @@ static int scan_pe_imp(cli_ctx *ctx, struct pe_image_data_dir *dirs, struct cli_
if (ret != CL_CLEAN) {
if (ret != CL_VIRUS)
break;
else if (!SCAN_ALL)
else if (!SCAN_ALLMATCHES)
break;
}
}
Expand All @@ -2582,7 +2582,7 @@ static int scan_pe_imp(cli_ctx *ctx, struct pe_image_data_dir *dirs, struct cli_
if (ret != CL_CLEAN) {
if (ret != CL_VIRUS)
break;
else if (!SCAN_ALL)
else if (!SCAN_ALLMATCHES)
break;
}
}
Expand Down Expand Up @@ -2758,7 +2758,7 @@ int cli_scanpe(cli_ctx *ctx)
return CL_ETIMEOUT;
}

if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
pe_json = get_pe_property(ctx);
}
#endif
Expand Down Expand Up @@ -3119,7 +3119,7 @@ int cli_scanpe(cli_ctx *ctx)
}

#if HAVE_JSON
if (ctx->options & CL_SCAN_FILE_PROPERTIES) {
if (SCAN_COLLECT_METADATA) {
snprintf(jsonbuf, sizeof(jsonbuf), "0x%x", vep);
if (pe_json != NULL)
cli_jsonstr(pe_json, "EntryPoint", jsonbuf);
Expand Down Expand Up @@ -3349,7 +3349,7 @@ int cli_scanpe(cli_ctx *ctx)
}

if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */
if(SCAN_ALGO && (DCONF & PE_CONF_POLIPOS) && !*sname && exe_sections[i].vsz > 40000 && exe_sections[i].vsz < 70000 && exe_sections[i].chr == 0xe0000060) polipos = i;
if(SCAN_HEURISTICS && (DCONF & PE_CONF_POLIPOS) && !*sname && exe_sections[i].vsz > 40000 && exe_sections[i].vsz < 70000 && exe_sections[i].chr == 0xe0000060) polipos = i;

/* check hash section sigs */
if((DCONF & PE_CONF_MD5SECT) && ctx->engine->hm_mdb) {
Expand Down Expand Up @@ -3516,7 +3516,7 @@ int cli_scanpe(cli_ctx *ctx)
cli_warnmsg("cli_scanpe: NULL argument supplied\n");
break;
case CL_VIRUS:
if (SCAN_ALL)
if (SCAN_ALLMATCHES)
break;
/* intentional fall-through */
case CL_BREAK:
Expand All @@ -3530,15 +3530,15 @@ int cli_scanpe(cli_ctx *ctx)
/* Attempt to detect some popular polymorphic viruses */

/* W32.Parite.B */
if(SCAN_ALGO && (DCONF & PE_CONF_PARITE) && !dll && epsize == 4096 && ep == exe_sections[nsections - 1].raw) {
if(SCAN_HEURISTICS && (DCONF & PE_CONF_PARITE) && !dll && epsize == 4096 && ep == exe_sections[nsections - 1].raw) {
const char *pt = cli_memstr(epbuff, 4040, "\x47\x65\x74\x50\x72\x6f\x63\x41\x64\x64\x72\x65\x73\x73\x00", 15);
if(pt) {
pt += 15;
if((((uint32_t)cli_readint32(pt) ^ (uint32_t)cli_readint32(pt + 4)) == 0x505a4f) && (((uint32_t)cli_readint32(pt + 8) ^ (uint32_t)cli_readint32(pt + 12)) == 0xffffb) && (((uint32_t)cli_readint32(pt + 16) ^ (uint32_t)cli_readint32(pt + 20)) == 0xb8)) {
ret = cli_append_virus(ctx,"Heuristics.W32.Parite.B");
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
free(exe_sections);
return ret;
}
Expand All @@ -3554,7 +3554,7 @@ int cli_scanpe(cli_ctx *ctx)
}

/* Kriz */
if(SCAN_ALGO && (DCONF & PE_CONF_KRIZ) && epsize >= 200 && CLI_ISCONTAINED(exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz, ep, 0x0fd2) && epbuff[1]=='\x9c' && epbuff[2]=='\x60') {
if(SCAN_HEURISTICS && (DCONF & PE_CONF_KRIZ) && epsize >= 200 && CLI_ISCONTAINED(exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz, ep, 0x0fd2) && epbuff[1]=='\x9c' && epbuff[2]=='\x60') {
enum {KZSTRASH,KZSCDELTA,KZSPDELTA,KZSGETSIZE,KZSXORPRFX,KZSXOR,KZSDDELTA,KZSLOOP,KZSTOP};
uint8_t kzs[] = {KZSTRASH,KZSCDELTA,KZSPDELTA,KZSGETSIZE,KZSTRASH,KZSXORPRFX,KZSXOR,KZSTRASH,KZSDDELTA,KZSTRASH,KZSLOOP,KZSTOP};
uint8_t *kzstate = kzs;
Expand Down Expand Up @@ -3663,7 +3663,7 @@ int cli_scanpe(cli_ctx *ctx)
ret = cli_append_virus(ctx,"Heuristics.W32.Kriz");
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
free(exe_sections);
return ret;
}
Expand All @@ -3682,7 +3682,7 @@ int cli_scanpe(cli_ctx *ctx)
}

/* W32.Magistr.A/B */
if(SCAN_ALGO && (DCONF & PE_CONF_MAGISTR) && !dll && (nsections>1) && (exe_sections[nsections - 1].chr & 0x80000000)) {
if(SCAN_HEURISTICS && (DCONF & PE_CONF_MAGISTR) && !dll && (nsections>1) && (exe_sections[nsections - 1].chr & 0x80000000)) {
uint32_t rsize, vsize, dam = 0;

vsize = exe_sections[nsections - 1].uvsz;
Expand All @@ -3701,7 +3701,7 @@ int cli_scanpe(cli_ctx *ctx)
ret = cli_append_virus(ctx, dam ? "Heuristics.W32.Magistr.A.dam" : "Heuristics.W32.Magistr.A");
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
free(exe_sections);
return ret;
}
Expand All @@ -3723,7 +3723,7 @@ int cli_scanpe(cli_ctx *ctx)
ret = cli_append_virus(ctx,dam ? "Heuristics.W32.Magistr.B.dam" : "Heuristics.W32.Magistr.B");
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
free(exe_sections);
return ret;
}
Expand Down Expand Up @@ -3800,7 +3800,7 @@ int cli_scanpe(cli_ctx *ctx)
ret = cli_append_virus(ctx,"Heuristics.W32.Polipos.A");
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
free(jumps);
free(exe_sections);
return ret;
Expand All @@ -3821,7 +3821,7 @@ int cli_scanpe(cli_ctx *ctx)
}

/* Trojan.Swizzor.Gen */
if (SCAN_ALGO && (DCONF & PE_CONF_SWIZZOR) && nsections > 1 && fsize > 64*1024 && fsize < 4*1024*1024) {
if (SCAN_HEURISTICS && (DCONF & PE_CONF_SWIZZOR) && nsections > 1 && fsize > 64*1024 && fsize < 4*1024*1024) {
if(dirs[2].Size) {
struct swizz_stats *stats = cli_calloc(1, sizeof(*stats));
unsigned int m = 1000;
Expand All @@ -3836,7 +3836,7 @@ int cli_scanpe(cli_ctx *ctx)
ret = cli_append_virus(ctx,"Heuristics.Trojan.Swizzor.Gen");
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS) {
if (!SCAN_ALL) {
if (!SCAN_ALLMATCHES) {
free(stats);
free(exe_sections);
return ret;
Expand Down Expand Up @@ -4727,7 +4727,7 @@ int cli_scanpe(cli_ctx *ctx)
CLI_UNPTEMP("yC",(spinned,exe_sections,0));
CLI_UNPRESULTS("yC",(yc_decrypt(ctx, spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0));

if (SCAN_ALL && yc_unp_num_viruses != ctx->num_viruses) {
if (SCAN_ALLMATCHES && yc_unp_num_viruses != ctx->num_viruses) {
free(exe_sections);
return CL_VIRUS;
}
Expand Down Expand Up @@ -4991,7 +4991,7 @@ int cli_scanpe(cli_ctx *ctx)
return CL_ETIMEOUT;
#endif

if (SCAN_ALL && viruses_found)
if (SCAN_ALLMATCHES && viruses_found)
return CL_VIRUS;

return CL_CLEAN;
Expand Down
6 changes: 3 additions & 3 deletions libclamav/phishcheck.c
Expand Up @@ -739,7 +739,7 @@ int phishingScan(cli_ctx* ctx,tag_arguments_t* hrefs)
if(!pchk || pchk->is_disabled)
return CL_CLEAN;

if(!ctx->found_possibly_unwanted && !SCAN_ALL)
if(!ctx->found_possibly_unwanted && !SCAN_ALLMATCHES)
*ctx->virname=NULL;
#if 0
FILE *f = fopen("/home/edwin/quarantine/urls","r");
Expand Down Expand Up @@ -785,10 +785,10 @@ int phishingScan(cli_ctx* ctx,tag_arguments_t* hrefs)
urls.link_type |= LINKTYPE_IMAGE;
}
urls.always_check_flags = 0;
if (ctx->options & CL_SCAN_PHISHING_BLOCKSSL) {
if (SCAN_HEURISTIC_PHISHING_SSL_MISMATCH) {
urls.always_check_flags |= CHECK_SSL;
}
if (ctx->options & CL_SCAN_PHISHING_BLOCKCLOAK) {
if (SCAN_HEURISTIC_PHISHING_CLOAK) {
urls.always_check_flags |= CHECK_CLOAKING;
}
string_init_c(&urls.realLink,(char*)hrefs->value[i]);
Expand Down
295 changes: 150 additions & 145 deletions libclamav/scanners.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion libclamav/tiff.c
Expand Up @@ -146,7 +146,7 @@ int cli_parsetiff(cli_ctx *ctx)
if(entry.value + value_size > map->len) {
cli_warnmsg("cli_parsetiff: TFD entry field %u exceeds bounds of TIFF file [%llu > %llu]\n",
i, (long long unsigned)(entry.value + value_size), (long long unsigned)map->len);
return cli_append_virus(ctx, "Heuristic.TIFF.OutOfBoundsAccess");
return cli_append_virus(ctx, "Heuristics.TIFF.OutOfBoundsAccess");
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions libclamav/untar.c
Expand Up @@ -176,7 +176,7 @@ cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx)
if (!ctx->engine->keeptmp)
if (cli_unlink(fullname)) return CL_EUNLINK;
if (ret==CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
else
num_viruses++;
Expand Down Expand Up @@ -300,7 +300,7 @@ cli_untar(const char *dir, unsigned int posix, cli_ctx *ctx)
strncpy(name, block, 100);
name[100] = '\0';
if(cli_matchmeta(ctx, name, size, size, 0, files, 0, NULL) == CL_VIRUS) {
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return CL_VIRUS;
else
num_viruses++;
Expand Down
10 changes: 5 additions & 5 deletions libclamav/unzip.c
Expand Up @@ -542,7 +542,7 @@ static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int

if(cli_matchmeta(ctx, name, LH_csize, LH_usize, (LH_flags & F_ENCR)!=0, fc, LH_crc32, NULL) == CL_VIRUS) {
*ret = CL_VIRUS;
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
return 0;
virus_found = 1;
}
Expand All @@ -554,10 +554,10 @@ static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int
return 0;
}

if(detect_encrypted && (LH_flags & F_ENCR) && DETECT_ENCRYPTED) {
if(detect_encrypted && (LH_flags & F_ENCR) && SCAN_HEURISTIC_ENCRYPTED) {
cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n");
*ret = cli_append_virus(ctx, "Heuristics.Encrypted.Zip");
if ((*ret == CL_VIRUS && !SCAN_ALL) || *ret != CL_CLEAN) {
if ((*ret == CL_VIRUS && !SCAN_ALLMATCHES) || *ret != CL_CLEAN) {
fmap_unneed_off(map, loff, SIZEOF_LH);
return 0;
}
Expand Down Expand Up @@ -757,7 +757,7 @@ int cli_unzip(cli_ctx *ctx) {
}
#endif
if (ret != CL_CLEAN) {
if (ret == CL_VIRUS && SCAN_ALL) {
if (ret == CL_VIRUS && SCAN_ALLMATCHES) {
ret = CL_CLEAN;
virus_found = 1;
} else
Expand All @@ -772,7 +772,7 @@ int cli_unzip(cli_ctx *ctx) {
while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(map, lhoff, fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd, 1, zip_scan_cb))) {
fc++;
lhoff+=coff;
if (SCAN_ALL && ret == CL_VIRUS) {
if (SCAN_ALLMATCHES && ret == CL_VIRUS) {
ret = CL_CLEAN;
virus_found = 1;
}
Expand Down
8 changes: 4 additions & 4 deletions libclamav/xar.c
Expand Up @@ -285,7 +285,7 @@ static int xar_get_toc_data_values(xmlTextReaderPtr reader, size_t *length, size
reader - xmlTextReaderPtr
ctx - pointer to cli_ctx
Returns:
CL_SUCCESS - subdoc found and clean scan (or virus found and SCAN_ALL), or no subdocument
CL_SUCCESS - subdoc found and clean scan (or virus found and SCAN_ALLMATCHES), or no subdocument
other - error return code from cli_mem_scandesc()
*/
static int xar_scan_subdocuments(xmlTextReaderPtr reader, cli_ctx *ctx)
Expand Down Expand Up @@ -316,7 +316,7 @@ static int xar_scan_subdocuments(xmlTextReaderPtr reader, cli_ctx *ctx)
subdoc_len = xmlStrlen(subdoc);
cli_dbgmsg("cli_scanxar: in-memory scan of xml subdocument, len %i.\n", subdoc_len);
rc = cli_mem_scandesc(subdoc, subdoc_len, ctx);
if (rc == CL_VIRUS && SCAN_ALL)
if (rc == CL_VIRUS && SCAN_ALLMATCHES)
rc = CL_SUCCESS;

/* make a file to leave if --leave-temps in effect */
Expand Down Expand Up @@ -524,7 +524,7 @@ int cli_scanxar(cli_ctx *ctx)
cli_dbgmsg("cli_scanxar: scanning xar TOC xml in memory.\n");
rc = cli_mem_scandesc(toc, hdr.toc_length_decompressed, ctx);
if (rc != CL_SUCCESS) {
if (rc != CL_VIRUS || !SCAN_ALL)
if (rc != CL_VIRUS || !SCAN_ALLMATCHES)
goto exit_toc;
}

Expand Down Expand Up @@ -855,7 +855,7 @@ int cli_scanxar(cli_ctx *ctx)
if (rc != CL_SUCCESS) {
if (rc == CL_VIRUS) {
cli_dbgmsg("cli_scanxar: Infected with %s\n", cli_get_last_virus(ctx));
if (!SCAN_ALL)
if (!SCAN_ALLMATCHES)
goto exit_tmpfile;
} else if (rc != CL_BREAK) {
cli_dbgmsg("cli_scanxar: cli_magic_scandesc error %i\n", rc);
Expand Down
18 changes: 15 additions & 3 deletions sigtool/sigtool.c
Expand Up @@ -171,8 +171,12 @@ static int hashpe(const char *filename, unsigned int class, int type)
const char *fmptr;
struct cl_engine *engine;
cli_ctx ctx;
struct cl_scan_options options;
int fd, ret;

memset(&options, 0, sizeof(struct cl_scan_options));
ctx.options = &options;

/* build engine */
if(!(engine = cl_engine_new())) {
mprintf("!hashpe: Can't create new engine\n");
Expand Down Expand Up @@ -201,7 +205,7 @@ static int hashpe(const char *filename, unsigned int class, int type)
/* prepare context */
memset(&ctx, '\0', sizeof(cli_ctx));
ctx.engine = engine;
ctx.options = CL_SCAN_STDOPT;
ctx.options->parse = ~0;
ctx.containers = cli_calloc(sizeof(cli_ctx_container), engine->maxreclevel + 2);
if(!ctx.containers) {
cl_engine_free(engine);
Expand Down Expand Up @@ -2207,8 +2211,12 @@ static void matchsig(const char *sig, const char *offset, int fd)
STATBUF sb;
unsigned int matches = 0;
cli_ctx ctx;
struct cl_scan_options options;
int ret;

memset(&options, 0, sizeof(struct cl_scan_options));
ctx.options = &options;

mprintf("SUBSIG: %s\n", sig);

if(!(engine = cl_engine_new())) {
Expand Down Expand Up @@ -2236,7 +2244,7 @@ static void matchsig(const char *sig, const char *offset, int fd)
}
memset(&ctx, '\0', sizeof(cli_ctx));
ctx.engine = engine;
ctx.options = CL_SCAN_STDOPT;
ctx.options->parse = ~0;
ctx.containers = cli_calloc(sizeof(cli_ctx_container), engine->maxreclevel + 2);
if(!ctx.containers) {
cl_engine_free(engine);
Expand Down Expand Up @@ -3388,9 +3396,13 @@ static int dumpcerts(const struct optstruct *opts)
const char * fmptr;
struct cl_engine *engine;
cli_ctx ctx;
struct cl_scan_options options;
int fd, ret;
uint8_t shash1[SHA1_HASH_SIZE];

memset(&options, 0, sizeof(struct cl_scan_options));
ctx.options = &options;

logg_file = NULL;

filename = optget(opts, "print-certs")->strarg;
Expand Down Expand Up @@ -3430,7 +3442,7 @@ static int dumpcerts(const struct optstruct *opts)
/* prepare context */
memset(&ctx, '\0', sizeof(cli_ctx));
ctx.engine = engine;
ctx.options = CL_SCAN_STDOPT;
ctx.options->parse = ~0;
ctx.containers = cli_calloc(sizeof(cli_ctx_container), engine->maxreclevel + 2);
if(!ctx.containers) {
cl_engine_free(engine);
Expand Down
6 changes: 5 additions & 1 deletion unit_tests/check_bytecode.c
Expand Up @@ -62,9 +62,13 @@ static void runtest(const char *file, uint64_t expected, int fail, int nojit,
int fdin = -1;
char filestr[512];
const char * virname = NULL;
struct cl_scan_options options;

memset(&cctx, 0, sizeof(cctx));
cctx.options |= CL_SCAN_ALLMATCHES;
memset(&options, 0, sizeof(struct cl_scan_options));
cctx.options = &options;

cctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES;
cctx.virname = &virname;
cctx.engine = engine = cl_engine_new();
fail_unless(!!cctx.engine, "cannot create engine");
Expand Down
80 changes: 67 additions & 13 deletions unit_tests/check_clamav.c
Expand Up @@ -160,18 +160,22 @@ static int get_test_file(int i, char *file, unsigned fsize, unsigned long *size)
static struct cl_engine *g_engine;

#ifdef CHECK_HAVE_LOOPS
/* int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) */
/* int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, struct cl_scan_options* options) */
START_TEST (test_cl_scandesc)
{
const char *virname = NULL;
char file[256];
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;

int fd = get_test_file(_i, file, sizeof(file), &size);
cli_dbgmsg("scanning (scandesc) %s\n", file);
ret = cl_scandesc(fd, &virname, &scanned, g_engine, CL_SCAN_STDOPT);
ret = cl_scandesc(fd, &virname, &scanned, g_engine, &options);
cli_dbgmsg("scan end (scandesc) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -189,10 +193,15 @@ START_TEST (test_cl_scandesc_allscan)
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;
options.general |= CL_SCAN_GENERAL_ALLMATCHES;

int fd = get_test_file(_i, file, sizeof(file), &size);
cli_dbgmsg("scanning (scandesc) %s\n", file);
ret = cl_scandesc(fd, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT);
ret = cl_scandesc(fd, &virname, &scanned, g_engine, &options);

cli_dbgmsg("scan end (scandesc) %s\n", file);

Expand All @@ -212,12 +221,16 @@ START_TEST (test_cl_scanfile)
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;

int fd = get_test_file(_i, file, sizeof(file), &size);
close(fd);

cli_dbgmsg("scanning (scanfile) %s\n", file);
ret = cl_scanfile(file, &virname, &scanned, g_engine, CL_SCAN_STDOPT);
ret = cl_scanfile(file, &virname, &scanned, g_engine, &options);
cli_dbgmsg("scan end (scanfile) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -234,12 +247,17 @@ START_TEST (test_cl_scanfile_allscan)
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;
options.general |= CL_SCAN_GENERAL_ALLMATCHES;

int fd = get_test_file(_i, file, sizeof(file), &size);
close(fd);

cli_dbgmsg("scanning (scanfile_allscan) %s\n", file);
ret = cl_scanfile(file, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT);
ret = cl_scanfile(file, &virname, &scanned, g_engine, &options);
cli_dbgmsg("scan end (scanfile_allscan) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -256,13 +274,17 @@ START_TEST (test_cl_scanfile_callback)
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;

int fd = get_test_file(_i, file, sizeof(file), &size);
close(fd);

cli_dbgmsg("scanning (scanfile_cb) %s\n", file);
/* TODO: test callbacks */
ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (scanfile_cb) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -279,13 +301,18 @@ START_TEST (test_cl_scanfile_callback_allscan)
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;
options.general |= CL_SCAN_GENERAL_ALLMATCHES;

int fd = get_test_file(_i, file, sizeof(file), &size);
close(fd);

cli_dbgmsg("scanning (scanfile_cb_allscan) %s\n", file);
/* TODO: test callbacks */
ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (scanfile_cb_allscan) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -302,12 +329,16 @@ START_TEST (test_cl_scandesc_callback)
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;

int fd = get_test_file(_i, file, sizeof(file), &size);

cli_dbgmsg("scanning (scandesc_cb) %s\n", file);
/* TODO: test callbacks */
ret = cl_scandesc_callback(fd, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
ret = cl_scandesc_callback(fd, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (scandesc_cb) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -325,12 +356,17 @@ START_TEST (test_cl_scandesc_callback_allscan)
unsigned long size;
unsigned long int scanned = 0;
int ret;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;
options.general |= CL_SCAN_GENERAL_ALLMATCHES;

int fd = get_test_file(_i, file, sizeof(file), &size);

cli_dbgmsg("scanning (scandesc_cb_allscan) %s\n", file);
/* TODO: test callbacks */
ret = cl_scandesc_callback(fd, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
ret = cl_scandesc_callback(fd, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (scandesc_cb_allscan) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand Down Expand Up @@ -490,14 +526,18 @@ START_TEST (test_cl_scanmap_callback_handle)
int ret;
char file[256];
unsigned long size;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;

int fd = get_test_file(_i, file, sizeof(file), &size);
/* intentionally use different way than scanners.c for testing */
map = cl_fmap_open_handle(&fd, 0, size, pread_cb, 1);
fail_unless(!!map, "cl_fmap_open_handle");

cli_dbgmsg("scanning (handle) %s\n", file);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (handle) %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -516,14 +556,19 @@ START_TEST (test_cl_scanmap_callback_handle_allscan)
int ret;
char file[256];
unsigned long size;
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;
options.general |= CL_SCAN_GENERAL_ALLMATCHES;

int fd = get_test_file(_i, file, sizeof(file), &size);
/* intentionally use different way than scanners.c for testing */
map = cl_fmap_open_handle(&fd, 0, size, pread_cb, 1);
fail_unless(!!map, "cl_fmap_open_handle %s");

cli_dbgmsg("scanning (handle) allscan %s\n", file);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (handle) allscan %s\n", file);

if (!FALSE_NEGATIVE) {
Expand All @@ -543,6 +588,10 @@ START_TEST (test_cl_scanmap_callback_mem)
void *mem;
unsigned long size;
char file[256];
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;

int fd = get_test_file(_i, file, sizeof(file), &size);

Expand All @@ -554,7 +603,7 @@ START_TEST (test_cl_scanmap_callback_mem)
fail_unless(!!map, "cl_fmap_open_mem");

cli_dbgmsg("scanning (mem) %s\n", file);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (mem) %s\n", file);
if (!FALSE_NEGATIVE) {
fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
Expand All @@ -576,6 +625,11 @@ START_TEST (test_cl_scanmap_callback_mem_allscan)
void *mem;
unsigned long size;
char file[256];
struct cl_scan_options options;

memset(&options, 0, sizeof(struct cl_scan_options));
options.parse |= ~0;
options.general |= CL_SCAN_GENERAL_ALLMATCHES;

int fd = get_test_file(_i, file, sizeof(file), &size);

Expand All @@ -587,7 +641,7 @@ START_TEST (test_cl_scanmap_callback_mem_allscan)
fail_unless(!!map, "cl_fmap_open_mem %s");

cli_dbgmsg("scanning (mem) allscan %s\n", file);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, &options, NULL);
cli_dbgmsg("scan end (mem) allscan %s\n", file);
if (!FALSE_NEGATIVE) {
fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
Expand Down
18 changes: 15 additions & 3 deletions unit_tests/check_matchers.c
Expand Up @@ -155,13 +155,20 @@ static const struct pcre_testdata_s {
#endif /* HAVE_PCRE */

static cli_ctx ctx;
static struct cl_scan_options options;

static fmap_t *thefmap = NULL;
static const char *virname = NULL;
static void setup(void)
{
struct cli_matcher *root;
virname = NULL;
thefmap = NULL;

memset(&ctx, 0, sizeof(ctx));
memset(&options, 0, sizeof(struct cl_scan_options));
ctx.options = &options;

ctx.virname = &virname;
ctx.fmap = &thefmap;
ctx.engine = cl_engine_new();
Expand Down Expand Up @@ -208,6 +215,7 @@ START_TEST (test_ac_scanbuff) {
ret = cli_ac_initdata(&mdata, root->ac_partsigs, 0, 0, CLI_DEFAULT_AC_TRACKLEN);
fail_unless(ret == CL_SUCCESS, "cli_ac_initdata() failed");

ctx.options->general &= ~CL_SCAN_GENERAL_ALLMATCHES; /* make sure all-match is disabled */
for(i = 0; ac_testdata[i].data; i++) {
ret = cli_ac_scanbuff((const unsigned char*)ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL);
fail_unless_fmt(ret == CL_VIRUS, "cli_ac_scanbuff() failed for %s", ac_testdata[i].virname);
Expand Down Expand Up @@ -250,7 +258,7 @@ START_TEST (test_ac_scanbuff_allscan) {
ret = cli_ac_initdata(&mdata, root->ac_partsigs, 0, 0, CLI_DEFAULT_AC_TRACKLEN);
fail_unless(ret == CL_SUCCESS, "cli_ac_initdata() failed");

ctx.options |= CL_SCAN_ALLMATCHES;
ctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES; /* enable all-match */
for(i = 0; ac_testdata[i].data; i++) {
ret = cli_ac_scanbuff((const unsigned char*)ac_testdata[i].data, strlen(ac_testdata[i].data), &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL);
fail_unless_fmt(ret == CL_VIRUS, "cli_ac_scanbuff() failed for %s", ac_testdata[i].virname);
Expand Down Expand Up @@ -294,6 +302,7 @@ START_TEST (test_ac_scanbuff_ex) {
ret = cli_ac_initdata(&mdata, root->ac_partsigs, 0, 0, CLI_DEFAULT_AC_TRACKLEN);
fail_unless(ret == CL_SUCCESS, "[ac_ex] cli_ac_initdata() failed");

ctx.options->general &= ~CL_SCAN_GENERAL_ALLMATCHES; /* make sure all-match is disabled */
for(i = 0; ac_sigopts_testdata[i].data; i++) {
ret = cli_ac_scanbuff((const unsigned char*)ac_sigopts_testdata[i].data, ac_sigopts_testdata[i].dlength, &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL);
fail_unless_fmt(ret == ac_sigopts_testdata[i].expected_result, "[ac_ex] cli_ac_scanbuff() failed for %s (%d != %d)", ac_sigopts_testdata[i].virname, ret, ac_sigopts_testdata[i].expected_result);
Expand Down Expand Up @@ -335,7 +344,7 @@ START_TEST (test_ac_scanbuff_allscan_ex) {
ret = cli_ac_initdata(&mdata, root->ac_partsigs, 0, 0, CLI_DEFAULT_AC_TRACKLEN);
fail_unless(ret == CL_SUCCESS, "[ac_ex] cli_ac_initdata() failed");

ctx.options |= CL_SCAN_ALLMATCHES;
ctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES; /* enable all-match */
for(i = 0; ac_sigopts_testdata[i].data; i++) {
ret = cli_ac_scanbuff((const unsigned char*)ac_sigopts_testdata[i].data, ac_sigopts_testdata[i].dlength, &virname, NULL, NULL, root, &mdata, 0, 0, NULL, AC_SCAN_VIR, NULL);
fail_unless_fmt(ret == ac_sigopts_testdata[i].expected_result, "[ac_ex] cli_ac_scanbuff() failed for %s (%d != %d)", ac_sigopts_testdata[i].virname, ret, ac_sigopts_testdata[i].expected_result);
Expand Down Expand Up @@ -374,6 +383,7 @@ START_TEST (test_bm_scanbuff) {
ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");

ctx.options->general &= ~CL_SCAN_GENERAL_ALLMATCHES; /* make sure all-match is disabled */
ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL, NULL);
fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed");
fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n");
Expand Down Expand Up @@ -402,6 +412,7 @@ START_TEST (test_bm_scanbuff_allscan) {
ret = cli_parse_add(root, "Sig3", "babedead", 0, 0, 0, "*", 0, NULL, 0);
fail_unless(ret == CL_SUCCESS, "cli_parse_add() failed");

ctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES; /* enable all-match */
ret = cli_bm_scanbuff((const unsigned char*)"blah\xde\xad\xbe\xef", 12, &virname, NULL, root, 0, NULL, NULL, NULL);
fail_unless(ret == CL_VIRUS, "cli_bm_scanbuff() failed");
fail_unless(!strncmp(virname, "Sig2", 4), "Incorrect signature matched in cli_bm_scanbuff()\n");
Expand Down Expand Up @@ -448,6 +459,7 @@ START_TEST (test_pcre_scanbuff) {
ret = cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, root->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN);
fail_unless(ret == CL_SUCCESS, "[pcre] cli_ac_initdata() failed");

ctx.options->general &= ~CL_SCAN_GENERAL_ALLMATCHES; /* make sure all-match is disabled */
for(i = 0; pcre_testdata[i].data; i++) {
ret = cli_pcre_scanbuf((const unsigned char*)pcre_testdata[i].data, strlen(pcre_testdata[i].data), &virname, NULL, root, NULL, NULL, NULL);
fail_unless_fmt(ret == pcre_testdata[i].expected_result, "[pcre] cli_pcre_scanbuff() failed for %s (%d != %d)", pcre_testdata[i].virname, ret, pcre_testdata[i].expected_result);
Expand Down Expand Up @@ -500,7 +512,7 @@ START_TEST (test_pcre_scanbuff_allscan) {
ret = cli_ac_initdata(&mdata, root->ac_partsigs, root->ac_lsigs, root->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN);
fail_unless(ret == CL_SUCCESS, "[pcre] cli_ac_initdata() failed");

ctx.options |= CL_SCAN_ALLMATCHES;
ctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES; /* enable all-match */
for(i = 0; pcre_testdata[i].data; i++) {
ret = cli_pcre_scanbuf((const unsigned char*)pcre_testdata[i].data, strlen(pcre_testdata[i].data), &virname, NULL, root, NULL, NULL, NULL);
fail_unless_fmt(ret == pcre_testdata[i].expected_result, "[pcre] cli_pcre_scanbuff() failed for %s (%d != %d)", pcre_testdata[i].virname, ret, pcre_testdata[i].expected_result);
Expand Down
8 changes: 7 additions & 1 deletion unit_tests/check_regex.c
Expand Up @@ -367,11 +367,14 @@ static void do_phishing_test(const struct rtest *rtest)
{
char *realurl;
cli_ctx ctx;
struct cl_scan_options options;
const char *virname = NULL;
tag_arguments_t hrefs;
int rc;

memset(&ctx, 0, sizeof(ctx));
memset(&options, 0, sizeof(struct cl_scan_options));
ctx.options = &options;

realurl = cli_strdup(rtest->realurl);
fail_unless(!!realurl, "cli_strdup");
Expand Down Expand Up @@ -434,8 +437,11 @@ static void do_phishing_test_allscan(const struct rtest *rtest)
const char *virname = NULL;
tag_arguments_t hrefs;
int rc;
struct cl_scan_options options;

memset(&ctx, 0, sizeof(ctx));
memset(&options, 0, sizeof(struct cl_scan_options));
ctx.options = &options;

realurl = cli_strdup(rtest->realurl);
fail_unless(!!realurl, "cli_strdup");
Expand All @@ -453,7 +459,7 @@ static void do_phishing_test_allscan(const struct rtest *rtest)

ctx.engine = engine;
ctx.virname = &virname;
ctx.options |= CL_SCAN_ALLMATCHES;
ctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES;

rc = phishingScan(&ctx, &hrefs);

Expand Down
103 changes: 60 additions & 43 deletions win32/clamav-for-windows/clamav-for-windows/interface.c
Expand Up @@ -130,7 +130,7 @@ FILETIME last_chk_time = {0, 0};
typedef struct {
CLAM_SCAN_CALLBACK scancb;
void *scancb_ctx;
unsigned int scanopts;
struct cl_scan_options* scanopts;
_int64 *filetype;
} instance;

Expand Down Expand Up @@ -562,31 +562,46 @@ int CLAMAPI Scan_Uninitialize(void) {

int CLAMAPI Scan_CreateInstance(CClamAVScanner **ppScanner) {
instance *inst;
struct cl_scan_options *scanopts;

INFN();
if(!ppScanner)
FAIL(CL_ENULLARG, "NULL pScanner");
inst = (instance *)calloc(1, sizeof(*inst));
if(!inst)
FAIL(CL_EMEM, "CreateInstance: OOM");
FAIL(CL_EMEM, "CreateInstance: OOM");

scanopts = (struct cl_scan_options *)calloc(1, sizeof(struct cl_scan_options));
memset(scanopts, 0, sizeof(struct cl_scan_options));
if(!scanopts) {
free(inst);
FAIL(CL_EMEM, "CreateInstance: OOM");
}
inst->scanopts = scanopts;

if(lock_engine()) {
free(inst);
FAIL(CL_ELOCK, "Failed to lock engine");
free(inst->scanopts);
free(inst);
FAIL(CL_ELOCK, "CreateInstance: Failed to lock engine");
}
if(!engine) {
free(inst);
unlock_engine();
FAIL(CL_ESTATE, "Create instance called with no engine");
free(inst->scanopts);
free(inst);
unlock_engine();
FAIL(CL_ESTATE, "CreateInstance: Create instance called with no engine");
}
if(add_instance(inst)) {
free(inst);
unlock_engine();
FAIL(CL_EMEM, "add_instance failed");
free(inst->scanopts);
free(inst);
unlock_engine();
FAIL(CL_EMEM, "CreateInstance: add_instance failed");
}
unlock_engine();
inst->scanopts = CL_SCAN_STDOPT;
inst->scanopts->parser |= ~0; /* enable all parsers */
inst->scanopts->general |= CL_SCAN_GENERAL_HEURISTICS; /* enable heuristic alert options */
if (logg_verbose)
inst->scanopts |= CL_SCAN_PERFORMANCE_INFO;
inst->scanopts->dev |= CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO;

*ppScanner = (CClamAVScanner *)inst;
logg("Created new instance %p\n", inst);
WIN();
Expand All @@ -596,21 +611,23 @@ int CLAMAPI Scan_CreateInstance(CClamAVScanner **ppScanner) {
// No point in retrying more times since we are shutting down anyway.
int CLAMAPI Scan_DestroyInstance(CClamAVScanner *pScanner) {
int rc;
instance *inst = (instance*)pScanner;
INFN();
if(!pScanner)
FAIL(CL_ENULLARG, "NULL pScanner");
if((rc = del_instance((instance *)pScanner))) {
if (rc == CL_EBUSY) {
// wait for one of the scanner threads to finish, and retry again,
// that's better than caller always waiting 2 seconds to retry.
if (WaitForSingleObject(reload_event, 1000) != WAIT_OBJECT_0)
logg("Scan_DestroyInstance: timeout");
rc = del_instance((instance *)pScanner);
}
if (rc)
FAIL(rc, "del_instance failed for %p", pScanner);
}
free(pScanner);
FAIL(CL_ENULLARG, "NULL pScanner");
if((rc = del_instance(inst))) {
if (rc == CL_EBUSY) {
// wait for one of the scanner threads to finish, and retry again,
// that's better than caller always waiting 2 seconds to retry.
if (WaitForSingleObject(reload_event, 1000) != WAIT_OBJECT_0)
logg("Scan_DestroyInstance: timeout");
rc = del_instance(inst);
}
if (rc)
FAIL(rc, "del_instance failed for %p", pScanner);
}
free(inst->scanopts);
free(inst);
logg("in Scan_DestroyInstance: Instance %p destroyed\n", pScanner);
WIN();
}
Expand Down Expand Up @@ -656,39 +673,39 @@ int CLAMAPI Scan_SetOption(CClamAVScanner *pScanner, int option, void *value, un
switch(option) {
case CLAM_OPTION_SCAN_ARCHIVE:
logg("CLAM_OPTION_SCAN_ARCHIVE: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_ARCHIVE;
whichopt = CL_SCAN_PARSE_ARCHIVE;
break;
case CLAM_OPTION_SCAN_MAIL:
logg("CLAM_OPTION_SCAN_MAIL: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_MAIL;
whichopt = CL_SCAN_PARSE_MAIL;
break;
case CLAM_OPTION_SCAN_OLE2:
logg("CLAM_OPTION_SCAN_OLE2: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_OLE2;
whichopt = CL_SCAN_PARSE_OLE2;
break;
case CLAM_OPTION_SCAN_HTML:
logg("CLAM_OPTION_SCAN_HTML: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_HTML;
whichopt = CL_SCAN_PARSE_HTML;
break;
case CLAM_OPTION_SCAN_PE:
logg("CLAM_OPTION_SCAN_PE: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_PE;
whichopt = CL_SCAN_PARSE_PE;
break;
case CLAM_OPTION_SCAN_PDF:
logg("CLAM_OPTION_SCAN_PDF: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_PDF;
whichopt = CL_SCAN_PARSE_PDF;
break;
case CLAM_OPTION_SCAN_ALGORITHMIC:
logg("CLAM_OPTION_SCAN_ALGORITHMIC: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_ALGORITHMIC;
whichopt = CL_SCAN_GENERAL_HEURISTICS;
break;
case CLAM_OPTION_SCAN_ELF:
logg("CLAM_OPTION_SCAN_ELF: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_ELF;
whichopt = CL_SCAN_PARSE_ELF;
break;
case CLAM_OPTION_SCAN_SWF:
logg("CLAM_OPTION_SCAN_SWF: %s on instance %p\n", newval ? "enabled" : "disabled", inst);
whichopt = CL_SCAN_SWF;
whichopt = CL_SCAN_PARSE_SWF;
break;
default:
unlock_instances();
Expand Down Expand Up @@ -722,31 +739,31 @@ int CLAMAPI Scan_GetOption(CClamAVScanner *pScanner, int option, void *value, un
}
switch(option) {
case CLAM_OPTION_SCAN_ARCHIVE:
whichopt = CL_SCAN_ARCHIVE;
whichopt = CL_SCAN_PARSE_ARCHIVE;
break;
case CLAM_OPTION_SCAN_MAIL:
whichopt = CL_SCAN_MAIL;
whichopt = CL_SCAN_PARSE_MAIL;
break;
case CLAM_OPTION_SCAN_OLE2:
whichopt = CL_SCAN_OLE2;
whichopt = CL_SCAN_PARSE_OLE2;
break;
case CLAM_OPTION_SCAN_HTML:
whichopt = CL_SCAN_HTML;
whichopt = CL_SCAN_PARSE_HTML;
break;
case CLAM_OPTION_SCAN_PE:
whichopt = CL_SCAN_PE;
whichopt = CL_SCAN_PARSE_PE;
break;
case CLAM_OPTION_SCAN_PDF:
whichopt = CL_SCAN_PDF;
whichopt = CL_SCAN_PARSE_PDF;
break;
case CLAM_OPTION_SCAN_ALGORITHMIC:
whichopt = CL_SCAN_ALGORITHMIC;
whichopt = CL_SCAN_GENERAL_HEURISTICS;
break;
case CLAM_OPTION_SCAN_ELF:
whichopt = CL_SCAN_ELF;
whichopt = CL_SCAN_PARSE_ELF;
break;
case CLAM_OPTION_SCAN_SWF:
whichopt = CL_SCAN_SWF;
whichopt = CL_SCAN_PARSE_SWF;
break;
default:
unlock_instances();
Expand Down
2 changes: 1 addition & 1 deletion win32/conf_examples/clamd.conf.sample
Expand Up @@ -547,7 +547,7 @@ TCPAddr 127.0.0.1
#PCREMaxFileSize 100M

# When BlockMax is set, files exceeding the MaxFileSize, MaxScanSize, or MaxRecursion limit will be flagged
# with the virus "Heuristic.Limits.Exceeded".
# with the virus "Heuristics.Limits.Exceeded".
# Default: no
#BlockMax yes

Expand Down