mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 18:33:16 +00:00
Fix several coverity warnings
290424 Missing break in switch - In hash_match: Missing break statement between cases in switch statement 290414 Resource leak - In cli_scanishield_msi: Leak of memory or pointers to system resources. Memory leak in a fail case 288197 Resource leak - In decrypt_any: Leak of memory or pointers to system resources. Memory leak in a fail case 290426 Resource leak - In cli_magic_scan: Leak of memory or pointers to system resources. Leaked a file prefix when running with --save-temps 192923 Resource leak - In cli_scanrar: Leak of memory or pointers to system resources. Leaked a file descriptor if a virus was found in a RAR file comment 225146 Resource leak - In cli_scanegg: Leak of memory or pointers to system resources. Leaked a file descriptor if unable to write a comment file to disk 290425 Resource leak - In scan_common: Leak of memory or pointers to system resources. Memory leaks in various fail cases. Also changes cli_scanrar to write out the file comment only if --leave-temps is specified and scan the buffer (like what is done in cli_scanegg) instead of writing the file out, scanning that, and then deleting the file if --leave-temps is not specified. The unit tests stopped working when correcting an issue with a switch statement that determined what type of signature had matched on a Google SafeBrowsing GDB rule. Looking into the unit tests, it looks like the code had always assumed that the test cases would be detected by a malware test rule in unit_tests/input/daily.gdb, but now some of the tests get matched on the phishing test rule. I updated the test logic to be more clear, and added tests for both cases now. Fix some memory leaks in libclamav/scanners.c
This commit is contained in:
parent
e830b45ca7
commit
319bfb51a5
7 changed files with 130 additions and 71 deletions
|
@ -241,7 +241,12 @@ int cli_scanishield_msi(cli_ctx *ctx, off_t off)
|
|||
|
||||
/* FIXMEISHIELD: cleanup the spam below */
|
||||
cli_dbgmsg("ishield-msi: File %s (csize: %llx, unk1:%x unk2:%x unk3:%x unk4:%x unk5:%x unk6:%x unk7:%x unk8:%x unk9:%x unk10:%x unk11:%x)\n", key, (long long)csize, fb.unk1, fb.unk2, fb.unk3, fb.unk4, fb.unk5, fb.unk6, fb.unk7, fb.unk8, fb.unk9, fb.unk10, fb.unk11);
|
||||
if (!(tempfile = cli_gentemp(ctx->sub_tmpdir))) return CL_EMEM;
|
||||
if (!(tempfile = cli_gentemp(ctx->sub_tmpdir))) {
|
||||
if (NULL != filename) {
|
||||
free(filename);
|
||||
}
|
||||
return CL_EMEM;
|
||||
}
|
||||
if ((ofd = open(tempfile, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) < 0) {
|
||||
cli_dbgmsg("ishield-msi: failed to create file %s\n", tempfile);
|
||||
free(tempfile);
|
||||
|
|
|
@ -1265,6 +1265,7 @@ char *decrypt_any(struct pdf_struct *pdf, uint32_t id, const char *in, size_t *l
|
|||
memcpy(q, in, *length);
|
||||
if (false == arc4_init(&arc4, result, n)) {
|
||||
noisy_warnmsg("decrypt_any: failed to init arc4\n");
|
||||
free(q);
|
||||
return NULL;
|
||||
}
|
||||
arc4_apply(&arc4, q, (unsigned)*length); /* TODO: may truncate for very large lengths */
|
||||
|
@ -1281,10 +1282,6 @@ char *decrypt_any(struct pdf_struct *pdf, uint32_t id, const char *in, size_t *l
|
|||
break;
|
||||
case ENC_AESV3:
|
||||
cli_dbgmsg("decrypt_any: enc is aesv3\n");
|
||||
if (pdf->keylen == 0) {
|
||||
cli_dbgmsg("decrypt_any: no key\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aes_256cbc_decrypt((const unsigned char *)in, length, q, pdf->key, pdf->keylen, 1);
|
||||
|
||||
|
|
|
@ -1208,10 +1208,13 @@ static cl_error_t hash_match(const struct regex_matcher* rlist,
|
|||
break;
|
||||
case '1':
|
||||
*phishing_verdict = CL_PHISH_HASH1;
|
||||
break;
|
||||
case '2':
|
||||
*phishing_verdict = CL_PHISH_HASH2;
|
||||
break;
|
||||
default:
|
||||
*phishing_verdict = CL_PHISH_HASH0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,6 +472,9 @@ cl_error_t load_regex_matcher(struct cl_engine *engine, struct regex_matcher *ma
|
|||
if (!*buffer)
|
||||
continue; /* skip empty lines */
|
||||
|
||||
if (buffer[0] == '#')
|
||||
continue;
|
||||
|
||||
if (functionality_level_check(buffer))
|
||||
continue;
|
||||
|
||||
|
|
|
@ -272,6 +272,8 @@ static cl_error_t cli_scanrar(const char *filepath, int desc, cli_ctx *ctx)
|
|||
|
||||
/* If the archive header had a comment, write it to the comment dir. */
|
||||
if ((comment != NULL) && (comment_size > 0)) {
|
||||
|
||||
if (ctx->engine->keeptmp) {
|
||||
int comment_fd = -1;
|
||||
if (!(comment_fullpath = cli_gentemp_with_prefix(ctx->sub_tmpdir, "comments"))) {
|
||||
status = CL_EMEM;
|
||||
|
@ -285,14 +287,13 @@ static cl_error_t cli_scanrar(const char *filepath, int desc, cli_ctx *ctx)
|
|||
cli_dbgmsg("RAR: Writing the archive comment to temp file: %s\n", comment_fullpath);
|
||||
if (0 == write(comment_fd, comment, comment_size)) {
|
||||
cli_dbgmsg("RAR: ERROR: Failed to write to output file\n");
|
||||
} else {
|
||||
/* Scan the comment file */
|
||||
status = cli_magic_scan_file(comment_fullpath, ctx, NULL);
|
||||
}
|
||||
close(comment_fd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the tempfile if not --leave-temps */
|
||||
if (!ctx->engine->keeptmp)
|
||||
if (cli_unlink(comment_fullpath))
|
||||
cli_dbgmsg("RAR: Failed to unlink the extracted comment file: %s\n", comment_fullpath);
|
||||
/* Scan the comment */
|
||||
status = cli_magic_scan_buff(comment, comment_size, ctx, NULL);
|
||||
|
||||
if ((status == CL_VIRUS) && SCAN_ALLMATCHES) {
|
||||
status = CL_CLEAN;
|
||||
|
@ -302,9 +303,6 @@ static cl_error_t cli_scanrar(const char *filepath, int desc, cli_ctx *ctx)
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
close(comment_fd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read & scan each file header.
|
||||
|
@ -657,7 +655,6 @@ static cl_error_t cli_scanegg(cli_ctx *ctx, size_t sfx_offset)
|
|||
goto done;
|
||||
}
|
||||
free(prefix);
|
||||
prefix = NULL;
|
||||
|
||||
comment_fd = open(comment_fullpath, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600);
|
||||
if (comment_fd < 0) {
|
||||
|
@ -666,10 +663,8 @@ static cl_error_t cli_scanegg(cli_ctx *ctx, size_t sfx_offset)
|
|||
cli_dbgmsg("EGG: Writing the archive comment to temp file: %s\n", comment_fullpath);
|
||||
if (0 == write(comment_fd, comments[i], nComments)) {
|
||||
cli_dbgmsg("EGG: ERROR: Failed to write to output file\n");
|
||||
} else {
|
||||
close(comment_fd);
|
||||
comment_fd = -1;
|
||||
}
|
||||
close(comment_fd);
|
||||
}
|
||||
free(comment_fullpath);
|
||||
comment_fullpath = NULL;
|
||||
|
@ -3471,7 +3466,6 @@ cl_error_t cli_magic_scan(cli_ctx *ctx, cli_file_t type)
|
|||
void *parent_property = NULL;
|
||||
#endif
|
||||
|
||||
char *fmap_basename = NULL;
|
||||
char *old_temp_path = NULL;
|
||||
char *new_temp_path = NULL;
|
||||
|
||||
|
@ -3509,6 +3503,7 @@ cl_error_t cli_magic_scan(cli_ctx *ctx, cli_file_t type)
|
|||
}
|
||||
|
||||
if (ctx->engine->keeptmp) {
|
||||
char *fmap_basename = NULL;
|
||||
/*
|
||||
* Keep-temp enabled, so create a sub-directory to provide extraction directory recursion.
|
||||
*/
|
||||
|
@ -3518,6 +3513,7 @@ cl_error_t cli_magic_scan(cli_ctx *ctx, cli_file_t type)
|
|||
* The fmap has a name, lets include it in the new sub-directory.
|
||||
*/
|
||||
new_temp_path = cli_gentemp_with_prefix(ctx->sub_tmpdir, fmap_basename);
|
||||
free(fmap_basename);
|
||||
if (NULL == new_temp_path) {
|
||||
cli_errmsg("cli_magic_scan: Failed to generate temp directory name.\n");
|
||||
ret = CL_EMEM;
|
||||
|
@ -4582,6 +4578,7 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
|
||||
time_t current_time;
|
||||
struct tm tm_struct;
|
||||
fmap_t **fmap_head = NULL;
|
||||
|
||||
if (NULL == map) {
|
||||
return CL_ENULLARG;
|
||||
|
@ -4599,17 +4596,21 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
memcpy(ctx.options, scanoptions, sizeof(struct cl_scan_options));
|
||||
ctx.found_possibly_unwanted = 0;
|
||||
ctx.containers = cli_calloc(sizeof(cli_ctx_container), ctx.engine->maxreclevel + 2);
|
||||
if (!ctx.containers)
|
||||
return CL_EMEM;
|
||||
if (!ctx.containers) {
|
||||
rc = CL_EMEM;
|
||||
goto done;
|
||||
}
|
||||
cli_set_container(&ctx, CL_TYPE_ANY, 0);
|
||||
ctx.dconf = (struct cli_dconf *)engine->dconf;
|
||||
ctx.cb_ctx = context;
|
||||
ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 3);
|
||||
if (!ctx.fmap)
|
||||
return CL_EMEM;
|
||||
fmap_head = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 3);
|
||||
if (!fmap_head) {
|
||||
rc = CL_EMEM;
|
||||
goto done;
|
||||
}
|
||||
if (!(ctx.hook_lsig_matches = cli_bitset_init())) {
|
||||
free(ctx.fmap);
|
||||
return CL_EMEM;
|
||||
rc = CL_EMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4618,7 +4619,7 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
* fmap's file descriptor in the virus found callback (like for deferred
|
||||
* low-seveerity alerts).
|
||||
*/
|
||||
ctx.fmap++;
|
||||
ctx.fmap = fmap_head + 1;
|
||||
*ctx.fmap = map;
|
||||
|
||||
perf_init(&ctx);
|
||||
|
@ -4658,7 +4659,8 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
if (!localtime_r(¤t_time, &tm_struct)) {
|
||||
#endif
|
||||
cli_errmsg("scan_common: Failed to get local time.\n");
|
||||
return CL_ESTAT;
|
||||
rc = CL_ESTAT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ctx.engine->keeptmp) &&
|
||||
|
@ -4669,7 +4671,8 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
new_temp_prefix = cli_calloc(1, new_temp_prefix_len + 1);
|
||||
if (!new_temp_prefix) {
|
||||
cli_errmsg("scan_common: Failed to allocate memory for temp directory name.\n");
|
||||
return CL_EMEM;
|
||||
rc = CL_EMEM;
|
||||
goto done;
|
||||
}
|
||||
strftime(new_temp_prefix, new_temp_prefix_len, "%Y%m%d_%H%M%S-", &tm_struct);
|
||||
strcpy(new_temp_prefix + strlen("YYYYMMDD_HHMMSS-"), target_basename);
|
||||
|
@ -4679,7 +4682,8 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
new_temp_prefix = cli_calloc(1, new_temp_prefix_len + 1);
|
||||
if (!new_temp_prefix) {
|
||||
cli_errmsg("scan_common: Failed to allocate memory for temp directory name.\n");
|
||||
return CL_EMEM;
|
||||
rc = CL_EMEM;
|
||||
goto done;
|
||||
}
|
||||
strftime(new_temp_prefix, new_temp_prefix_len, "%Y%m%d_%H%M%S-scantemp", &tm_struct);
|
||||
}
|
||||
|
@ -4689,14 +4693,16 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
free(new_temp_prefix);
|
||||
if (NULL == new_temp_path) {
|
||||
cli_errmsg("scan_common: Failed to generate temp directory name.\n");
|
||||
return CL_EMEM;
|
||||
rc = CL_EMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ctx.sub_tmpdir = new_temp_path;
|
||||
|
||||
if (mkdir(ctx.sub_tmpdir, 0700)) {
|
||||
cli_errmsg("Can't create temporary directory for scan: %s.\n", ctx.sub_tmpdir);
|
||||
return CL_EACCES;
|
||||
rc = CL_EACCES;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cli_logg_setup(&ctx);
|
||||
|
@ -4801,6 +4807,9 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
}
|
||||
}
|
||||
|
||||
cli_logg_unsetup();
|
||||
|
||||
done:
|
||||
if (NULL != ctx.sub_tmpdir) {
|
||||
if (!ctx.engine->keeptmp) {
|
||||
(void)cli_rmdirs(ctx.sub_tmpdir);
|
||||
|
@ -4808,16 +4817,33 @@ static cl_error_t scan_common(cl_fmap_t *map, const char *filepath, const char *
|
|||
free(ctx.sub_tmpdir);
|
||||
}
|
||||
|
||||
if (NULL != target_basename) {
|
||||
free(target_basename);
|
||||
}
|
||||
|
||||
if (NULL != ctx.target_filepath) {
|
||||
free(ctx.target_filepath);
|
||||
}
|
||||
free(ctx.containers);
|
||||
cli_bitset_free(ctx.hook_lsig_matches);
|
||||
ctx.fmap--; /* Restore original fmap pointer */
|
||||
free(ctx.fmap);
|
||||
free(ctx.options);
|
||||
cli_logg_unsetup();
|
||||
|
||||
if (NULL != ctx.perf) {
|
||||
perf_done(&ctx);
|
||||
}
|
||||
|
||||
if (NULL != ctx.hook_lsig_matches) {
|
||||
cli_bitset_free(ctx.hook_lsig_matches);
|
||||
}
|
||||
|
||||
if (NULL != fmap_head) {
|
||||
free(fmap_head);
|
||||
}
|
||||
|
||||
if (NULL != ctx.containers) {
|
||||
free(ctx.containers);
|
||||
}
|
||||
|
||||
if (NULL != ctx.options) {
|
||||
free(ctx.options);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -219,11 +219,16 @@ static const struct rtest {
|
|||
"http://www.paypal.com", "pics.ebay.com", RTR_WHITELISTED},
|
||||
{NULL, "http://somefakeurl.example.com", "someotherdomain-key.com", RTR_CLEAN},
|
||||
{NULL, "http://somefakeurl.example.com", "someotherdomain.key.com", RTR_PHISH},
|
||||
{NULL, "http://1.test.example.com/something", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://1.test.example.com/2", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@1.test.example.com/2", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@1.test.example.com/2/test", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@1.test.example.com/", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://malware-test.example.com/something", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://phishing-test.example.com/something", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://sub.malware-test.example.com/2", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://sub.phishing-test.example.com/2", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@malware-test.example.com/2", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@phishing-test.example.com/2", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@malware-test.example.com/2/test", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@phishing-test.example.com/2/test", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@malware-test.example.com/", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://user@phishing-test.example.com/", "test", RTR_BLACKLISTED},
|
||||
{NULL, "http://x.exe", "http:///x.exe", RTR_CLEAN},
|
||||
{".+\\.ebayrtm\\.com([/?].*)?:[^.]+\\.ebay\\.(de|com|co\\.uk)/",
|
||||
"http://srx.main.ebayrtm.com",
|
||||
|
@ -430,8 +435,17 @@ static void do_phishing_test(const struct rtest *rtest)
|
|||
"this should be blacklisted, realURL: %s, displayURL: %s",
|
||||
rtest->realurl, rtest->displayurl);
|
||||
if (*ctx.virname) {
|
||||
char *phishingFound = strstr((const char *)*ctx.virname, "Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net");
|
||||
ck_assert_msg(phishingFound != NULL, "\n\t should be: Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net,\n\t but is: %s\n", *ctx.virname);
|
||||
char *phishingFound = NULL;
|
||||
char *detectionName = NULL;
|
||||
if (strstr(rtest->realurl, "malware-test")) {
|
||||
detectionName = "Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net";
|
||||
|
||||
} else if (strstr(rtest->realurl, "phishing-test")) {
|
||||
detectionName = "Heuristics.Safebrowsing.Suspected-phishing_safebrowsing.clamav.net";
|
||||
}
|
||||
ck_assert_msg(detectionName != NULL, "\n\t Blacklist test case error - malware-test or phishing-test not found in: %s\n", rtest->realurl);
|
||||
phishingFound = strstr((const char *)*ctx.virname, detectionName);
|
||||
ck_assert_msg(phishingFound != NULL, "\n\t should be: %s,\n\t but is: %s\n", detectionName, *ctx.virname);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -512,8 +526,17 @@ static void do_phishing_test_allscan(const struct rtest *rtest)
|
|||
"this should be blacklisted, realURL: %s, displayURL: %s",
|
||||
rtest->realurl, rtest->displayurl);
|
||||
if (*ctx.virname) {
|
||||
char *phishingFound = strstr((const char *)*ctx.virname, "Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net");
|
||||
ck_assert_msg(phishingFound != NULL, "\n\t should be: Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net,\n\t but is: %s\n", *ctx.virname);
|
||||
char *phishingFound = NULL;
|
||||
char *detectionName = NULL;
|
||||
if (strstr(rtest->realurl, "malware-test")) {
|
||||
detectionName = "Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net";
|
||||
|
||||
} else if (strstr(rtest->realurl, "phishing-test")) {
|
||||
detectionName = "Heuristics.Safebrowsing.Suspected-phishing_safebrowsing.clamav.net";
|
||||
}
|
||||
ck_assert_msg(detectionName != NULL, "\n\t Blacklist test case error - malware-test or phishing-test not found in: %s\n", rtest->realurl);
|
||||
phishingFound = strstr((const char *)*ctx.virname, detectionName);
|
||||
ck_assert_msg(phishingFound != NULL, "\n\t should be: %s,\n\t but is: %s\n", detectionName, *ctx.virname);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
S:P:d1b8a025
|
||||
S:F:d1b8a0251d7555d016b6468ae623e4b1e830c7efccc54966d09447a3d0a85c60
|
||||
S2:P:7f6fd541
|
||||
S2:F:7f6fd541e625e7bc5d5a64f166e47ecfe13735464a74d160b48265c162a71089
|
||||
# Google Safe Browsing Malware Site rule for malware-test.example.com/
|
||||
S:P:4d8bef53
|
||||
S:F:4d8bef53100a92ef3b9490dc234c6c4a6d0f45bf73cb13b166188cd802c1a080
|
||||
# Google Safe Browsing Phishing Site rule for phishing-test.example.com/
|
||||
S2:P:f396c58e
|
||||
S2:F:f396c58e768d8b9ddc6a21bc17c90be9a68e019d964c8003699ee17b3e4dd4b6
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue