Browse code

bb11805 fix multiple results. Refactor false positive and heuristic precedence logic.

Steven Morgan authored on 2017/04/19 01:03:36
Showing 22 changed files
... ...
@@ -116,7 +116,7 @@ void clamd_virus_found_cb(int fd, const char *virname, void *ctx)
116 116
     
117 117
     if (d == NULL)
118 118
         return;
119
-    if (!(d->options & CL_SCAN_ALLMATCHES))
119
+    if (!(d->options & CL_SCAN_ALLMATCHES) && !(d->options & CL_SCAN_HEURISTIC_PRECEDENCE))
120 120
         return;
121 121
     if (virname == NULL)
122 122
         return;
... ...
@@ -124,6 +124,7 @@ void clamd_virus_found_cb(int fd, const char *virname, void *ctx)
124 124
     fname = (c && c->filename) ? c->filename : "(filename not set)";
125 125
 
126 126
     if (virname) {
127
+        d->infected++;
127 128
         conn_reply_virus(d->conn, fname, virname);
128 129
         if(c->virsize > 0 && optget(d->opts, "ExtendedDetectionInfo")->enabled)
129 130
             logg("~%s: %s(%s:%llu) FOUND\n", fname, virname, c->virhash, c->virsize);
... ...
@@ -274,19 +275,18 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_rea
274 274
     }
275 275
 
276 276
     if (ret == CL_VIRUS) {
277
-        scandata->infected++;
278 277
 
279
-        if (scandata->options & CL_SCAN_ALLMATCHES) {
278
+         if (scandata->options & CL_SCAN_ALLMATCHES || (scandata->infected && scandata->options & CL_SCAN_HEURISTIC_PRECEDENCE)) {
280 279
             if(optget(scandata->opts, "PreludeEnable")->enabled){
281 280
                 prelude_logging(filename, virname, context.virhash, context.virsize);
282 281
             }
283 282
             virusaction(filename, virname, scandata->opts);
284 283
         } else {
284
+           scandata->infected++;
285 285
             if (conn_reply_virus(scandata->conn, filename, virname) == -1) {
286 286
                 free(filename);
287 287
                 return CL_ETIMEOUT;
288 288
             }
289
-
290 289
             if(optget(scandata->opts, "PreludeEnable")->enabled){
291 290
                 prelude_logging(filename, virname, context.virhash, context.virsize);
292 291
             }
... ...
@@ -108,11 +108,7 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {
108 108
     res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
109 109
     if(res == SZ_ERROR_ENCRYPTED && DETECT_ENCRYPTED) {
110 110
 	cli_dbgmsg("cli_7unz: Encrypted header found in archive.\n");
111
-	cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
112
-	viruses_found++;
113
-	if(!SCAN_ALL) {
114
-	    found = CL_VIRUS;
115
-	}
111
+	found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
116 112
     } else if(res == SZ_OK) {
117 113
 	UInt32 i, blockIndex = 0xFFFFFFFF;
118 114
 	Byte *outBuffer = 0;
... ...
@@ -164,11 +160,13 @@ int cli_7unz (cli_ctx *ctx, size_t offset) {
164 164
 		encrypted = 1;
165 165
 		if(DETECT_ENCRYPTED) {
166 166
 		    cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
167
-		    cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
168
-		    viruses_found++;
169
-		    if(!SCAN_ALL) {
170
-			found = CL_VIRUS;
171
-			break;
167
+		    found = cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
168
+                    if (found != CL_CLEAN) {
169
+                        if (found == CL_VIRUS) {
170
+                            if (SCAN_ALL)
171
+                                viruses_found++;
172
+                        } else
173
+                            break;
172 174
 		    }
173 175
 		}
174 176
 	    }
... ...
@@ -248,6 +248,7 @@ static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size
248 248
     int ret = CL_CLEAN, tmp = CL_CLEAN;
249 249
     off_t pos;
250 250
     uint32_t max_prtns = 0;
251
+    int virus_found = 0;
251 252
 
252 253
     prtn_intxn_list_init(&prtncheck);
253 254
 
... ...
@@ -286,35 +287,30 @@ static int apm_prtn_intxn(cli_ctx *ctx, struct apm_partition_info *aptable, size
286 286
 
287 287
         tmp = prtn_intxn_list_check(&prtncheck, &pitxn, apentry.pBlockStart, apentry.pBlockCount);
288 288
         if (tmp != CL_CLEAN) {
289
-            if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
289
+            if (tmp == CL_VIRUS) {
290 290
                 apm_parsemsg("Name: %s\n", (char*)aptable.name);
291 291
                 apm_parsemsg("Type: %s\n", (char*)aptable.type);
292 292
 
293 293
                 cli_dbgmsg("cli_scanapm: detected intersection with partitions "
294 294
                            "[%u, %u]\n", pitxn, i);
295
-                cli_append_virus(ctx, PRTN_INTXN_DETECTION);
295
+                ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
296
+                if (ret == CL_VIRUS)
297
+                    virus_found = 1;
298
+                if (SCAN_ALL || ret == CL_CLEAN)
299
+                    tmp = 0;
300
+                else
301
+                    goto leave;
302
+            } else {
296 303
                 ret = tmp;
297
-                tmp = 0;
298
-            }
299
-            else if (tmp == CL_VIRUS) {
300
-                apm_parsemsg("Name: %s\n", (char*)aptable.name);
301
-                apm_parsemsg("Type: %s\n", (char*)aptable.type);
302
-
303
-                cli_dbgmsg("cli_scanapm: detected intersection with partitions "
304
-                           "[%u, %u]\n", pitxn, i);
305
-                cli_append_virus(ctx, PRTN_INTXN_DETECTION);
306
-                prtn_intxn_list_free(&prtncheck);
307
-                return CL_VIRUS;
308
-            }
309
-            else {
310
-                prtn_intxn_list_free(&prtncheck);
311
-                return tmp;
304
+                goto leave;
312 305
             }
313 306
         }
314
-
315 307
         pos += sectorsize;
316 308
     }
317 309
 
310
+ leave:
318 311
     prtn_intxn_list_free(&prtncheck);
312
+    if (virus_found)
313
+        return CL_VIRUS;
319 314
     return ret;
320 315
 }
... ...
@@ -2810,11 +2810,10 @@ int cli_bytecode_runlsig(cli_ctx *cctx, struct cli_target_info *tinfo,
2810 2810
     if (ctx.virname) {
2811 2811
 	int rc;
2812 2812
 	cli_dbgmsg("Bytecode found virus: %s\n", ctx.virname);
2813
-	cli_append_virus(cctx, ctx.virname);
2814 2813
 	if (!strncmp(ctx.virname, "BC.Heuristics", 13))
2815
-	    rc = cli_found_possibly_unwanted(cctx);
2816
-	else
2817
-	    rc = CL_VIRUS;
2814
+	    rc = cli_append_possibly_unwanted(cctx, ctx.virname);
2815
+        else
2816
+            rc = cli_append_virus(cctx, ctx.virname);
2818 2817
 	cli_bytecode_context_clear(&ctx);
2819 2818
 	return rc;
2820 2819
     }
... ...
@@ -80,6 +80,7 @@ struct cl_fmap {
80 80
     HANDLE fh;
81 81
     HANDLE mh;
82 82
 #endif
83
+    unsigned char maphash[16];
83 84
     uint32_t placeholder_for_bitmap;
84 85
 };
85 86
 
... ...
@@ -604,6 +604,7 @@ static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize
604 604
     off_t pos;
605 605
     size_t maplen;
606 606
     uint32_t max_prtns = 0;
607
+    int virus_found = 0;
607 608
 
608 609
     maplen = (*ctx->fmap)->real_len;
609 610
 
... ...
@@ -647,23 +648,19 @@ static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize
647 647
         else {
648 648
             tmp = prtn_intxn_list_check(&prtncheck, &pitxn, gpe.firstLBA, gpe.lastLBA - gpe.firstLBA + 1);
649 649
             if (tmp != CL_CLEAN) {
650
-                if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
650
+                if (tmp == CL_VIRUS) {
651 651
                     cli_dbgmsg("cli_scangpt: detected intersection with partitions "
652 652
                                "[%u, %u]\n", pitxn, i);
653
-                    cli_append_virus(ctx, PRTN_INTXN_DETECTION);
653
+                    ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
654
+                    if (ret == CL_VIRUS)
655
+                        virus_found = 1;
656
+                    if (SCAN_ALL || ret == CL_CLEAN)
657
+                        tmp = 0;
658
+                    else
659
+                        goto leave;
660
+                } else {
654 661
                     ret = tmp;
655
-                    tmp = 0;
656
-                }
657
-                else if (tmp == CL_VIRUS) {
658
-                    cli_dbgmsg("cli_scangpt: detected intersection with partitions "
659
-                               "[%u, %u]\n", pitxn, i);
660
-                    cli_append_virus(ctx, PRTN_INTXN_DETECTION);
661
-                    prtn_intxn_list_free(&prtncheck);
662
-                    return CL_VIRUS;
663
-                }
664
-                else {
665
-                    prtn_intxn_list_free(&prtncheck);
666
-                    return tmp;
662
+                    goto leave;
667 663
                 }
668 664
             }
669 665
         }
... ...
@@ -672,6 +669,9 @@ static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize
672 672
         pos += hdr.tableEntrySize;
673 673
     }
674 674
 
675
+ leave:
675 676
     prtn_intxn_list_free(&prtncheck);
677
+    if (virus_found)
678
+        return CL_VIRUS;
676 679
     return ret;
677 680
 }
... ...
@@ -176,8 +176,8 @@ struct macho_fat_arch
176 176
     if(matcher)						    \
177 177
 	return -1;					    \
178 178
     if(DETECT_BROKEN) {					    \
179
-	cli_append_virus(ctx, "Heuristics.Broken.Executable"); \
180
-	return CL_VIRUS;				    \
179
+        if (CL_VIRUS == cli_append_virus(ctx, "Heuristics.Broken.Executable")) \
180
+            return CL_VIRUS;				    \
181 181
     }							    \
182 182
     return CL_EFORMAT
183 183
 
... ...
@@ -738,16 +738,15 @@ int cli_pcre_scanbuf(const unsigned char *buffer, uint32_t length, const char **
738 738
                         newres->offset = adjbuffer+p_res.match[0];
739 739
                         *res = newres;
740 740
                     } else {
741
-                        if (ctx && SCAN_ALL) {
742
-                            viruses_found = 1;
743
-                            cli_append_virus(ctx, (const char *)pm->virname);
744
-                        }
741
+                        ret = CL_CLEAN;
742
+                        viruses_found = 1;
743
+                        if (ctx)
744
+                            ret = cli_append_virus(ctx, (const char *)pm->virname);
745 745
                         if (virname)
746 746
                             *virname = pm->virname;
747
-                        if (!ctx || !SCAN_ALL) {
748
-                            ret = CL_VIRUS;
749
-                            break;
750
-                        }
747
+                        if (!ctx || !SCAN_ALL)
748
+                            if (ret != CL_CLEAN)
749
+                                break;
751 750
                     }
752 751
                 }
753 752
             }
... ...
@@ -157,8 +157,9 @@ static inline int matcher_run(const struct cli_matcher *root,
157 157
 	    if (SCAN_ALL)
158 158
 		viruses_found = 1;
159 159
 	    else {
160
-		cli_append_virus(ctx, *virname);
161
-		return ret;
160
+		ret = cli_append_virus(ctx, *virname);
161
+		if (ret != CL_CLEAN)
162
+                    return ret;
162 163
 	    }
163 164
 	}
164 165
     }
... ...
@@ -169,8 +170,9 @@ static inline int matcher_run(const struct cli_matcher *root,
169 169
             if (SCAN_ALL)
170 170
                 viruses_found = 1;
171 171
             else {
172
-                cli_append_virus(ctx, *virname);
173
-                return ret;
172
+                ret = cli_append_virus(ctx, *virname);
173
+                if (ret != CL_CLEAN)
174
+                    return ret;
174 175
             }
175 176
         } else if (ret > CL_TYPENO && acmode & AC_SCAN_VIR)
176 177
             saved_ret = ret;
... ...
@@ -227,7 +229,7 @@ static inline int matcher_run(const struct cli_matcher *root,
227 227
     /* end experimental fragment */
228 228
 
229 229
     if (ctx && !SCAN_ALL && ret == CL_VIRUS)
230
-        cli_append_virus(ctx, *virname);
230
+        return cli_append_virus(ctx, *virname);
231 231
     if (ctx && SCAN_ALL && viruses_found)
232 232
         return CL_VIRUS;
233 233
 
... ...
@@ -501,6 +503,11 @@ void cli_targetinfo(struct cli_target_info *info, unsigned int target, fmap_t *m
501 501
 
502 502
 int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
503 503
 {
504
+    return cli_checkfp_virus(digest, size, ctx, NULL);
505
+}
506
+
507
+int cli_checkfp_virus(unsigned char *digest, size_t size, cli_ctx *ctx, const char * vname)
508
+{
504 509
     char md5[33];
505 510
     unsigned int i;
506 511
     const char *virname=NULL;
... ...
@@ -525,11 +532,11 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
525 525
             sprintf(md5 + i * 2, "%02x", digest[i]);
526 526
         md5[32] = 0;
527 527
         cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) size,
528
-               cli_get_last_virus(ctx) ? cli_get_last_virus(ctx) : "Name");
528
+                   vname ? vname : "Name");
529 529
     }
530 530
 
531
-    if(cli_get_last_virus(ctx))
532
-        do_dsig_check = strncmp("W32S.", cli_get_last_virus(ctx), 5);
531
+    if(vname)
532
+        do_dsig_check = strncmp("W32S.", vname, 5);
533 533
 
534 534
     map = *ctx->fmap;
535 535
     have_sha1 = cli_hm_have_size(ctx->engine->hm_fp, CLI_HASH_SHA1, size)
... ...
@@ -586,7 +593,7 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
586 586
             for(i=0; i<SHA1_HASH_SIZE; i++)
587 587
                 sprintf((char *)shash1+i*2, "%02x", shash1[SHA1_HASH_SIZE+i]);
588 588
 
589
-            cli_errmsg("COLLECT:%s:%s:%u:%s:%s\n", shash256, shash1, size, cli_get_last_virus(ctx), ctx->entry_filename);
589
+            cli_errmsg("COLLECT:%s:%s:%u:%s:%s\n", shash256, shash1, size, vname?vname:"noname", ctx->entry_filename);
590 590
         } else
591 591
             cli_errmsg("can't compute sha\n!");
592 592
 
... ...
@@ -614,10 +621,10 @@ int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx)
614 614
     }
615 615
 
616 616
     if (ctx->engine->cb_hash)
617
-        ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, (const unsigned char *)md5, cli_get_last_virus(ctx), ctx->cb_ctx);
617
+        ctx->engine->cb_hash(fmap_fd(*ctx->fmap), size, (const unsigned char *)md5, vname?vname:"noname", ctx->cb_ctx);
618 618
 
619 619
     if (ctx->engine->cb_stats_add_sample)
620
-        ctx->engine->cb_stats_add_sample(cli_get_last_virus(ctx), digest, size, &sections, ctx->engine->stats_data);
620
+        ctx->engine->cb_stats_add_sample(vname?vname:"noname", digest, size, &sections, ctx->engine->stats_data);
621 621
 
622 622
     if (sections.sections)
623 623
         free(sections.sections);
... ...
@@ -768,8 +775,9 @@ static int lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data
768 768
                 return CL_CLEAN;
769 769
             if(matchicon(ctx, &target_info->exeinfo, ac_lsig->tdb.icongrp1, ac_lsig->tdb.icongrp2) == CL_VIRUS) {
770 770
                 if(!ac_lsig->bc_idx) {
771
-                    cli_append_virus(ctx, ac_lsig->virname);
772
-                    return CL_VIRUS;
771
+                    rc = cli_append_virus(ctx, ac_lsig->virname);
772
+                    if (rc != CL_CLEAN)
773
+                        return rc;
773 774
                 } else if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, ac_lsig->bc_idx, acdata->lsigcnt[lsid], acdata->lsigsuboff_first[lsid], map) == CL_VIRUS) {
774 775
                     return CL_VIRUS;
775 776
                 }
... ...
@@ -777,8 +785,9 @@ static int lsig_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data
777 777
             return CL_CLEAN;
778 778
         }
779 779
         if(!ac_lsig->bc_idx) {
780
-            cli_append_virus(ctx, ac_lsig->virname);
781
-            return CL_VIRUS;
780
+            rc = cli_append_virus(ctx, ac_lsig->virname);
781
+            if (rc != CL_CLEAN)
782
+                return rc;
782 783
         }
783 784
         if(cli_bytecode_runlsig(ctx, target_info, &ctx->engine->bcs, ac_lsig->bc_idx, acdata->lsigcnt[lsid], acdata->lsigsuboff_first[lsid], map) == CL_VIRUS) {
784 785
             return CL_VIRUS;
... ...
@@ -808,7 +817,7 @@ static int yara_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data
808 808
         if (ac_lsig->flag & CLI_LSIG_FLAG_PRIVATE) {
809 809
             rc = CL_CLEAN;
810 810
         } else {
811
-            cli_append_virus(ctx, ac_lsig->virname);
811
+            rc = cli_append_virus(ctx, ac_lsig->virname);
812 812
         }
813 813
     }
814 814
     return rc;
... ...
@@ -1172,19 +1181,18 @@ int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli
1172 1172
             /* If matched size-based hash ... */
