[Pkg-clamav-commits] [SCM] Debian repository for ClamAV branch, debian/unstable, updated. debian/0.95+dfsg-1-6156-g094ec9b

aCaB acab at clamav.net
Sun Apr 4 00:59:44 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit 511c2e792cf27b0d13ba3503a3cb035bc6581d66
Author: aCaB <acab at clamav.net>
Date:   Tue Aug 11 12:23:14 2009 +0200

    cache
    
    cache over 256 trees

diff --git a/clamd/clamd.c b/clamd/clamd.c
index 26e032f..8151c84 100644
--- a/clamd/clamd.c
+++ b/clamd/clamd.c
@@ -304,6 +304,8 @@ int main(int argc, char **argv)
 	break;
     }
 
+    cache_init(256);
+
     if(!(engine = cl_engine_new())) {
 	logg("!Can't initialize antivirus engine\n");
 	ret = 1;
diff --git a/clamscan/clamscan.c b/clamscan/clamscan.c
index c0ede1d..6cb31e6 100644
--- a/clamscan/clamscan.c
+++ b/clamscan/clamscan.c
@@ -169,6 +169,8 @@ int main(int argc, char **argv)
     gettimeofday(&t1, &tz);
 #endif
 
+    cache_init(256);
+
     ret = scanmanager(opts);
 
     if(!optget(opts, "no-summary")->enabled) {
diff --git a/libclamav/Makefile.am b/libclamav/Makefile.am
index f358bb7..1138959 100644
--- a/libclamav/Makefile.am
+++ b/libclamav/Makefile.am
@@ -323,7 +323,9 @@ libclamav_la_SOURCES = \
 	macho.c \
 	macho.h \
 	ishield.c \
-	ishield.h
+	ishield.h \
+	cache.c \
+	cache.h
 
 if !LINK_TOMMATH
 libclamav_la_SOURCES += bignum.c \
diff --git a/libclamav/Makefile.in b/libclamav/Makefile.in
index 2a8ba22..5d1d591 100644
--- a/libclamav/Makefile.in
+++ b/libclamav/Makefile.in
@@ -131,7 +131,7 @@ am__libclamav_la_SOURCES_DIST = clamav.h matcher-ac.c matcher-ac.h \
 	uniq.h version.c version.h mpool.c mpool.h default.h sha256.c \
 	sha256.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
 	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
-	ishield.c ishield.h bignum.c bignum_class.h
+	ishield.c ishield.h cache.c cache.h bignum.c bignum_class.h
 @LINK_TOMMATH_FALSE at am__objects_1 = libclamav_la-bignum.lo
 am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
 	libclamav_la-matcher-bm.lo libclamav_la-matcher.lo \
@@ -177,7 +177,8 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
 	libclamav_la-version.lo libclamav_la-mpool.lo \
 	libclamav_la-sha256.lo libclamav_la-bytecode.lo \
 	libclamav_la-bytecode_vm.lo libclamav_la-cpio.lo \
-	libclamav_la-macho.lo libclamav_la-ishield.lo $(am__objects_1)
+	libclamav_la-macho.lo libclamav_la-ishield.lo \
+	libclamav_la-cache.lo $(am__objects_1)
 libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
 libclamav_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libclamav_la_CFLAGS) \
@@ -547,7 +548,7 @@ libclamav_la_SOURCES = clamav.h matcher-ac.c matcher-ac.h matcher-bm.c \
 	uniq.h version.c version.h mpool.c mpool.h default.h sha256.c \
 	sha256.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
 	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
-	ishield.c ishield.h $(am__append_7)
+	ishield.c ishield.h cache.c cache.h $(am__append_7)
 noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la
 COMMON_CLEANFILES = version.h version.h.tmp *.gcda *.gcno
 @MAINTAINER_MODE_TRUE at BUILT_SOURCES = jsparse/generated/operators.h jsparse/generated/keywords.h jsparse-keywords.gperf
@@ -681,6 +682,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-bytecode_vm.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-bzlib.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-cab.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-cache.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-chmunpack.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-cpio.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-cvd.Plo at am__quote@
@@ -1417,6 +1419,13 @@ libclamav_la-ishield.lo: ishield.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-ishield.lo `test -f 'ishield.c' || echo '$(srcdir)/'`ishield.c
 
+libclamav_la-cache.lo: cache.c
+ at am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-cache.lo -MD -MP -MF $(DEPDIR)/libclamav_la-cache.Tpo -c -o libclamav_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+ at am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libclamav_la-cache.Tpo $(DEPDIR)/libclamav_la-cache.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cache.c' object='libclamav_la-cache.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+
 libclamav_la-bignum.lo: bignum.c
 @am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-bignum.lo -MD -MP -MF $(DEPDIR)/libclamav_la-bignum.Tpo -c -o libclamav_la-bignum.lo `test -f 'bignum.c' || echo '$(srcdir)/'`bignum.c
 @am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libclamav_la-bignum.Tpo $(DEPDIR)/libclamav_la-bignum.Plo
diff --git a/libclamav/cache.c b/libclamav/cache.c
new file mode 100644
index 0000000..30b3a38
--- /dev/null
+++ b/libclamav/cache.c
@@ -0,0 +1,186 @@
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include "md5.h"
+#include "mpool.h"
+#include "clamav.h"
+#include "cache.h"
+
+#if HAVE_CONFIG_H
+#include "clamav-config.h"
+#endif
+
+#define CACHE_PERTURB 10
+/* 1/10th */
+
+static mpool_t *mempool = NULL;
+static struct CACHE {
+    struct CACHE_ENTRY {
+	unsigned char hash[15];
+	uint32_t dbver;
+	uint32_t hits;
+    } *items;
+    pthread_mutex_t mutex;
+    uint32_t lastdb;
+} *cache = NULL;
+static unsigned int cache_entries = 0;
+
+int cache_init(unsigned int entries) {
+    unsigned int i;
+
+    if(!(mempool = mpool_create())) {
+	cli_errmsg("mpool init fail\n");
+	return 1;
+    }
+    if(!(cache = mpool_malloc(mempool, sizeof(struct CACHE) * 256))) {
+	cli_errmsg("mpool malloc fail\n");
+	mpool_destroy(mempool);
+	return 1;
+    }
+
+    for(i=0; i<256; i++) {
+	struct CACHE_ENTRY *e = mpool_calloc(mempool, sizeof(struct CACHE_ENTRY), entries);
+	if(!e) {
+	    cli_errmsg("mpool calloc fail\n");
+	    mpool_destroy(mempool);
+	    return 1;
+	}
+	cache[i].items = e;
+	cache[i].lastdb = 0;
+	if(pthread_mutex_init(&cache[i].mutex, NULL)) {
+	    cli_errmsg("mutex init fail\n");
+	    mpool_destroy(mempool);
+	    return 1;
+	}
+    }
+    cache_entries = entries;
+    return 0;
+}
+
+void cache_swap(struct CACHE_ENTRY *e, unsigned int a) {
+    struct CACHE_ENTRY t;
+    unsigned int b = a-1;
+
+    if(!a || e[a].hits <= e[b].hits)
+	return;
+
+    do {
+	if(e[a].hits > e[b].hits)
+	    continue;
+	break;
+    } while(b--);
+    b++;
+
+    memcpy(&t, &e[a], sizeof(t));
+    memcpy(&e[a], &e[b], sizeof(t));
+    memcpy(&e[b], &t, sizeof(t));
+}
+
+void updb(uint32_t db, unsigned int skip) {
+    unsigned int i;
+    for(i=0; i<256; i++) {
+	if(i==skip) continue;
+	if(pthread_mutex_lock(&cache[i].mutex)) {
+	    cli_errmsg("mutex lock fail\n");
+	    continue;
+	}
+	cache[i].lastdb = db;
+	pthread_mutex_unlock(&cache[i].mutex);	
+    }
+}
+
+int cache_check(unsigned char *md5, cli_ctx *ctx) {
+    unsigned int i;
+    int ret = CL_VIRUS;
+    struct CACHE_ENTRY *e;
+    struct CACHE *c;
+
+    if(!cache) return ret;
+
+    c = &cache[*md5];
+    e = c->items;
+    if(pthread_mutex_lock(&c->mutex)) {
+	cli_errmsg("mutex lock fail\n");
+	return ret;
+    }
+    if(c->lastdb <= ctx->engine->dbversion[0]) {
+	if(c->lastdb < ctx->engine->dbversion[0]) {
+	    c->lastdb = ctx->engine->dbversion[0];
+	    updb(c->lastdb, *md5);
+	} else {
+	    for(i=0; i<cache_entries; i++) {
+		if(!e[i].hits) break;
+		if(e[i].dbver == c->lastdb && !memcmp(e[i].hash, md5 + 1, 15)) {
+		    e[i].hits++;
+		    cache_swap(e, i);
+		    ret = CL_CLEAN;
+		    cli_warnmsg("cached\n");
+		    break;
+		}
+	    }
+	}
+    }
+    pthread_mutex_unlock(&c->mutex);
+    return ret;
+}
+
+void cache_add(unsigned char *md5, cli_ctx *ctx) {
+    unsigned int i, replace;
+    struct CACHE_ENTRY *e;
+    struct CACHE *c;
+
+    if(!cache) return;
+
+    c = &cache[*md5];
+    e = c->items;
+    if(pthread_mutex_lock(&c->mutex)) {
+	cli_errmsg("mutex lock fail\n");
+	return;
+    }
+    if(c->lastdb == ctx->engine->dbversion[0]) {
+	replace = cache_entries;
+	for(i=0; i<cache_entries; i++) {
+	    if(!e[i].hits) break;
+	    if(replace == cache_entries && e[i].dbver < c->lastdb) {
+		replace = i;
+	    } else if(e[i].hits && !memcmp(e[i].hash, md5 + 1, 15)) {
+		e[i].hits++;
+		cache_swap(e, i);
+		pthread_mutex_unlock(&c->mutex);
+		return;
+	    }
+	}
+	if(replace == cache_entries)
+	    replace = cache_entries - 1 - (rand() % (cache_entries / CACHE_PERTURB));
+	e[replace].hits = 1;
+	e[replace].dbver = c->lastdb;
+	memcpy(e[replace].hash, md5 + 1, 15);
+	cache_swap(e, replace);
+    }
+    pthread_mutex_unlock(&c->mutex);
+    return;
+}
+
+int cache_chekdesc(int desc, size_t size, unsigned char *hash, cli_ctx *ctx) {
+    cli_md5_ctx md5;
+    unsigned char buf[8192];
+    
+    off_t seekback = lseek(desc, 0, SEEK_CUR);
+
+    if(!cache) return CL_VIRUS;
+
+    cli_md5_init(&md5);
+    while(size) {
+	size_t readme = size < sizeof(buf) ? size : sizeof(buf);
+	if(cli_readn(desc, buf, readme)!=readme) {
+	    lseek(desc, seekback, SEEK_SET);
+	    return CL_VIRUS;
+	}
+	cli_md5_update(&md5, buf, readme);
+	size-=readme;
+    }
+    cli_md5_final(hash, &md5);
+    lseek(desc, seekback, SEEK_SET);
+    return cache_check(hash, ctx);
+}
diff --git a/libclamav/cache.h b/libclamav/cache.h
new file mode 100644
index 0000000..d70a7dc
--- /dev/null
+++ b/libclamav/cache.h
@@ -0,0 +1,11 @@
+#ifndef __CACHE_H
+#define __CACHE_H
+
+#include "others.h"
+
+int cache_init(unsigned int entries);
+int cache_check(unsigned char *md5, cli_ctx *ctx);
+void cache_add(unsigned char *md5, cli_ctx *ctx);
+int cache_chekdesc(int desc, size_t size, unsigned char *hash, cli_ctx *ctx);
+
+#endif
diff --git a/libclamav/libclamav.map b/libclamav/libclamav.map
index ea2d7be..40d1b25 100644
--- a/libclamav/libclamav.map
+++ b/libclamav/libclamav.map
@@ -154,6 +154,7 @@ CLAMAV_PRIVATE {
     cli_bytecode_context_setparam_ptr;
     cli_bytecode_context_getresult_int;
     cli_bytecode_context_clear;
+    cache_init;
   local:
     *;
 };
diff --git a/libclamav/matcher.c b/libclamav/matcher.c
index dd2008d..32680dc 100644
--- a/libclamav/matcher.c
+++ b/libclamav/matcher.c
@@ -445,3 +445,173 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
 
     return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
 }
