
bram-pynzni-qriry at lists
Dec 21, 2011, 8:11 AM
Post #2 of 2
(280 views)
Permalink
|
|
Re: [PATCH] reduce memory usage when scanning zip files
[In reply to]
|
|
Quoting Bram <bram-pynzni-qriry [at] lists>: > I decided to have a look on how to change the behaviour and wrote a > patch for it. > I don't know if this patch is desirable or acceptable but I'm > submitting it anyway. > Patch is against 0.97.3 but should apply cleanly on git master. ... It appears the list removed the attachment so here's an inline version of it: diff -Naur clamav-0.97.3.orig/libclamav/unzip.c clamav-0.97.3.patched/libclamav/unzip.c --- clamav-0.97.3.orig/libclamav/unzip.c 2011-01-10 18:48:28.000000000 +0100 +++ clamav-0.97.3.patched/libclamav/unzip.c 2011-12-21 16:53:29.000000000 +0100 @@ -56,7 +56,7 @@ return inflateInit2(a, b); } -static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, uint16_t flags, unsigned int *fu, cli_ctx *ctx, char *tmpd) { +static int unz(uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, uint16_t flags, unsigned int *fu, cli_ctx *ctx, char *tmpd, fmap_t *map) { char name[1024], obuf[BUFSIZ]; char *tempfile = name; int of, ret=CL_CLEAN; @@ -78,7 +78,7 @@ if(csize<usize) { unsigned int fake = *fu + 1; cli_dbgmsg("cli_unzip: attempting to inflate stored file with inconsistent size\n"); - if ((ret=unz(src, csize, usize, ALG_DEFLATE, 0, &fake, ctx, tmpd))==CL_CLEAN) { + if ((ret=unz(src, csize, usize, ALG_DEFLATE, 0, &fake, ctx, tmpd, map))==CL_CLEAN) { (*fu)++; res=fake-(*fu); } @@ -134,17 +134,57 @@ memset(&strm, 0, sizeof(strm)); - *next_in = src; *next_out = obuf; - *avail_in = csize; *avail_out = sizeof(obuf); if (unz_init(&strm, -wbits)!=Z_OK) { cli_dbgmsg("cli_unzip: zinit failed\n"); break; } - while(1) { - while((res = unz_unz(&strm, Z_NO_FLUSH))==Z_OK) {}; - if(*avail_out!=sizeof(obuf)) { + + int chunk_size = BUFSIZ; + uint32_t remaining = csize; + + do { + /* 'read' a chunk of data */ + if (remaining >= chunk_size) { + if (fmap_need_ptr_once(map, src, chunk_size)) { + *avail_in = chunk_size; + *next_in = src; + + src += chunk_size; + remaining -= chunk_size; + } + else { + cli_dbgmsg("cli_unzip: fmap_need_ptr_once failed?!\n"); + } + } + else { + if (remaining == 0) { + /* corrupted file? zlib has not detected a STREAM_END and expects more but all input is consumed... */ + cli_dbgmsg("cli_unzip: entire input stream used but zlib expets more...\n"); + res = Z_DATA_ERROR; + break; + } + else { + if (fmap_need_ptr_once(map, src, remaining)) { + *avail_in = remaining; + *next_in = src; + + src += remaining; + remaining -= remaining; + } + else { + cli_dbgmsg("cli_unzip: fmap_need_ptr_once failed?!\n"); + } + } + } + + /* inflate the data chunk */ + do { + *next_out = obuf; + *avail_out = sizeof(obuf); + + res = unz_unz(&strm, Z_NO_FLUSH); written+=sizeof(obuf)-(*avail_out); if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) { cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int) ctx->engine->maxfilesize); @@ -157,12 +197,9 @@ res = 100; break; } - *next_out = obuf; - *avail_out = sizeof(obuf); - continue; - } - break; - } + } while (*avail_out == 0); + } while (res != Z_DATA_ERROR && res != Z_STREAM_END && res != 100); + unz_end(&strm); if (res == Z_STREAM_END) res=0; break; @@ -384,8 +421,7 @@ if(LH_flags & F_ENCR) { cli_dbgmsg("cli_unzip: lh - skipping encrypted file\n"); } else { - if(fmap_need_ptr_once(map, zip, csize)) - *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd); + *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd, map); } zip+=csize; zsize-=csize; _______________________________________________ http://lurker.clamav.net/list/clamav-devel.html Please submit your patches to our Bugzilla: http://bugs.clamav.net
|