1173 1173
             if (found % 2) {
1174 1174
                 viruses_found = 1;
1175
-                cli_append_virus(ctx, virname);
1176
-                if (!SCAN_ALL)
1175
+                ret = cli_append_virus(ctx, virname);
1176
+                if (!SCAN_ALL || ret != CL_CLEAN)
1177 1177
                     break;
1178 1178
                 virname = NULL;
1179 1179
             }
1180 1180
             /* If matched size-agnostic hash ... */
1181 1181
             if (found > 1) {
1182 1182
                 viruses_found = 1;
1183
-                cli_append_virus(ctx, virname_w);
1184
-
1185
-                if (!SCAN_ALL)
1183
+                ret = cli_append_virus(ctx, virname_w);
1184
+                if (!SCAN_ALL || ret != CL_CLEAN)
1186 1185
                     break;
1187
-            }
1186
+             }
1188 1187
         }
1189 1188
     }
1190 1189
 
... ...
@@ -1228,6 +1236,7 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,
1228 1228
 {
1229 1229
 	const struct cli_cdb *cdb;
1230 1230
 	unsigned int viruses_found = 0;
1231
+        int ret = CL_CLEAN;
1231 1232
 
1232 1233
     cli_dbgmsg("CDBNAME:%s:%llu:%s:%llu:%llu:%d:%u:%u:%p\n",
1233 1234
 	       cli_ftname(cli_get_container_type(ctx, -1)), (long long unsigned)fsizec, fname, (long long unsigned)fsizec, (long long unsigned)fsizer,
... ...
@@ -1237,10 +1246,10 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,
1237 1237
 	if (ctx->engine->cb_meta(cli_ftname(cli_get_container_type(ctx, -1)), fsizec, fname, fsizer, encrypted, filepos, ctx->cb_ctx) == CL_VIRUS) {
1238 1238
 	    cli_dbgmsg("inner file blacklisted by callback: %s\n", fname);
1239 1239
 
1240
-	    cli_append_virus(ctx, "Detected.By.Callback");
1240
+	    ret = cli_append_virus(ctx, "Detected.By.Callback");
1241 1241
 	    viruses_found++;
1242
-	    if(!SCAN_ALL)
1243
-		return CL_VIRUS;
1242
+	    if(!SCAN_ALL || ret != CL_CLEAN)
1243
+		return ret;
1244 1244
 	}
1245 1245
 
1246 1246
     if(!ctx->engine || !(cdb = ctx->engine->cdb))
... ...
@@ -1273,10 +1282,10 @@ int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer,
1273 1273
 	if(cdb->name.re_magic && (!fname || cli_regexec(&cdb->name, fname, 0, NULL, 0) == REG_NOMATCH))
1274 1274
 	    continue;
1275 1275
 
1276
-	cli_append_virus(ctx, cdb->virname);
1276
+	ret = cli_append_virus(ctx, cdb->virname);
1277 1277
 	viruses_found++;
1278
-	if(!SCAN_ALL)
1279
-	    return CL_VIRUS;
1278
+	if(!SCAN_ALL || ret != CL_CLEAN)
1279
+	    return ret;
1280 1280
 
1281 1281
     } while((cdb = cdb->next));
1282 1282
 
... ...
@@ -208,6 +208,7 @@ int cli_exp_eval(cli_ctx *ctx, struct cli_matcher *root, struct cli_ac_data *acd
208 208
 int cli_caloff(const char *offstr, const struct cli_target_info *info, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max);
209 209
 
210 210
 int cli_checkfp(unsigned char *digest, size_t size, cli_ctx *ctx);
211
+int cli_checkfp_virus(unsigned char *digest, size_t size, cli_ctx *ctx, const char * vname);
211 212
 
212 213
 int cli_matchmeta(cli_ctx *ctx, const char *fname, size_t fsizec, size_t fsizer, int encrypted, unsigned int filepos, int res1, void *res2);
213 214
 
... ...
@@ -590,9 +590,8 @@ cli_parse_mbox(const char *dir, cli_ctx *ctx)
590 590
 	
591 591
 	if((retcode == CL_CLEAN) && ctx->found_possibly_unwanted &&
592 592
 	   (*ctx->virname == NULL || SCAN_ALL)) {
593
-	    cli_append_virus(ctx, "Heuristics.Phishing.Email");
593
+	    retcode = cli_append_virus(ctx, "Heuristics.Phishing.Email");
594 594
 	    ctx->found_possibly_unwanted = 0;
595
-	    retcode = CL_VIRUS;
596 595
 	}
597 596
 
598 597
 	cli_dbgmsg("cli_mbox returning %d\n", retcode);
... ...
@@ -502,23 +502,17 @@ static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size
502 502
             tmp = prtn_intxn_list_check(&prtncheck, &pitxn, mbr.entries[i].firstLBA,
503 503
                                         mbr.entries[i].numLBA);
504 504
             if (tmp != CL_CLEAN) {
505
-                if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
505
+                if (tmp == CL_VIRUS) {
506 506
                     cli_dbgmsg("cli_scanmbr: detected intersection with partitions "
507 507
                                "[%u, %u]\n", pitxn, i);
508
-                    cli_append_virus(ctx, PRTN_INTXN_DETECTION);
508
+                    ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
509
+                    if (SCAN_ALL || ret == CL_CLEAN)
510
+                        tmp = 0;
511
+                    else
512
+                        goto leave;
513
+                } else {
509 514
                     ret = tmp;
510
-                    tmp = 0;
511
-                }
512
-                else if (tmp == CL_VIRUS) {
513
-                    cli_dbgmsg("cli_scanmbr: detected intersection with partitions "
514
-                               "[%u, %u]\n", pitxn, i);
515
-                    cli_append_virus(ctx, PRTN_INTXN_DETECTION);
516
-                    prtn_intxn_list_free(&prtncheck);
517
-                    return CL_VIRUS;
518
-                }
519
-                else {
520
-                    prtn_intxn_list_free(&prtncheck);
521
-                    return tmp;
515
+                    goto leave;
522 516
                 }
523 517
             }
524 518
 
... ...
@@ -547,6 +541,7 @@ static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size
547 547
         }
548 548
     }
549 549
 
550
+leave:
550 551
     prtn_intxn_list_free(&prtncheck);
551 552
     return ret;
552 553
 }
... ...
@@ -559,6 +554,7 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
559 559
     unsigned i, pitxn;
560 560
     int ret = CL_CLEAN, tmp = CL_CLEAN, mbr_base = 0;
561 561
     off_t pos = 0, logiclba = 0;
562
+    int virus_found = 0;
562 563
 
563 564
     mbr_base = sectorsize - sizeof(struct mbr_boot_record);
564 565
 
... ...
@@ -585,23 +581,19 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
585 585
         /* assume that logical record is first and extended is second */
586 586
         tmp = prtn_intxn_list_check(&prtncheck, &pitxn, logiclba, ebr.entries[0].numLBA);
587 587
         if (tmp != CL_CLEAN) {
588
-            if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
588
+            if (tmp == CL_VIRUS) {
589 589
                 cli_dbgmsg("cli_scanebr: detected intersection with partitions "
590 590
                            "[%u, %u]\n", pitxn, i);
591
-                cli_append_virus(ctx, PRTN_INTXN_DETECTION);
591
+                ret = cli_append_virus(ctx, PRTN_INTXN_DETECTION);
592
+                if (ret == CL_VIRUS)
593
+                    virus_found = 1;
594
+                if (SCAN_ALL || ret == CL_CLEAN)
595
+                    tmp = 0;
596
+                else
597
+                    goto leave;
598
+            } else {
592 599
                 ret = tmp;
593
-                tmp = 0;
594
-            }
595
-            else if (tmp == CL_VIRUS) {
596
-                cli_dbgmsg("cli_scanebr: detected intersection with partitions "
597
-                           "[%u, %u]\n", pitxn, i);
598
-                cli_append_virus(ctx, PRTN_INTXN_DETECTION);
599
-                prtn_intxn_list_free(&prtncheck);
600
-                return CL_VIRUS;
601
-            }
602
-            else {
603
-                prtn_intxn_list_free(&prtncheck);
604
-                return tmp;
600
+                goto leave;
605 601
             }
606 602
         }
607 603
 
... ...
@@ -616,6 +608,9 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
616 616
         ++i;
617 617
     } while (logiclba != 0 && (*prtncount) < ctx->engine->maxpartitions);
618 618
 
619
-    prtn_intxn_list_free(&prtncheck);    
619
+ leave:
620
+    prtn_intxn_list_free(&prtncheck);
621
+    if (virus_found)
622
+        return CL_VIRUS;
620 623
     return ret;
621 624
 }
... ...
@@ -1088,15 +1088,39 @@ int cli_unlink(const char *pathname)
1088 1088
 	return 0;
1089 1089
 }
1090 1090
 