+
+int cli_scandesc_hash(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned char *digest)
+{
+ 	unsigned char *buffer, *buff, *endbl, *upt;
+	int ret = CL_CLEAN, type = CL_CLEAN, bytes;
+	unsigned int i, evalcnt;
+	uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0;
+	uint64_t evalids;
+	struct cli_ac_data gdata, tdata;
+	struct cli_matcher *groot = NULL, *troot = NULL;
+
+
+    if(!ctx->engine) {
+	cli_errmsg("cli_scandesc: engine == NULL\n");
+	return CL_ENULLARG;
+    }
+
+    if(!ftonly)
+	groot = ctx->engine->root[0]; /* generic signatures */
+
+    if(ftype) {
+	for(i = 1; i < CLI_MTARGETS; i++) {
+	    if(cli_mtargets[i].target == ftype) {
+		troot = ctx->engine->root[i];
+		break;
+	    }
+	}
+    }
+
+    if(ftonly) {
+	if(!troot)
+	    return CL_CLEAN;
+
+	maxpatlen = troot->maxpatlen;
+    } else {
+	if(troot)
+	    maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
+	else
+	    maxpatlen = groot->maxpatlen;
+    }
+
+    /* prepare the buffer */
+    buffersize = maxpatlen + SCANBUFF;
+    if(!(buffer = (unsigned char *) cli_calloc(buffersize, sizeof(unsigned char)))) {
+	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%u)\n", buffersize);
+	return CL_EMEM;
+    }
+
+    if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
+	return ret;
+
+    if(troot) {
+	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
+	    return ret;
+    }
+
+    buff = buffer;
+    buff += maxpatlen; /* pointer to read data block */
+    endbl = buff + SCANBUFF - maxpatlen; /* pointer to the last block
+					  * length of maxpatlen
+					  */
+
+    upt = buff;
+    while((bytes = cli_readn(desc, buff + shift, SCANBUFF - shift)) > 0) {
+
+	if(ctx->scanned)
+	    *ctx->scanned += bytes / CL_COUNT_PRECISION;
+
+	length = shift + bytes;
+	if(upt == buffer)
+	    length += maxpatlen;
+
+	if(troot) {
+	    if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, ftype, desc)) != CL_VIRUS)
+		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, desc, ftoffset, acmode, NULL);
+
+	    if(ret == CL_VIRUS) {
+		free(buffer);
+		if(!ftonly)
+		    cli_ac_freedata(&gdata);
+		cli_ac_freedata(&tdata);
+
+		if(cli_checkfp(desc, ctx))
+		    return CL_CLEAN;
+		else
+		    return CL_VIRUS;
+	    }
+	}
+
+	if(!ftonly) {
+	    if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, ftype, desc)) != CL_VIRUS)
+		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, desc, ftoffset, acmode, NULL);
+
+	    if(ret == CL_VIRUS) {
+		free(buffer);
+		cli_ac_freedata(&gdata);
+		if(troot)
+		    cli_ac_freedata(&tdata);
+		if(cli_checkfp(desc, ctx))
+		    return CL_CLEAN;
+		else
+		    return CL_VIRUS;
+
+	    } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
+		if(ret > type)
+		    type = ret;
+	    }
+	}
+
+	if(bytes + shift == SCANBUFF) {
+	    memmove(buffer, endbl, maxpatlen);
+	    offset += SCANBUFF;
+
+	    if(upt == buff) {
+		upt = buffer;
+		offset -= maxpatlen;
+	    }
+
+	    shift = 0;
+
+	} else {
+	    shift += bytes;
+	}
+    }
+
+    free(buffer);
+
+    if(troot) {
+	for(i = 0; i < troot->ac_lsigs; i++) {
+	    evalcnt = 0;
+	    evalids = 0;
+	    if(cli_ac_chklsig(troot->ac_lsigtable[i]->logic, troot->ac_lsigtable[i]->logic + strlen(troot->ac_lsigtable[i]->logic), tdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
+		if(ctx->virname)
+		    *ctx->virname = troot->ac_lsigtable[i]->virname;
+		ret = CL_VIRUS;
+		break;
+	    }
+	}
+	cli_ac_freedata(&tdata);
+    }
+
+    if(groot) {
+	if(ret != CL_VIRUS) for(i = 0; i < groot->ac_lsigs; i++) {
+	    evalcnt = 0;
+	    evalids = 0;
+	    if(cli_ac_chklsig(groot->ac_lsigtable[i]->logic, groot->ac_lsigtable[i]->logic + strlen(groot->ac_lsigtable[i]->logic), gdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
+		if(ctx->virname)
+		    *ctx->virname = groot->ac_lsigtable[i]->virname;
+		ret = CL_VIRUS;
+		break;
+	    }
+	}
+	cli_ac_freedata(&gdata);
+    }
+
+    if(ret == CL_VIRUS) {
+	lseek(desc, 0, SEEK_SET);
+	if(cli_checkfp(desc, ctx))
+	    return CL_CLEAN;
+	else
+	    return CL_VIRUS;
+    }
+
+    if(!ftonly && ctx->engine->md5_hdb) {
+	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS))
+	    return CL_VIRUS;
+    }
+
+    return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
+}
diff --git a/libclamav/matcher.h b/libclamav/matcher.h
index 82d030b..e6adc7c 100644
--- a/libclamav/matcher.h
+++ b/libclamav/matcher.h
@@ -127,6 +127,7 @@ struct cli_target_info {
 int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata);
 
 int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode);
