Fix newly introduced VBA/XLM OLE2 bugs

Fix an infinite loop in the new XLM macro parser.

Fix error handling, resource cleanup in OLE2 parser.

Fix issues tracking detected "viruses" in VBA & OLE2 parsers affecting
non-allmatch (regular) scan mode, wherein multiple viruses may be found
but each record lost and the overall detection comes up clean.

Also silence switch() fall-through warning for WORD/PPT/XL/HWP (OOXML)
file type fall-throughs to the ZIP parser (because they are zips).

Also silence switch() fall-through warning when handling the limits-
exceeded error types, checking for the limits-exceeded heuristic, and
continuing on to bail out with a clean verdict.
pull/133/head
Micah Snyder 5 years ago committed by Micah Snyder (micasnyd)
parent 78c8cb0fe1
commit b1dbf93f0b
  1. 129
      libclamav/scanners.c
  2. 1
      libclamav/xlm_extract.c

@ -1632,10 +1632,10 @@ done:
return ret;
}
static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U)
static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U, int *hasmacros)
{
cl_error_t ret = CL_CLEAN;
int i, j, fd, hasmacros = 0;
int i, j, fd;
size_t data_len;
vba_project_t *vba_project;
DIR *dd;
@ -1669,7 +1669,7 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
cli_dbgmsg("VBADir: Decompress VBA project '%s_%u'\n", vba_project->name[i], j);
data = (unsigned char *)cli_vba_inflate(fd, vba_project->offset[i], &data_len);
close(fd);
hasmacros++;
*hasmacros = *hasmacros + 1;
if (!data) {
} else {
/* cli_dbgmsg("Project content:\n%s", data); */
@ -1695,9 +1695,8 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
}
if (vba_scandata(data, data_len, ctx) == CL_VIRUS) {
if (SCAN_ALLMATCHES)
viruses_found++;
else {
viruses_found++;
if (!SCAN_ALLMATCHES) {
free(data);
ret = CL_VIRUS;
break;
@ -1706,6 +1705,9 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
free(data);
}
}
if (ret == CL_VIRUS && !SCAN_ALLMATCHES)
break;
}
cli_free_vba_project(vba_project);
@ -1774,9 +1776,8 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
if (ctx->scanned)
*ctx->scanned += vba_project->length[i] / CL_COUNT_PRECISION;
if (vba_scandata(data, vba_project->length[i], ctx) == CL_VIRUS) {
if (SCAN_ALLMATCHES)
viruses_found++;
else {
viruses_found++;
if (!SCAN_ALLMATCHES) {
free(data);
ret = CL_VIRUS;
break;
@ -1791,9 +1792,8 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
vba_project = NULL;
if (ret == CL_VIRUS) {
if (SCAN_ALLMATCHES)
viruses_found++;
else
viruses_found++;
if (!SCAN_ALLMATCHES)
break;
}
hashcnt--;
@ -1883,10 +1883,9 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
/* stat the file */
if (LSTAT(fullname, &statbuf) != -1) {
if (S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
if (cli_vba_scandir(fullname, ctx, U) == CL_VIRUS) {
if (SCAN_ALLMATCHES)
viruses_found++;
else {
if (cli_vba_scandir(fullname, ctx, U, hasmacros) == CL_VIRUS) {
viruses_found++;
if (!SCAN_ALLMATCHES) {
ret = CL_VIRUS;
free(fullname);
break;
@ -1904,7 +1903,7 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
closedir(dd);
#if HAVE_JSON
if (hasmacros && SCAN_COLLECT_METADATA && (ctx->wrkproperty != NULL)) {
if (*hasmacros && SCAN_COLLECT_METADATA && (ctx->wrkproperty != NULL)) {
cli_jsonbool(ctx->wrkproperty, "HasMacros", 1);
json_object *macro_languages = cli_jsonarray(ctx->wrkproperty, "MacroLanguages");
if (macro_languages) {
@ -1914,7 +1913,7 @@ static cl_error_t cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq
}
}
#endif
if (SCAN_HEURISTIC_MACROS && hasmacros) {
if (SCAN_HEURISTIC_MACROS && *hasmacros) {
ret = cli_append_virus(ctx, "Heuristics.OLE2.ContainsMacros");
if (ret == CL_VIRUS)
viruses_found++;
@ -2309,67 +2308,111 @@ static cl_error_t cli_scanhtml_utf16(cli_ctx *ctx)
static cl_error_t cli_scanole2(cli_ctx *ctx)
{
char *dir;
char *dir = NULL;
cl_error_t ret = CL_CLEAN;
struct uniq *files = NULL;
int has_vba = 0, has_xlm = 0;
int has_vba = 0, has_xlm = 0, has_macros = 0, viruses_found = 0;
cli_dbgmsg("in cli_scanole2()\n");
if (ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
return CL_EMAXREC;
if (ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel) {
ret = CL_EMAXREC;
goto done;
}
/* generate the temporary directory */
if (!(dir = cli_gentemp_with_prefix(ctx->sub_tmpdir, "ole2-tmp")))
return CL_EMEM;
if (NULL == (dir = cli_gentemp_with_prefix(ctx->sub_tmpdir, "ole2-tmp"))) {
ret = CL_EMEM;
goto done;
}
if (mkdir(dir, 0700)) {
cli_dbgmsg("OLE2: Can't create temporary directory %s\n", dir);
free(dir);
return CL_ETMPDIR;
ret = CL_ETMPDIR;
goto done;
}
ret = cli_ole2_extract(dir, ctx, &files, &has_vba, &has_xlm);
if (ret != CL_CLEAN && ret != CL_VIRUS) {
cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
if (!ctx->engine->keeptmp)
cli_rmdirs(dir);
free(dir);
return ret;
goto done;
}
if (CL_VIRUS == ret) {
viruses_found++;
if (!SCAN_ALLMATCHES) {
ctx->recursion--;
goto done;
}
}
if (has_vba && files) {
ctx->recursion++;
ret = cli_vba_scandir(dir, ctx, files);
if (ret != CL_VIRUS) {
ret = cli_vba_scandir_new(dir, ctx, files);
ret = cli_vba_scandir(dir, ctx, files, &has_macros);
if (CL_VIRUS == ret) {
viruses_found++;
if (!SCAN_ALLMATCHES) {
ctx->recursion--;
goto done;
}
}
if (ret != CL_VIRUS)
if (cli_magic_scan_dir(dir, ctx) == CL_VIRUS)
ret = CL_VIRUS;
ret = cli_vba_scandir_new(dir, ctx, files);
if (CL_VIRUS == ret) {
viruses_found++;
if (!SCAN_ALLMATCHES) {
ctx->recursion--;
goto done;
}
}
if (cli_magic_scan_dir(dir, ctx) == CL_VIRUS)
ret = CL_VIRUS;
ctx->recursion--;
}
if (CL_VIRUS == ret) {
viruses_found++;
if (!SCAN_ALLMATCHES) {
goto done;
}
}
if (has_xlm && files) {
ctx->recursion++;
ret = cli_xlm_scandir(dir, ctx, files);
if (ret != CL_VIRUS)
if (cli_magic_scan_dir(dir, ctx) == CL_VIRUS)
ret = CL_VIRUS;
if (CL_VIRUS == ret) {
viruses_found++;
if (!SCAN_ALLMATCHES) {
ctx->recursion--;
goto done;
}
}
if (cli_magic_scan_dir(dir, ctx) == CL_VIRUS)
ret = CL_VIRUS;
ctx->recursion--;
}
if (viruses_found > 0) {
ret = CL_VIRUS;
}
done:
if (files) {
uniq_free(files);
files = NULL;
}
if (!ctx->engine->keeptmp)
cli_rmdirs(dir);
free(dir);
if (NULL != dir) {
if (!ctx->engine->keeptmp)
cli_rmdirs(dir);
free(dir);
}
return ret;
}
@ -3873,6 +3916,7 @@ cl_error_t cli_magic_scan(cli_ctx *ctx, cli_file_t type)
}
}
#endif
/* fall-through */
case CL_TYPE_ZIP:
if (SCAN_PARSE_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
ret = cli_unzip(ctx);
@ -4259,6 +4303,7 @@ cl_error_t cli_magic_scan(cli_ctx *ctx, cli_file_t type)
case CL_EMAXSIZE:
case CL_EMAXFILES:
cli_check_blockmax(ctx, ret);
/* fall-through */
/* Malformed file cases */
case CL_EFORMAT:
case CL_EREAD:

@ -3790,6 +3790,7 @@ static cl_error_t parse_formula(FILE *out_file, char data[], unsigned data_size)
goto done;
}
}
data_pos += 3 + str_len;
} else if (data[data_pos + 2] == 0 && data_pos + 2 + data[data_pos + 1] <= data_size) {
unsigned str_len = data[data_pos + 1];
if (str_len > data_size - data_pos) {

Loading…
Cancel
Save