1091
-void cli_append_virus(cli_ctx * ctx, const char * virname)
1091
+void cli_virus_found_cb(cli_ctx * ctx)
1092
+{
1093
+    if (ctx->engine->cb_virus_found)
1094
+        ctx->engine->cb_virus_found(fmap_fd(*ctx->fmap), (const char *)*ctx->virname, ctx->cb_ctx);
1095
+}
1096
+
1097
+int cli_append_possibly_unwanted(cli_ctx * ctx, const char * virname)
1098
+{
1099
+    if (SCAN_ALL)
1100
+        return cli_append_virus(ctx, virname);
1101
+    else if (ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE)
1102
+        return cli_append_virus(ctx, virname);
1103
+    else if (ctx->num_viruses == 0 && ctx->virname != NULL && *ctx->virname == NULL) {
1104
+        ctx->found_possibly_unwanted = 1;
1105
+        ctx->num_viruses++;
1106
+        *ctx->virname = virname;
1107
+    }
1108
+    return CL_CLEAN;
1109
+}
1110
+
1111
+int cli_append_virus(cli_ctx * ctx, const char * virname)
1092 1112
 {
1093 1113
     if (ctx->virname == NULL)
1094
-        return;
1114
+        return CL_CLEAN;
1115
+    if (ctx->fmap != NULL && (*ctx->fmap) != NULL && CL_VIRUS != cli_checkfp_virus((*ctx->fmap)->maphash, (*ctx->fmap)->len, ctx, virname))
1116
+        return CL_CLEAN;
1117
+    if (!SCAN_ALL && ctx->num_viruses != 0)
1118
+        if (ctx->options & CL_SCAN_HEURISTIC_PRECEDENCE)
1119
+            return CL_CLEAN;
1095 1120
     if (ctx->limit_exceeded == 0 || SCAN_ALL) { 
1096
-        if (ctx->engine->cb_virus_found)
1097
-            ctx->engine->cb_virus_found(fmap_fd(*ctx->fmap), virname, ctx->cb_ctx);
1098 1121
         ctx->num_viruses++;
1099 1122
         *ctx->virname = virname;
1123
+        cli_virus_found_cb(ctx);
1100 1124
     }
1101 1125
 #if HAVE_JSON
1102 1126
     if (SCAN_PROPERTIES && ctx->wrkproperty) {
... ...
@@ -1105,17 +1129,18 @@ void cli_append_virus(cli_ctx * ctx, const char * virname)
1105 1105
             arrobj = json_object_new_array();
1106 1106
             if (NULL == arrobj) {
1107 1107
                 cli_errmsg("cli_append_virus: no memory for json virus array\n");
1108
-                return;
1108
+                return CL_EMEM;
1109 1109
             }
1110 1110
             json_object_object_add(ctx->wrkproperty, "Viruses", arrobj);
1111 1111
         }
1112 1112
         virobj = json_object_new_string(virname);
1113 1113
         if (NULL == virobj) {
1114 1114
             cli_errmsg("cli_append_virus: no memory for json virus name object\n");
1115
-            return;
1115
+            return CL_EMEM;
1116 1116
         }
1117 1117
         json_object_array_add(arrobj, virobj);
1118 1118
     }
1119
+    return CL_VIRUS;
1119 1120
 #endif
1120 1121
 }
1121 1122
 
... ...
@@ -601,9 +601,10 @@ static inline void cli_writeint32(void *offset, uint32_t value)
601 601
 }
602 602
 #endif
603 603
 
604
-void cli_append_virus(cli_ctx *ctx, const char *virname);
604
+int cli_append_virus(cli_ctx *ctx, const char *virname);
605 605
 const char *cli_get_last_virus(const cli_ctx *ctx);
606 606
 const char *cli_get_last_virus_str(const cli_ctx *ctx);
607
+void cli_virus_found_cb(cli_ctx *ctx);
607 608
 
608 609
 void cli_set_container(cli_ctx *ctx, cli_file_t type, size_t size);
609 610
 cli_file_t cli_get_container_type(cli_ctx *ctx, int index);
... ...
@@ -2458,10 +2458,10 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
2458 2458
 
2459 2459
         pdf_parseobj(&pdf, obj);
2460 2460
         if (SCAN_ALGO && obj->numfilters > PDF_FILTER_DTRIGGER) {
2461
-            cli_append_virus(ctx, "Heuristic.PDF.TooManyFilters");
2461
+            rc = cli_append_virus(ctx, "Heuristic.PDF.TooManyFilters");
2462 2462
             alerts++;
2463
-            if (!SCAN_ALL)
2464
-                rc = CL_VIRUS;
2463
+            if (SCAN_ALL && rc == CL_VIRUS)
2464
+                rc = CL_CLEAN;
2465 2465
         }
2466 2466
     }
2467 2467
 
... ...
@@ -2479,8 +2479,8 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
2479 2479
          * a password to decrypt */
2480 2480
         cli_append_virus(ctx, "Heuristics.Encrypted.PDF");
2481 2481
         alerts++;
2482
-        if (!SCAN_ALL)
2483
-            rc = CL_VIRUS;
2482
+        if (SCAN_ALL && rc == CL_VIRUS)
2483
+            rc = CL_CLEAN;
2484 2484
     }
2485 2485
 
