libclamav: Fix fmap leak in bytecode runtime

Fixes an fmap leak in the bytecode switch_input() API.  The
switch_input() API provides a way to read from an extracted file instead
of reading from the current file.  The issue is that the current
implementation fails to free the fmap created to read from the extracted
file on cleanup or when switching back to the original fmap.  In
addition, it fails to use the cli_bytecode_context_setfile() function
to restore the file_size in the context for the current fmap.

Fixes a couple fmap leaks in the unit tests.
pull/119/head
Micah Snyder 5 years ago committed by Micah Snyder (micasnyd)
parent f5a2584609
commit 50455664a7
  1. 3
      libclamav/bytecode.c
  2. 62
      libclamav/bytecode_api.c
  3. 30
      unit_tests/check_clamav.c

@ -226,6 +226,9 @@ static int cli_bytecode_context_reset(struct cli_bc_ctx *ctx)
ctx->maps = NULL;
ctx->nmaps = 0;
/* Use input_switch() to free the extracted file fmap, if one exists */
cli_bcapi_input_switch(ctx, 0);
#if HAVE_JSON
free((json_object **)(ctx->jsonobjs));
ctx->jsonobjs = NULL;

@ -1473,26 +1473,54 @@ int32_t cli_bcapi_extract_set_container(struct cli_bc_ctx *ctx, uint32_t ftype)
int32_t cli_bcapi_input_switch(struct cli_bc_ctx *ctx, int32_t extracted_file)
{
fmap_t *map;
if (ctx->extracted_file_input == (unsigned int)extracted_file)
return 0;
if (!extracted_file) {
cli_dbgmsg("bytecode api: input switched back to main file\n");
ctx->fmap = ctx->save_map;
if (0 == extracted_file) {
/*
* Set input back to original fmap.
*/
if (0 == ctx->extracted_file_input) {
/* Input already set to original fmap, nothing to do. */
return 0;
}
/* Free the fmap used for the extracted file */
funmap(ctx->fmap);
/* Restore pointer to original fmap */
cli_bytecode_context_setfile(ctx, ctx->save_map);
ctx->save_map = NULL;
ctx->extracted_file_input = 0;
cli_dbgmsg("bytecode api: input switched back to main file\n");
return 0;
} else {
/*
* Set input to extracted file.
*/
if (1 == ctx->extracted_file_input) {
/* Input already set to extracted file, nothing to do. */
return 0;
}
if (ctx->outfd < 0) {
/* no valid fd to switch to use for fmap */
return -1;
}
/* Create fmap for the extracted file */
map = fmap(ctx->outfd, 0, 0);
if (!map) {
cli_warnmsg("can't mmap() extracted temporary file %s\n", ctx->tempfile);
return -1;
}
/* Save off pointer to original fmap */
ctx->save_map = ctx->fmap;
cli_bytecode_context_setfile(ctx, map);
ctx->extracted_file_input = 1;
cli_dbgmsg("bytecode api: input switched to extracted file\n");
return 0;
}
if (ctx->outfd < 0)
return -1;
map = fmap(ctx->outfd, 0, 0);
if (!map) {
cli_warnmsg("can't mmap() extracted temporary file %s\n", ctx->tempfile);
return -1;
}
ctx->save_map = ctx->fmap;
cli_bytecode_context_setfile(ctx, map);
ctx->extracted_file_input = 1;
cli_dbgmsg("bytecode api: input switched to extracted file\n");
return 0;
}
uint32_t cli_bcapi_get_environment(struct cli_bc_ctx *ctx, struct cli_environment *env, uint32_t len)

@ -84,7 +84,7 @@ START_TEST(test_cl_retver)
const char *ver = cl_retver();
ck_assert_msg(!strcmp(REPO_VERSION "" VERSION_SUFFIX, ver), "cl_retver");
ck_assert_msg(strcspn(ver, "012345789") < strlen(ver),
"cl_retver must have a number");
"cl_retver must have a number");
}
END_TEST
@ -137,7 +137,8 @@ END_TEST
/* extern unsigned int cl_retflevel(void); */
START_TEST(test_cl_retflevel)
{}
{
}
END_TEST
/* extern struct cl_cvd *cl_cvdhead(const char *file); */
@ -151,7 +152,8 @@ END_TEST
/* extern struct cl_cvd *cl_cvdparse(const char *head); */
START_TEST(test_cl_cvdparse)
{}
{
}
END_TEST
static int get_test_file(int i, char *file, unsigned fsize, unsigned long *size);
@ -376,32 +378,38 @@ END_TEST
/* int cl_load(const char *path, struct cl_engine **engine, unsigned int *signo, unsigned int options) */
START_TEST(test_cl_load)
{}
{
}
END_TEST
/* int cl_cvdverify(const char *file) */
START_TEST(test_cl_cvdverify)
{}
{
}
END_TEST
/* int cl_statinidir(const char *dirname, struct cl_stat *dbstat) */
START_TEST(test_cl_statinidir)
{}
{
}
END_TEST
/* int cl_statchkdir(const struct cl_stat *dbstat) */
START_TEST(test_cl_statchkdir)
{}
{
}
END_TEST
/* void cl_settempdir(const char *dir, short leavetemps) */
START_TEST(test_cl_settempdir)
{}
{
}
END_TEST
/* const char *cl_strerror(int clerror) */
START_TEST(test_cl_strerror)
{}
{
}
END_TEST
static char **testfiles = NULL;
@ -544,6 +552,7 @@ START_TEST(test_cl_scanmap_callback_handle)
ck_assert_msg(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
ck_assert_msg(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
}
cl_fmap_close(map);
close(fd);
}
END_TEST
@ -575,6 +584,7 @@ START_TEST(test_cl_scanmap_callback_handle_allscan)
ck_assert_msg(ret == CL_VIRUS, "cl_scanmap_callback allscan failed for %s: %s", file, cl_strerror(ret));
ck_assert_msg(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
}
cl_fmap_close(map);
close(fd);
}
END_TEST
@ -826,7 +836,7 @@ static const size_t dsig_tests_cnt = sizeof(dsig_tests) / sizeof(dsig_tests[0]);
START_TEST(test_cli_dsig)
{
ck_assert_msg(cli_versig(dsig_tests[_i].md5, dsig_tests[_i].dsig) == dsig_tests[_i].result,
"digital signature verification test failed");
"digital signature verification test failed");
}
END_TEST

Loading…
Cancel
Save