+int cli_scandesc_hash(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned char *digest);
 
 int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname);
 
diff --git a/libclamav/scanners.c b/libclamav/scanners.c
index 7f6a1be..085a0eb 100644
--- a/libclamav/scanners.c
+++ b/libclamav/scanners.c
@@ -96,6 +96,7 @@
 #include "macho.h"
 #include "ishield.h"
 #include "7z.h"
+#include "cache.h"
 
 #ifdef HAVE_BZLIB_H
 #include <bzlib.h>
@@ -1881,6 +1882,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
 	cli_file_t type, dettype = 0;
 	struct stat sb;
 	uint8_t typercg = 1;
+	unsigned char hash[16];
 
     if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
         cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
@@ -1910,13 +1912,17 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
     if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
         return CL_CLEAN;
 
+    if(cache_chekdesc(desc, sb.st_size, hash, ctx) == CL_CLEAN)
+	return CL_CLEAN;
+    
     if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
 	if(ctx->recursion == ctx->engine->maxreclevel)
 	    cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
 	else
 	    cli_dbgmsg("Raw mode: No support for special files\n");
-	if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
+	if((ret = cli_scandesc_hash(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, hash)) == CL_VIRUS)
 	    cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
+	else cache_add(hash, ctx);
 	return ret;
     }
 
@@ -2177,8 +2183,10 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
 	case CL_EMAXSIZE:
 	case CL_EMAXFILES:
 	    cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
+	    cache_add(hash, ctx);
 	    return CL_CLEAN;
 	default:
+	    if(ret == CL_CLEAN) cache_add(hash, ctx);
 	    return ret;
     }
 }

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list