2486 2486
     if (!rc) {
... ...
@@ -2547,8 +2547,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
2547 2547
         if (!rc && SCAN_ALGO && (ctx->dconf->other & OTHER_CONF_PDFNAMEOBJ)) {
2548 2548
             if (pdf.flags & (1 << ESCAPED_COMMON_PDFNAME)) {
2549 2549
                 /* for example /Fl#61te#44#65#63#6f#64#65 instead of /FlateDecode */
2550
-                cli_append_virus(ctx, "Heuristics.PDF.ObfuscatedNameObject");
2551
-                rc = cli_found_possibly_unwanted(ctx);
2550
+                cli_append_possibly_unwanted(ctx, "Heuristics.PDF.ObfuscatedNameObject");
2552 2551
             }
2553 2552
         }
2554 2553
 #if 0
... ...
@@ -555,7 +555,7 @@ static int scan_pe_mdb (cli_ctx * ctx, struct cli_exe_section *exe_section)
555 555
     if (cli_debug_flag) {
556 556
         md5 = hashset[CLI_HASH_MD5];
557 557
         if (md5) {
558
-            cli_dbgmsg("MDB: %u:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
558
+            cli_dbgmsg("MDB hashset: %u:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
559 559
                 exe_section->rsz, md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], md5[7],
560 560
                 md5[8], md5[9], md5[10], md5[11], md5[12], md5[13], md5[14], md5[15]);
561 561
         } else if (cli_always_gen_section_hash) {
... ...
@@ -589,17 +589,21 @@ static int scan_pe_mdb (cli_ctx * ctx, struct cli_exe_section *exe_section)
589 589
     /* Do scans */
590 590
     for(type = CLI_HASH_MD5; type < CLI_HASH_AVAIL_TYPES; type++) {
591 591
        if(foundsize[type] && cli_hm_scan(hashset[type], exe_section->rsz, &virname, mdb_sect, type) == CL_VIRUS) {
592
-            cli_append_virus(ctx, virname);
593
-            ret = CL_VIRUS;
594
-            if (!SCAN_ALL) {
595
-                break;
592
+            ret = cli_append_virus(ctx, virname);
593
+            if (ret != CL_CLEAN) {
594
+                if (ret != CL_VIRUS)
595
+                    break;
596
+                else if (!SCAN_ALL)
597
+                    break;
596 598
             }
597 599
        }
598 600
        if(foundwild[type] && cli_hm_scan_wild(hashset[type], &virname, mdb_sect, type) == CL_VIRUS) {
599
-            cli_append_virus(ctx, virname);
600
-            ret = CL_VIRUS;
601
-            if (!SCAN_ALL) {
602
-                break;
601
+            ret = cli_append_virus(ctx, virname);
602
+            if (ret != CL_CLEAN) {
603
+                if (ret != CL_VIRUS)
604
+                    break;
605
+                else if (!SCAN_ALL)
606
+                    break;
603 607
             }
604 608
        }
605 609
     }
... ...
@@ -2209,10 +2213,10 @@ static int validate_impname(const char *name, uint32_t length, int dll)
2209 2209
 
2210 2210
 static inline int hash_impfns(cli_ctx *ctx, void **hashctx, uint32_t *impsz, struct pe_image_import_descriptor *image, const char *dllname, struct cli_exe_section *exe_sections, uint16_t nsections, uint32_t hdr_size, int pe_plus, int *first)
2211 2211
 {
2212
-    uint32_t thuoff, offset;
2212
+    uint32_t thuoff = 0, offset;
2213 2213
     fmap_t *map = *ctx->fmap;
2214 2214
     size_t dlllen = 0, fsize = map->len;
2215
-    int i, j, err, num_fns = 0, ret = CL_SUCCESS;
2215
+    int i, j, err = 0, num_fns = 0, ret = CL_SUCCESS;
2216 2216
     const char *buffer;
2217 2217
     enum CLI_HASH_TYPE type;
2218 2218
 #if HAVE_JSON
... ...
@@ -2557,17 +2561,23 @@ static int scan_pe_imp(cli_ctx *ctx, struct pe_image_data_dir *dirs, struct cli_
2557 2557
     /* Do scans */
2558 2558
     for(type = CLI_HASH_MD5; type < CLI_HASH_AVAIL_TYPES; type++) {
2559 2559
         if(cli_hm_scan(hashset[type], impsz, &virname, imp, type) == CL_VIRUS) {
2560
-            cli_append_virus(ctx, virname);
2561
-            ret = CL_VIRUS;
2562
-            if(!SCAN_ALL)
2563
-                break;
2560
+            ret = cli_append_virus(ctx, virname);
2561
+            if (ret != CL_CLEAN) {
2562
+                if (ret != CL_VIRUS)
2563
+                    break;
2564
+                else if (!SCAN_ALL)
2565
+                    break;
2566
+            }
2564 2567
         }
2565 2568
         if(cli_hm_scan_wild(hashset[type], &virname, imp, type) == CL_VIRUS) {
2566 2569
             cli_append_virus(ctx, virname);
2567
-            ret = CL_VIRUS;
2568
-            if(!SCAN_ALL)
2569
-                break;
2570
-        }
2570
+            if (ret != CL_CLEAN) {
2571
+                if (ret != CL_VIRUS)
2572
+                    break;
2573
+                else if (!SCAN_ALL)
2574
+                    break;
2575
+            }
2576
+       }
2571 2577
     }
2572 2578
 
2573 2579
     for(type = CLI_HASH_MD5; type < CLI_HASH_AVAIL_TYPES; type++)
... ...
@@ -2759,8 +2769,8 @@ int cli_scanpe(cli_ctx *ctx)
2759 2759
         cli_dbgmsg("Can't read new header address\n");
2760 2760
         /* truncated header? */
2761 2761
         if(DETECT_BROKEN_PE) {
2762
-            cli_append_virus(ctx,"Heuristics.Broken.Executable");
2763
-            return CL_VIRUS;
2762
+            ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
2763
+            return ret;
2764 2764
         }
2765 2765
 
2766 2766
         return CL_CLEAN;
... ...
@@ -2775,7 +2785,7 @@ int cli_scanpe(cli_ctx *ctx)
2775 2775
 
2776 2776
     if(fmap_readn(map, &file_hdr, e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
2777 2777
         /* bad information in e_lfanew - probably not a PE file */
2778
-        cli_dbgmsg("Can't read file header\n");
2778
+        cli_dbgmsg("cli_scanpe: Can't read file header\n");
2779 2779
         return CL_CLEAN;
2780 2780
     }
2781 2781
 
... ...
@@ -2908,8 +2918,8 @@ int cli_scanpe(cli_ctx *ctx)
2908 2908
         pe_add_heuristic_property(ctx, "BadNumberOfSections");
2909 2909
 #endif
2910 2910
         if(DETECT_BROKEN_PE) {
2911
-            cli_append_virus(ctx,"Heuristics.Broken.Executable");
2912
-            return CL_VIRUS;
2911
+            ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
2912
+            return ret;
2913 2913
         }
2914 2914
 
2915 2915
         if(!ctx->corrupted_input) {
... ...
@@ -2945,8 +2955,8 @@ int cli_scanpe(cli_ctx *ctx)
2945 2945
 #endif
2946 2946
         cli_dbgmsg("SizeOfOptionalHeader too small\n");
2947 2947
         if(DETECT_BROKEN_PE) {
2948
-            cli_append_virus(ctx,"Heuristics.Broken.Executable");
2949
-            return CL_VIRUS;
2948
+            ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
2949
+            return ret;
2950 2950
         }
2951 2951
 
2952 2952
         return CL_CLEAN;
... ...
@@ -2956,8 +2966,8 @@ int cli_scanpe(cli_ctx *ctx)
2956 2956
     if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
2957 2957
         cli_dbgmsg("Can't read optional file header\n");
2958 2958
         if(DETECT_BROKEN_PE) {
2959
-            cli_append_virus(ctx,"Heuristics.Broken.Executable");
2960
-            return CL_VIRUS;
2959
+            ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
2960
+            return ret;
2961 2961
         }
2962 2962
 
2963 2963
         return CL_CLEAN;
... ...
@@ -2974,8 +2984,8 @@ int cli_scanpe(cli_ctx *ctx)
2974 2974
             cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n");
2975 2975
 
2976 2976
             if(DETECT_BROKEN_PE) {
2977
-                cli_append_virus(ctx,"Heuristics.Broken.Executable");
2978
-                return CL_VIRUS;
2977
+                ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
2978
+                return ret;
2979 2979
             }
2980 2980
 
2981 2981
             return CL_CLEAN;
... ...
@@ -3044,8 +3054,8 @@ int cli_scanpe(cli_ctx *ctx)
3044 3044
             if(fmap_readn(map, &optional_hdr32 + 1, at, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
3045 3045
             cli_dbgmsg("Can't read optional file header\n");
3046 3046
             if(DETECT_BROKEN_PE) {
3047
-                cli_append_virus(ctx,"Heuristics.Broken.Executable");
3048
-                return CL_VIRUS;
3047
+                ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
3048
+                return ret;
3049 3049
             }
3050 3050
 
3051 3051
             return CL_CLEAN;
... ...
@@ -3168,14 +3178,14 @@ int cli_scanpe(cli_ctx *ctx)
3168 3168
 
3169 3169
     if (DETECT_BROKEN_PE && !native && (!(pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment)) || (pe_plus?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment))%0x1000)) {
3170 3170
         cli_dbgmsg("Bad virtual alignment\n");
3171
-        cli_append_virus(ctx,"Heuristics.Broken.Executable");
3172
-        return CL_VIRUS;
3171
+        ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
3172
+        return ret;
3173 3173
     }
3174 3174
 
3175 3175
     if (DETECT_BROKEN_PE && !native && (!(pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment)) || (pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment))%0x200)) {
3176 3176
         cli_dbgmsg("Bad file alignment\n");
3177
-        cli_append_virus(ctx, "Heuristics.Broken.Executable");
3178
-        return CL_VIRUS;
3177
+        ret = cli_append_virus(ctx, "Heuristics.Broken.Executable");
3178
+        return ret;
3179 3179
     }
3180 3180
 
3181 3181
     fsize = map->len;
... ...
@@ -3206,8 +3216,8 @@ int cli_scanpe(cli_ctx *ctx)
3206 3206
         free(exe_sections);
3207 3207
 
3208 3208
         if(DETECT_BROKEN_PE) {
3209
-            cli_append_virus(ctx,"Heuristics.Broken.Executable");
3210
-            return CL_VIRUS;
3209
+            ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
3210
+            return ret;
3211 3211
         }
3212 3212
 
3213 3213
         return CL_CLEAN;
... ...
@@ -3251,8 +3261,8 @@ int cli_scanpe(cli_ctx *ctx)
3251 3251
                         free(exe_sections);
3252 3252
 
3253 3253
                         if(DETECT_BROKEN_PE) {
3254
-                            cli_append_virus(ctx, "Heuristics.Broken.Executable");
3255
-                            return CL_VIRUS;
3254
+                            ret = cli_append_virus(ctx, "Heuristics.Broken.Executable");
3255
+                            return ret;
3256 3256
                         }
3257 3257
 
3258 3258
                         return CL_CLEAN; /* no ninjas to see here! move along! */
... ...
@@ -3324,10 +3334,10 @@ int cli_scanpe(cli_ctx *ctx)
3324 3324
         if (DETECT_BROKEN_PE && (!valign || (exe_sections[i].urva % valign))) { /* Bad virtual alignment */
3325 3325
             cli_dbgmsg("VirtualAddress is misaligned\n");
3326 3326
             cli_dbgmsg("------------------------------------\n");
3327
-            cli_append_virus(ctx, "Heuristics.Broken.Executable");
3327
+            ret = cli_append_virus(ctx, "Heuristics.Broken.Executable");
3328 3328
             free(section_hdr);
3329 3329
             free(exe_sections);
3330
-            return CL_VIRUS;
3330
+            return ret;
3331 3331
         }
3332 3332
 
3333 3333
         if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */
... ...
@@ -3355,8 +3365,8 @@ int cli_scanpe(cli_ctx *ctx)
3355 3355
             free(section_hdr);
3356 3356
             free(exe_sections);
3357 3357
             if(DETECT_BROKEN_PE) {
3358
-                cli_append_virus(ctx, "Heuristics.Broken.Executable");
3359
-                return CL_VIRUS;
3358
+                ret = cli_append_virus(ctx, "Heuristics.Broken.Executable");
3359
+                return ret;
3360 3360
             }
3361 3361
 
3362 3362
             return CL_CLEAN;
... ...
@@ -3365,10 +3375,10 @@ int cli_scanpe(cli_ctx *ctx)
3365 3365
         if(!i) {
3366 3366
             if (DETECT_BROKEN_PE && exe_sections[i].urva!=hdr_size) { /* Bad first section RVA */
3367 3367
                 cli_dbgmsg("First section is in the wrong place\n");
3368
-                cli_append_virus(ctx, "Heuristics.Broken.Executable");
3368
+                ret = cli_append_virus(ctx, "Heuristics.Broken.Executable");
3369 3369
                 free(section_hdr);
3370 3370
                 free(exe_sections);
3371
-                return CL_VIRUS;
3371
+                return ret;
3372 3372
             }
3373 3373
 
3374 3374
             min = exe_sections[i].rva;
... ...
@@ -3376,10 +3386,10 @@ int cli_scanpe(cli_ctx *ctx)
3376 3376
         } else {
3377 3377
             if (DETECT_BROKEN_PE && exe_sections[i].urva - exe_sections[i-1].urva != exe_sections[i-1].vsz) { /* No holes, no overlapping, no virtual disorder */
3378 3378
                 cli_dbgmsg("Virtually misplaced section (wrong order, overlapping, non contiguous)\n");
3379
-                cli_append_virus(ctx, "Heuristics.Broken.Executable");
3379
+                ret = cli_append_virus(ctx, "Heuristics.Broken.Executable");
3380 3380
                 free(section_hdr);
3381 3381
                 free(exe_sections);
3382
-                return CL_VIRUS;
3382
+                return ret;
3383 3383
             }
3384 3384
 
3385 3385
             if(exe_sections[i].rva < min)
... ...
@@ -3398,8 +3408,8 @@ int cli_scanpe(cli_ctx *ctx)
3398 3398
         cli_dbgmsg("EntryPoint out of file\n");
3399 3399
         free(exe_sections);
3400 3400
         if(DETECT_BROKEN_PE) {
3401
-            cli_append_virus(ctx,"Heuristics.Broken.Executable");
3402
-            return CL_VIRUS;
3401
+            ret = cli_append_virus(ctx,"Heuristics.Broken.Executable");
3402
+            return ret;
3403 3403
         }
3404 3404
 
3405 3405
         return CL_CLEAN;
... ...
@@ -3517,13 +3527,20 @@ int cli_scanpe(cli_ctx *ctx)
3517 3517
         if(pt) {
3518 3518
             pt += 15;
3519 3519
             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)) {
3520
-                cli_append_virus(ctx,"Heuristics.W32.Parite.B");
3521
-                if (!SCAN_ALL) {
3522
-                    free(exe_sections);
3523
-                    return CL_VIRUS;
3520
+                ret = cli_append_virus(ctx,"Heuristics.W32.Parite.B");
3521
+                if (ret != CL_CLEAN) {
3522
+                    if (ret == CL_VIRUS) {
3523
+                        if (!SCAN_ALL) {
3524
+                            free(exe_sections);
3525
+                            return ret;
3526
+                        }
3527
+                        else
3528
+                            viruses_found++;
3529
+                    } else {
3530
+                        free(exe_sections);
3531
+                        return ret;
3532
+                    }
3524 3533
                 }
3525
-
3526
-                viruses_found++;
3527 3534
             }
3528 3535
         }
3529 3536
     }
... ...
@@ -3635,15 +3652,21 @@ int cli_scanpe(cli_ctx *ctx)
3635 3635
                 break;
3636 3636
             case KZSLOOP:
3637 3637
                 if (op==kzdsize+0x48 && *kzcode==0x75 && kzlen-(int8_t)kzcode[1]-3<=kzinitlen && kzlen-(int8_t)kzcode[1]>=kzxorlen) {
3638
-                    cli_append_virus(ctx,"Heuristics.W32.Kriz");
3639
-                    if (!SCAN_ALL) {
3640
-                        free(exe_sections);
3641
-                        return CL_VIRUS;
3638
+                    ret = cli_append_virus(ctx,"Heuristics.W32.Kriz");
3639
+                    if (ret != CL_CLEAN) {
3640
+                        if (ret == CL_VIRUS) {
3641
+                            if (!SCAN_ALL) {
3642
+                                free(exe_sections);
3643
+                                return ret;
3644
+                            }
3645
+                            else
3646
+                                viruses_found++;
3647
+                        } else {
3648
+                            free(exe_sections);
3649
+                            return ret;
3650
+                        }
3642 3651
                     }
3643
-
3644
-                    viruses_found++;
3645 3652
                 }
3646
-
3647 3653
                 cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n");
3648 3654
                 kzstate++;
3649 3655
             }
... ...
@@ -3667,13 +3690,20 @@ int cli_scanpe(cli_ctx *ctx)
3667 3667
 
3668 3668
             if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
3669 3669
                 if(cli_memstr(tbuff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
3670
-                    cli_append_virus(ctx, dam ? "Heuristics.W32.Magistr.A.dam" : "Heuristics.W32.Magistr.A");
3671
-                    if (!SCAN_ALL) {
3672
-                        free(exe_sections);
3673
-                        return CL_VIRUS;
3670
+                    ret = cli_append_virus(ctx, dam ? "Heuristics.W32.Magistr.A.dam" : "Heuristics.W32.Magistr.A");
3671
+                    if (ret != CL_CLEAN) {
3672
+                        if (ret == CL_VIRUS) {
3673
+                            if (!SCAN_ALL) {
3674
+                                free(exe_sections);
3675
+                                return ret;
3676
+                            }
3677
+                            else
3678
+                                viruses_found++;
3679
+                        } else {
3680
+                            free(exe_sections);
3681
+                            return ret;
3682
+                        }
3674 3683
                     }
3675
-
3676
-                    viruses_found++;
3677 3684
                 }
3678 3685
             }
3679 3686
         } else if(rsize >= 0x7000 && vsize >= 0x7000 && ((vsize & 0xff) == 0xed)) {
... ...
@@ -3682,13 +3712,20 @@ int cli_scanpe(cli_ctx *ctx)
3682 3682
 
3683 3683
             if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
3684 3684
                 if(cli_memstr(tbuff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
3685
-                    cli_append_virus(ctx,dam ? "Heuristics.W32.Magistr.B.dam" : "Heuristics.W32.Magistr.B");
3686
-                    if (!SCAN_ALL) {
3687
-                        free(exe_sections);
3688
-                        return CL_VIRUS;
3685
+                    ret = cli_append_virus(ctx,dam ? "Heuristics.W32.Magistr.B.dam" : "Heuristics.W32.Magistr.B");
3686
+                    if (ret != CL_CLEAN) {
3687
+                        if (ret == CL_VIRUS) {
3688
+                            if (!SCAN_ALL) {
3689
+                                free(exe_sections);
3690
+                                return ret;
3691
+                            }
3692
+                            else
3693
+                                viruses_found++;
3694
+                        } else {
3695
+                            free(exe_sections);
3696
+                            return ret;
3697
+                        }
3689 3698
                     }
3690
-
3691
-                    viruses_found++;
3692 3699
                 } 
3693 3700
             }
3694 3701
         }
... ...
@@ -3752,14 +3789,22 @@ int cli_scanpe(cli_ctx *ctx)
3752 3752
                 continue;
3753 3753
 
3754 3754
             if((jump=cli_readint32(code))==0x60ec8b55 || (code[4]==0x0ec && ((jump==0x83ec8b55 && code[6]==0x60) || (jump==0x81ec8b55 && !code[7] && !code[8])))) {
3755
-                cli_append_virus(ctx,"Heuristics.W32.Polipos.A");
3756
-                if (!SCAN_ALL) {
3757
-                    free(jumps);
3758
-                    free(exe_sections);
3759
-                    return CL_VIRUS;
3755
+                ret = cli_append_virus(ctx,"Heuristics.W32.Polipos.A");
3756
+                if (ret != CL_CLEAN) {
3757
+                    if (ret == CL_VIRUS) {
3758
+                        if (!SCAN_ALL) {
3759
+                            free(jumps);
3760
+                            free(exe_sections);
3761
+                            return ret;
3762
+                        }
3763
+                        else
3764
+                            viruses_found++;
3765
+                    } else {
3766
+                        free(jumps);
3767
+                        free(exe_sections);
3768
+                        return ret;
3769
+                    }
3760 3770
                 }
3761
-
3762
-                viruses_found++;
3763 3771
             }
3764 3772
         }
3765 3773
 
... ...
@@ -3775,21 +3820,28 @@ int cli_scanpe(cli_ctx *ctx)
3775 3775
             ret = CL_CLEAN;
3776 3776
 
3777 3777
             if (!stats) {
3778
-                ret = CL_EMEM;
3778
+                free(exe_sections);
3779
+                return CL_EMEM;
3779 3780
             } else {
3780 3781
                 cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), map, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
3781
-                if ((ret = cli_detect_swizz(stats)) == CL_VIRUS)
3782
-                    cli_append_virus(ctx,"Heuristics.Trojan.Swizzor.Gen");
3783
-
3784
-                free(stats);
3785
-            }
3786
-            if (ret != CL_CLEAN) {
3787
-                if (!(ret == CL_VIRUS && SCAN_ALL)) {
3788
-                    free(exe_sections);
3789
-                    return ret;
3782
+                if ((ret = cli_detect_swizz(stats)) == CL_VIRUS) {
3783
+                    ret = cli_append_virus(ctx,"Heuristics.Trojan.Swizzor.Gen");
3784
+                    if (ret != CL_CLEAN) {
3785
+                        if (ret == CL_VIRUS) {
3786
+                            if (!SCAN_ALL) {
3787
+                                free(stats);
3788
+                                free(exe_sections);
3789
+                                return ret;
3790
+                            }
3791
+                            else
3792
+                                viruses_found++;
3793
+                        } else {
3794
+                            free(stats);
3795
+                            free(exe_sections);
3796
+                            return ret;
3797
+                        }
3798
+                    }
3790 3799
                 }
3791
-
3792
-                viruses_found++;
3793 3800
             }
3794 3801
         }
3795 3802
     }
... ...
@@ -4982,7 +5034,7 @@ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
4982 4982
 
4983 4983
     if(fmap_readn(map, &file_hdr, peinfo->offset + e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
4984 4984
         /* bad information in e_lfanew - probably not a PE file */
4985
-        cli_dbgmsg("Can't read file header\n");
4985
+        cli_dbgmsg("cli_peheader: Can't read file header\n");
4986 4986
         return -1;
4987 4987
     }
4988 4988
 
... ...
@@ -814,32 +814,31 @@ int phishingScan(cli_ctx* ctx,tag_arguments_t* hrefs)
814 814
 				case CL_PHISH_CLEAN:
815 815
 					continue;
816 816
 				case CL_PHISH_NUMERIC_IP:
817
-				    cli_append_virus(ctx, "Heuristics.Phishing.Email.Cloaked.NumericIP");
817
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Phishing.Email.Cloaked.NumericIP");
818 818
 					break;
819 819
 				case CL_PHISH_CLOAKED_NULL:
820
-				    cli_append_virus(ctx, "Heuristics.Phishing.Email.Cloaked.Null");/*fakesite%01%00@fake.example.com*/
820
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Phishing.Email.Cloaked.Null");/*fakesite%01%00@fake.example.com*/
821 821
 					break;
822 822
 				case CL_PHISH_SSL_SPOOF:
823
-				    cli_append_virus(ctx, "Heuristics.Phishing.Email.SSL-Spoof");
823
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Phishing.Email.SSL-Spoof");
824 824
 					break;
825 825
 				case CL_PHISH_CLOAKED_UIU:
826
-				    cli_append_virus(ctx, "Heuristics.Phishing.Email.Cloaked.Username");/*http://banksite@fake.example.com*/
826
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Phishing.Email.Cloaked.Username");/*http://banksite@fake.example.com*/
827 827
 					break;
828 828
 				case CL_PHISH_HASH0:
829
-				    cli_append_virus(ctx, "Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net");
829
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Safebrowsing.Suspected-malware_safebrowsing.clamav.net");
830 830
 					break;
831 831
 				case CL_PHISH_HASH1:
832
-				    cli_append_virus(ctx, "Heuristics.Phishing.URL.Blacklisted");
832
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Phishing.URL.Blacklisted");
833 833
 					break;
834 834
 				case CL_PHISH_HASH2:
835
-				    cli_append_virus(ctx, "Heuristics.Safebrowsing.Suspected-phishing_safebrowsing.clamav.net");
835
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Safebrowsing.Suspected-phishing_safebrowsing.clamav.net");
836 836
 					break;
837 837
 				case CL_PHISH_NOMATCH:
838 838
 				default:
839
-				    cli_append_virus(ctx, "Heuristics.Phishing.Email.SpoofedDomain");
839
+				    cli_append_possibly_unwanted(ctx, "Heuristics.Phishing.Email.SpoofedDomain");
840 840
 					break;
841 841
 			}
842
-			return cli_found_possibly_unwanted(ctx);
843 842
 	}
844 843
 	return CL_CLEAN;
845 844
 }
... ...
@@ -227,9 +227,9 @@ static int cli_unrar_scanmetadata(int desc, unrar_metadata_t *metadata, cli_ctx
227 227
 	cli_dbgmsg("RAR: Encrypted files found in archive.\n");
228 228
 	ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
229 229
 	if(ret != CL_VIRUS) {
230
-	    cli_append_virus(ctx, "Heuristics.Encrypted.RAR");
231
-	    return CL_VIRUS;
232
-	}
230
+	    if (CL_VIRUS == cli_append_virus(ctx, "Heuristics.Encrypted.RAR"))
231
+                return CL_VIRUS;
232
+        }
233 233
     }
234 234
 
235 235
     if (virus_found != 0)
... ...
@@ -269,13 +269,13 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c
269 269
 	    cli_dbgmsg("RAR: Encrypted main header\n");
270 270
 	    if(DETECT_ENCRYPTED) {
271 271
 		if (lseek(desc, 0, SEEK_SET) == -1) {
272
-            cli_dbgmsg("RAR: call to lseek() failed\n");
273
-            return CL_ESEEK;
274
-        }
272
+                    cli_dbgmsg("RAR: call to lseek() failed\n");
273
+                    return CL_ESEEK;
274
+                }
275 275
 		ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, NULL);
276 276
 		if(ret != CL_VIRUS)
277
-		    cli_append_virus(ctx, "Heuristics.Encrypted.RAR");
278
-		return CL_VIRUS;
277
+		    if (CL_VIRUS == cli_append_virus(ctx, "Heuristics.Encrypted.RAR"))
278
+                        return CL_VIRUS;
279 279
 	    }
280 280
 	    return CL_CLEAN;
281 281
 	} if(ret == UNRAR_EMEM) {
... ...
@@ -1179,9 +1179,9 @@ static int cli_vba_scandir(const char *dirname, cli_ctx *ctx, struct uniq *U)
1179 1179
         cli_jsonbool(ctx->wrkproperty, "HasMacros", 1);
1180 1180
 #endif
1181 1181
     if(BLOCK_MACROS && hasmacros) {
1182
-	cli_append_virus(ctx, "Heuristics.OLE2.ContainsMacros");
1183
-	ret = CL_VIRUS;
1184
-	viruses_found++;
1182
+	ret = cli_append_virus(ctx, "Heuristics.OLE2.ContainsMacros");
1183
+	if (ret == CL_VIRUS)
1184
+            viruses_found++;
1185 1185
     }
1186 1186
     if (SCAN_ALL && viruses_found)
1187 1187
 	return CL_VIRUS;
... ...
@@ -1609,24 +1609,20 @@ static int cli_scanscrenc(cli_ctx *ctx)
1609 1609
 
1610 1610
 static int cli_scanriff(cli_ctx *ctx)
1611 1611
 {
1612
-	int ret = CL_CLEAN;
1612
+    int ret = CL_CLEAN;
1613 1613
 
1614
-    if(cli_check_riff_exploit(ctx) == 2) {
1615
-	ret = CL_VIRUS;
1616
-	cli_append_virus(ctx, "Heuristics.Exploit.W32.MS05-002");
1617
-    }
1614
+    if (cli_check_riff_exploit(ctx) == 2)
1615
+	ret = cli_append_virus(ctx, "Heuristics.Exploit.W32.MS05-002");
1618 1616
 
1619 1617
     return ret;
1620 1618
 }
1621 1619
 
1622 1620
 static int cli_scanjpeg(cli_ctx *ctx)
1623 1621
 {
1624
-	int ret = CL_CLEAN;
1622
+    int ret = CL_CLEAN;
1625 1623
 
1626
-	if(cli_check_jpeg_exploit(ctx, 0) == 1) {
1627
-	ret = CL_VIRUS;
1628
-	cli_append_virus(ctx, "Heuristics.Exploit.W32.MS04-028");
1629
-    }
1624
+    if(cli_check_jpeg_exploit(ctx, 0) == 1)
1625
+        ret = cli_append_virus(ctx, "Heuristics.Exploit.W32.MS04-028");
1630 1626
 
1631 1627
     return ret;
1632 1628
 }
... ...
@@ -1872,20 +1868,20 @@ static int cli_scan_structured(cli_ctx *ctx)
1872 1872
 
1873 1873
     if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
1874 1874
 	cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
1875
-	cli_append_virus(ctx,"Heuristics.Structured.CreditCardNumber");
1876
-	if (SCAN_ALL)
1877
-	    viruses_found++;
1878
-	else
1879
-	    return CL_VIRUS;
1875
+	if (CL_VIRUS == cli_append_virus(ctx,"Heuristics.Structured.CreditCardNumber"))
1876
+            if (SCAN_ALL)
1877
+                viruses_found++;
1878
+            else
1879
+                return CL_VIRUS;
1880 1880
     }
1881 1881
 
1882 1882
     if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
1883 1883
 	cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
1884
-	cli_append_virus(ctx,"Heuristics.Structured.SSN");
1885
-	if (SCAN_ALL)
1886
-	    viruses_found++;
1887
-	else
1888
-	    return CL_VIRUS;
1884
+	if (CL_VIRUS == cli_append_virus(ctx,"Heuristics.Structured.SSN"))
1885
+            if (SCAN_ALL)
1886
+                viruses_found++;
1887
+            else
1888
+                return CL_VIRUS;
1889 1889
     }
1890 1890
 
1891 1891
     if (viruses_found)
... ...
@@ -2161,32 +2157,32 @@ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_
2161 2161
                 case CL_TYPE_MHTML:
2162 2162
                     if(SCAN_MAIL && (DCONF_MAIL & MAIL_CONF_MBOX)) {
2163 2163
                         cli_dbgmsg("MHTML signature found at %u\n", (unsigned int) fpt->offset);
2164
-                        ret = cli_scanmail(ctx);
2164
+                        nret = ret = cli_scanmail(ctx);
2165 2165
                     }
2166 2166
                     break;
2167 2167
 
2168 2168
                 case CL_TYPE_XDP:
2169 2169
                     if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
2170 2170
                         cli_dbgmsg("XDP signature found at %u\n", (unsigned int) fpt->offset);
2171
-                        ret = cli_scanxdp(ctx);
2171
+                        nret = ret = cli_scanxdp(ctx);
2172 2172
                     }
2173 2173
                     break;
2174 2174
                 case CL_TYPE_XML_WORD:
2175 2175
                     if(SCAN_XMLDOCS && (DCONF_DOC & DOC_CONF_MSXML)) {
2176 2176
                         cli_dbgmsg("XML-WORD signature found at %u\n", (unsigned int) fpt->offset);
2177
-                        ret = cli_scanmsxml(ctx);
2177
+                        nret = ret = cli_scanmsxml(ctx);
2178 2178
                     }
2179 2179
                     break;
2180 2180
                 case CL_TYPE_XML_XL:
2181 2181
                     if(SCAN_XMLDOCS && (DCONF_DOC & DOC_CONF_MSXML)) {
2182 2182
                         cli_dbgmsg("XML-XL signature found at %u\n", (unsigned int) fpt->offset);
2183
-                        ret = cli_scanmsxml(ctx);
2183
+                        nret = ret = cli_scanmsxml(ctx);
2184 2184
                     }
2185 2185
                     break;
2186 2186
                 case CL_TYPE_XML_HWP:
2187 2187
                     if(SCAN_XMLDOCS && (DCONF_DOC & DOC_CONF_HWP)) {
2188 2188
                         cli_dbgmsg("XML-HWP signature found at %u\n", (unsigned int) fpt->offset);
2189
-                        ret = cli_scanhwpml(ctx);
2189
+                        nret = ret = cli_scanhwpml(ctx);
2190 2190
                     }
2191 2191
                     break;
2192 2192
                 case CL_TYPE_RARSFX:
... ...
@@ -2441,10 +2437,16 @@ static int magic_scandesc_cleanup(cli_ctx *ctx, cli_file_t type, unsigned char *
2441 2441
 
2442 2442
     UNUSEDPARAM(type);
2443 2443
 
2444
-    if (retcode == CL_CLEAN && (ctx->found_possibly_unwanted || ctx->num_viruses != 0))
2444
+    if (retcode == CL_CLEAN && ctx->found_possibly_unwanted) {
2445
+        cli_virus_found_cb(ctx);
2445 2446
         cb_retcode = CL_VIRUS;
2446
-    else
2447
-        cb_retcode = retcode;
2447
+    }
2448
+    else {
2449
+        if (retcode == CL_CLEAN && ctx->num_viruses != 0)
2450
+            cb_retcode = CL_VIRUS;
2451
+        else
2452
+            cb_retcode = retcode;
2453
+    }
2448 2454
 
2449 2455
     cli_dbgmsg("cli_magic_scandesc: returning %d %s\n", retcode, __AT__);
2450 2456
     if(ctx->engine->cb_post_scan) {
... ...
@@ -2689,6 +2691,7 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
2689 2689
 
2690 2690
     perf_stop(ctx, PERFT_CACHE);
2691 2691
     hashed_size = (*ctx->fmap)->len;
2692
+    memcpy((*ctx->fmap)->maphash, hash, 16);
2692 2693
     ctx->hook_lsig_matches = NULL;
2693 2694
 
2694 2695
     if(!(ctx->options&~CL_SCAN_ALLMATCHES) || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
... ...
@@ -90,8 +90,7 @@ int cli_check_mydoom_log(cli_ctx *ctx)
90 90
     if ((~check) != key)
91 91
 	return CL_CLEAN;
92 92
 
93
-    cli_append_virus(ctx, "Heuristics.Worm.Mydoom.M.log");
94
-    return CL_VIRUS;
93
+    return cli_append_virus(ctx, "Heuristics.Worm.Mydoom.M.log");
95 94
 }
96 95
 
97 96
 static int jpeg_check_photoshop_8bim(cli_ctx *ctx, off_t *off)
... ...
@@ -146,8 +146,7 @@ int cli_parsetiff(cli_ctx *ctx)
146 146
                 if(entry.value + value_size > map->len) {
147 147
                     cli_warnmsg("cli_parsetiff: TFD entry field %u exceeds bounds of TIFF file [%llu > %llu]\n",
148 148
                                 i, (long long unsigned)(entry.value + value_size), (long long unsigned)map->len);
149
-                    cli_append_virus(ctx, "Heuristic.TIFF.OutOfBoundsAccess");
150
-                    return CL_VIRUS;
149
+                    return cli_append_virus(ctx, "Heuristic.TIFF.OutOfBoundsAccess");
151 150
                 }
152 151
             }
153 152
         }
... ...
@@ -556,9 +556,8 @@ static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int
556 556
 
557 557
   if(detect_encrypted && (LH_flags & F_ENCR) && DETECT_ENCRYPTED) {
558 558
     cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n");
559
-    cli_append_virus(ctx, "Heuristics.Encrypted.Zip");
560
-    *ret = CL_VIRUS;
561
-    if (!SCAN_ALL) {
559
+    *ret = cli_append_virus(ctx, "Heuristics.Encrypted.Zip");
560
+    if ((*ret == CL_VIRUS && !SCAN_ALL) || *ret != CL_CLEAN) {
562 561
         fmap_unneed_off(map, loff, SIZEOF_LH);
563 562
         return 0;
564 563
     }
... ...
@@ -461,27 +461,27 @@ static void do_phishing_test_allscan(const struct rtest *rtest)
461 461
 	fail_unless(rc == CL_CLEAN,"phishingScan");
462 462
 	switch(rtest->result) {
463 463
 		case 0:
464
-			fail_unless_fmt(ctx.found_possibly_unwanted,
464
+			fail_unless_fmt(ctx.num_viruses,
465 465
 					"this should be phishing, realURL: %s, displayURL: %s",
466 466
 					rtest->realurl, rtest->displayurl);
467 467
 			break;
468 468
 		case 1:
469
-			fail_unless_fmt(!ctx.found_possibly_unwanted,
469
+			fail_unless_fmt(!ctx.num_viruses,
470 470
 					"this should be whitelisted, realURL: %s, displayURL: %s",
471 471
 					rtest->realurl, rtest->displayurl);
472 472
 			break;
473 473
 		case 2:
474
-			fail_unless_fmt(!ctx.found_possibly_unwanted,
474
+			fail_unless_fmt(!ctx.num_viruses,
475 475
 					"this should be clean, realURL: %s, displayURL: %s",
476 476
 					rtest->realurl, rtest->displayurl);
477 477
 			break;
478 478
 		case 3:
479 479
 			if(!loaded_2)
480
-				fail_unless_fmt(!ctx.found_possibly_unwanted,
480
+				fail_unless_fmt(!ctx.num_viruses,
481 481
 					"this should be clean, realURL: %s, displayURL: %s",
482 482
 					rtest->realurl, rtest->displayurl);
483 483
 			else {
484
-				fail_unless_fmt(ctx.found_possibly_unwanted,
484
+				fail_unless_fmt(ctx.num_viruses,
485 485
 					"this should be blacklisted, realURL: %s, displayURL: %s",
486 486
 					rtest->realurl, rtest->displayurl);
487 487
 				if (*ctx.virname)