[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 01:03:48 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit 10aa2df79bb24168ab216f588f92d3c54c077e56
Merge: 686ed348884c29a1f72e131c2a32717a3866c454 dd3b1850e0f0102c2f4ea1bc21b843ec1b437962
Author: aCaB <acab at clamav.net>
Date:   Wed Sep 2 00:09:28 2009 +0200

    Merge branch 'replace-mmap' into fmap4all
    
    Conflicts:
    	libclamav/matcher-bm.c
    	libclamav/matcher-bm.h
    	libclamav/matcher.c
    	libclamav/pe.c
    	libclamav/phishcheck.c
    	libclamav/regex_list.c

diff --combined libclamav/matcher-ac.c
index 9918dc7,ca2eead..2f3c144
--- a/libclamav/matcher-ac.c
+++ b/libclamav/matcher-ac.c
@@@ -830,32 -830,37 +830,32 @@@ int cli_ac_initdata(struct cli_ac_data 
      return CL_SUCCESS;
  }
  
 -int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, int fd)
 +int cli_ac_caloff(const struct cli_matcher *root, struct cli_ac_data *data, struct F_MAP *map)
  {
  	int ret;
  	unsigned int i;
  	struct cli_ac_patt *patt;
  	struct cli_target_info info;
 -	struct stat sb;
  
 -    if(fd != -1) {
 +    if(map) {
  	memset(&info, 0, sizeof(info));
 -	if(fstat(fd, &sb) == -1) {
 -	    cli_errmsg("cli_ac_caloff: fstat(%d) failed\n", fd);
 -	    return CL_ESTAT;
 -	}
 -	info.fsize = sb.st_size;
 +	info.fsize = map->len;
      }
  
      for(i = 0; i < root->ac_reloff_num; i++) {
  	patt = root->ac_reloff[i];
 -	if(fd == -1) {
 +	if(!map) {
  	    data->offset[patt->offset_min] = CLI_OFF_NONE;
 -	} else if((ret = cli_caloff(NULL, &info, fd, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
 +	} else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], &data->offset[patt->offset_max]))) {
  	    cli_errmsg("cli_ac_caloff: Can't calculate relative offset in signature for %s\n", patt->virname);
  	    if(info.exeinfo.section)
  		free(info.exeinfo.section);
  	    return ret;
- 	} else if(data->offset[patt->offset_min] + patt->length > info.fsize) {
+ 	} else if((data->offset[patt->offset_min] != CLI_OFF_NONE) && (data->offset[patt->offset_min] + patt->length > info.fsize)) {
  	    data->offset[patt->offset_min] = CLI_OFF_NONE;
  	}
      }
 -    if(fd != -1 && info.exeinfo.section)
 +    if(map && info.exeinfo.section)
  	free(info.exeinfo.section);
  
      return CL_SUCCESS;
@@@ -1486,7 -1491,7 +1486,7 @@@ int cli_ac_addsig(struct cli_matcher *r
      if(new->lsigid[0])
  	root->ac_lsigtable[new->lsigid[1]]->virname = new->virname;
  
 -    ret = cli_caloff(offset, NULL, -1, root->type, new->offdata, &new->offset_min, &new->offset_max);
 +    ret = cli_caloff(offset, NULL, NULL, root->type, new->offdata, &new->offset_min, &new->offset_max);
      if(ret != CL_SUCCESS) {
  	mpool_free(root->mempool, new->prefix ? new->prefix : new->pattern);
  	mpool_ac_free_alt(root->mempool, new);
diff --combined libclamav/matcher-bm.c
index 40e13fa,44f6083..6b592eb
--- a/libclamav/matcher-bm.c
+++ b/libclamav/matcher-bm.c
@@@ -51,7 -51,7 +51,7 @@@ int cli_bm_addpatt(struct cli_matcher *
  	return CL_EMALFDB;
      }
  
 -    if((ret = cli_caloff(offset, NULL, -1, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
 +    if((ret = cli_caloff(offset, NULL, NULL, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
  	cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
  	return ret;
      }
@@@ -104,6 -104,17 +104,17 @@@
      pattern->pattern0 = pattern->pattern[0];
      root->bm_suffix[idx]->cnt++;
  
+     if(root->bm_offmode) {
+ 	root->bm_pattab = (struct cli_bm_patt **) mpool_realloc2(root->mempool, root->bm_pattab, (root->bm_patterns + 1) * sizeof(struct cli_bm_patt *));
+ 	if(!root->bm_pattab) {
+ 	    cli_errmsg("cli_bm_addpatt: Can't allocate memory for root->bm_pattab\n");
+ 	    return CL_EMEM;
+ 	}
+ 	root->bm_pattab[root->bm_patterns] = pattern;
+ 	if(pattern->offdata[0] != CLI_OFF_ABSOLUTE)
+ 	    pattern->offset_min = root->bm_patterns;
+     }
+ 
      root->bm_patterns++;
      return CL_SUCCESS;
  }
@@@ -114,6 -125,7 +125,7 @@@ int cli_bm_init(struct cli_matcher *roo
  #ifdef USE_MPOOL
      assert (root->mempool && "mempool must be initialized");
  #endif
+ 
      if(!(root->bm_shift = (uint8_t *) mpool_calloc(root->mempool, size, sizeof(uint8_t))))
  	return CL_EMEM;
  
@@@ -128,6 -140,78 +140,73 @@@
      return CL_SUCCESS;
  }
  
+ static int qcompare(const void *a, const void *b)
+ {
+     return *(const uint32_t *)a - *(const uint32_t *)b;
+ }
+ 
 -int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, int fd)
++int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, struct F_MAP *map)
+ {
+ 	int ret;
+ 	unsigned int i;
+ 	struct cli_bm_patt *patt;
+ 	struct cli_target_info info;
 -	struct stat sb;
+ 
+ 
+     if(!root->bm_patterns) {
+ 	data->offtab = data->offset = 0;
+ 	data->cnt = data->pos = 0;
+ 	return CL_SUCCESS;
+     }
+     memset(&info, 0, sizeof(info));
 -    if(fstat(fd, &sb) == -1) {
 -	cli_errmsg("cli_bm_initoff: fstat(%d) failed\n", fd);
 -	return CL_ESTAT;
 -    }
 -    info.fsize = sb.st_size;
++    info.fsize = map->len;
+ 
+     data->cnt = data->pos = 0;
+     data->offtab = (uint32_t *) cli_malloc(root->bm_patterns * sizeof(uint32_t));
+     if(!data->offtab) {
+ 	cli_errmsg("cli_bm_initoff: Can't allocate memory for data->offtab\n");
+ 	return CL_EMEM;
+     }
+     data->offset = (uint32_t *) cli_malloc(root->bm_patterns * sizeof(uint32_t));
+     if(!data->offset) {
+ 	cli_errmsg("cli_bm_initoff: Can't allocate memory for data->offset\n");
+ 	free(data->offtab);
+ 	return CL_EMEM;
+     }
+     for(i = 0; i < root->bm_patterns; i++) {
+ 	patt = root->bm_pattab[i];
+ 	if(patt->offdata[0] == CLI_OFF_ABSOLUTE) {
+ 	    data->offtab[data->cnt] = patt->offset_min + patt->prefix_length;
+ 	    data->cnt++;
 -	} else if((ret = cli_caloff(NULL, &info, fd, root->type, patt->offdata, &data->offset[patt->offset_min], NULL))) {
++	} else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], NULL))) {
+ 	    cli_errmsg("cli_bm_initoff: Can't calculate relative offset in signature for %s\n", patt->virname);
+ 	    if(info.exeinfo.section)
+ 		free(info.exeinfo.section);
+ 	    free(data->offtab);
+ 	    free(data->offset);
+ 	    return ret;
+ 	} else if((data->offset[patt->offset_min] != CLI_OFF_NONE) && (data->offset[patt->offset_min] + patt->length <= info.fsize)) {
+ 	    if(!data->cnt || (data->offset[patt->offset_min] != data->offtab[data->cnt - 1])) {
+ 		data->offtab[data->cnt] = data->offset[patt->offset_min] + patt->prefix_length;
+ 		data->cnt++;
+ 	    }
+ 	}
+     }
+     if(info.exeinfo.section)
+ 	free(info.exeinfo.section);
+ 
+     qsort(data->offtab, data->cnt, sizeof(uint32_t), qcompare);
+     return CL_SUCCESS;
+ }
+ 
+ void cli_bm_freeoff(struct cli_bm_off *data)
+ {
+     free(data->offset);
+     data->offset = NULL;
+     free(data->offtab);
+     data->offtab = NULL;
+ }
+ 
  void cli_bm_free(struct cli_matcher *root)
  {
  	struct cli_bm_patt *patt, *prev;
@@@ -137,6 -221,9 +216,9 @@@
      if(root->bm_shift)
  	mpool_free(root->mempool, root->bm_shift);
  
+     if(root->bm_pattab)
+ 	mpool_free(root->mempool, root->bm_pattab);
+ 
      if(root->bm_suffix) {
  	for(i = 0; i < size; i++) {
  	    patt = root->bm_suffix[i];
@@@ -156,7 -243,7 +238,7 @@@
      }
  }
  
- int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, struct F_MAP *map)
 -int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata)
++int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, struct F_MAP *map, struct cli_bm_off *offdata)
  {
  	uint32_t i, j, off, off_min, off_max;
  	uint8_t found, pchain, shift;
@@@ -174,7 -261,13 +256,13 @@@
  	return CL_CLEAN;
  
      memset(&info, 0, sizeof(info));
-     for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) {
+     i = BM_MIN_LENGTH - BM_BLOCK_SIZE;
+     if(offdata) {
+ 	if(offdata->pos == offdata->cnt)
+ 	    return CL_CLEAN;
+ 	i += offdata->offtab[offdata->pos] - offset;
+     }
+     for(; i < length - BM_BLOCK_SIZE + 1; ) {
  	idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]);
  	shift = root->bm_shift[idx];
  
@@@ -182,7 -275,15 +270,15 @@@
  	    prefix = buffer[i - BM_MIN_LENGTH + BM_BLOCK_SIZE];
  	    p = root->bm_suffix[idx];
  	    if(p && p->cnt == 1 && p->pattern0 != prefix) {
- 		i++;
+ 		if(offdata) {
+ 		    off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
+ 		    for(; off >= offdata->offtab[offdata->pos] && offdata->pos < offdata->cnt; offdata->pos++);
+ 		    if(offdata->pos == offdata->cnt || off >= offdata->offtab[offdata->pos])
+ 			return CL_CLEAN;
+ 		    i += offdata->offtab[offdata->pos] - off;
+ 		} else {
+ 		    i++;
+ 		}
  		continue;
  	    }
  	    pchain = 0;
@@@ -202,6 -303,18 +298,18 @@@
  		    continue;
  		}
  
+ 		if(offdata) {
+ 		    if(p->offdata[0] == CLI_OFF_ABSOLUTE) {
+ 			if(p->offset_min != offset + off - p->prefix_length) {
+ 			    p = p->next;
+ 			    continue;
+ 			}
+ 		    } else if((offdata->offset[p->offset_min] == CLI_OFF_NONE) || (offdata->offset[p->offset_min] != offset + off - p->prefix_length)) {
+ 			p = p->next;
+ 			continue;
+ 		    }
+ 		}
+ 
  		idxchk = MIN(p->length, length - off) - 1;
  		if(idxchk) {
  		    if((bp[idxchk] != p->pattern[idxchk]) ||  (bp[idxchk / 2] != p->pattern[idxchk / 2])) {
@@@ -227,9 -340,9 +335,9 @@@
  		}
  
  		if(found && p->length + p->prefix_length == j) {
- 		    if(p->offset_min != CLI_OFF_ANY) {
+ 		    if(!offdata && (p->offset_min != CLI_OFF_ANY)) {
  			if(p->offdata[0] != CLI_OFF_ABSOLUTE) {
 -			    ret = cli_caloff(NULL, &info, fd, root->type, p->offdata, &off_min, &off_max);
 +			    ret = cli_caloff(NULL, &info, map, root->type, p->offdata, &off_min, &off_max);
  			    if(ret != CL_SUCCESS) {
  				cli_errmsg("cli_bm_scanbuff: Can't calculate relative offset in signature for %s\n", p->virname);
  				if(info.exeinfo.section)
@@@ -252,14 -365,21 +360,21 @@@
  			free(info.exeinfo.section);
  		    return CL_VIRUS;
  		}
- 
  		p = p->next;
  	    }
  	    shift = 1;
  	}
  
- 	i += shift;
+ 	if(offdata) {
+ 	    off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
+ 	    for(; off >= offdata->offtab[offdata->pos] && offdata->pos < offdata->cnt; offdata->pos++);
+ 	    if(offdata->pos == offdata->cnt || off >= offdata->offtab[offdata->pos])
+ 		return CL_CLEAN;
+ 	    i += offdata->offtab[offdata->pos] - off;
+ 	} else {
+ 	    i += shift;
+ 	}
+ 
      }
  
      if(info.exeinfo.section)
diff --combined libclamav/matcher-bm.h
index 834867c,75e2e94..b6a0059
--- a/libclamav/matcher-bm.h
+++ b/libclamav/matcher-bm.h
@@@ -24,7 -24,6 +24,7 @@@
  #include "matcher.h"
  #include "filetypes.h"
  #include "cltypes.h"
 +#include "fmap.h"
  
  struct cli_bm_patt {
      unsigned char *pattern, *prefix;
@@@ -36,9 -35,15 +36,15 @@@
      unsigned char pattern0;
  };
  
+ struct cli_bm_off {
+     uint32_t *offset, *offtab, cnt, pos;
+ };
+ 
  int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset);
  int cli_bm_init(struct cli_matcher *root);
- int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, struct F_MAP *map);
 -int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, int fd);
++int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, struct F_MAP *map);
+ void cli_bm_freeoff(struct cli_bm_off *data);
 -int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, int fd, struct cli_bm_off *offdata);
++int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_matcher *root, uint32_t offset, struct F_MAP *map, struct cli_bm_off *offdata);
  void cli_bm_free(struct cli_matcher *root);
  
  #endif
diff --combined libclamav/matcher.c
index 221e129,9573f8f..d91cb3e
--- a/libclamav/matcher.c
+++ b/libclamav/matcher.c
@@@ -45,7 -45,6 +45,7 @@@
  #include "cltypes.h"
  #include "default.h"
  #include "macho.h"
 +#include "fmap.h"
  
  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)
  {
@@@ -77,7 -76,7 +77,7 @@@
  	if(!acdata && (ret = cli_ac_initdata(&mdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
  	    return ret;
  
- 	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, NULL)) != CL_VIRUS)
 -	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, -1, NULL)) != CL_VIRUS)
++	if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, NULL, NULL)) != CL_VIRUS)
  	    ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, troot, acdata ? (acdata[0]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
  
  	if(!acdata)
@@@ -90,7 -89,7 +90,7 @@@
      if(!acdata && (ret = cli_ac_initdata(&mdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)))
  	return ret;
  
-     if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, NULL)) != CL_VIRUS)
 -    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, -1, NULL)) != CL_VIRUS)
++    if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, NULL, NULL)) != CL_VIRUS)
  	ret = cli_ac_scanbuff(buffer, length, virname, NULL, NULL, groot, acdata ? (acdata[1]) : (&mdata), offset, ftype, NULL, AC_SCAN_VIR, NULL);
  
      if(!acdata)
@@@ -105,12 -104,15 +105,12 @@@
   * offdata[2]: max shift
   * offdata[3]: section number
   */
 -int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
 +int cli_caloff(const char *offstr, struct cli_target_info *info, struct F_MAP *map, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max)
  {
 -	int (*einfo)(int, struct cli_exe_info *) = NULL;
 +	int (*einfo)(struct F_MAP *, struct cli_exe_info *) = NULL;
  	char offcpy[65];
  	unsigned int n, val;
  	char *pt;
 -	off_t pos;
 -	struct stat sb;
 -
  
      if(!info) { /* decode offset string */
  	if(!offstr) {
@@@ -199,13 -201,21 +199,15 @@@
      } else {
  	/* calculate relative offsets */
  	if(info->status == -1) {
- 	    *offset_min = *offset_max = 0;
+ 	    *offset_min = CLI_OFF_NONE;
+ 	    if(offset_max)
+ 		*offset_max = CLI_OFF_NONE;
  	    return CL_SUCCESS;
  	}
  
  	if((offdata[0] == CLI_OFF_EOF_MINUS)) {
 -	    if(!info->fsize) {
 -		if(fstat(fd, &sb) == -1) {
 -		    cli_errmsg("cli_caloff: fstat(%d) failed\n", fd);
 -		    return CL_ESTAT;
 -		}
 -		info->fsize = sb.st_size;
 -	    }
 -
 +	    if(!info->fsize)
 +		info->fsize = map->len;
  	} else if(!info->status) {
  	    if(target == 1)
  		einfo = cli_peheader;
@@@ -219,12 -229,22 +221,14 @@@
  		return CL_EMALFDB;
  	    }
  
 -	    if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
 -		cli_errmsg("cli_caloff: lseek(%d) failed\n", fd);
 -		return CL_ESEEK;
 -	    }
 -
 -	    lseek(fd, 0, SEEK_SET);
 -	    if(einfo(fd, &info->exeinfo)) {
 +	    if(einfo(map, &info->exeinfo)) {
  		/* einfo *may* fail */
 -		lseek(fd, pos, SEEK_SET);
  		info->status = -1;
- 		*offset_min = *offset_max = 0;
+ 		*offset_min = CLI_OFF_NONE;
+ 		if(offset_max)
+ 		    *offset_max = CLI_OFF_NONE;
  		return CL_SUCCESS;
  	    }
 -	    lseek(fd, pos, SEEK_SET);
  	    info->status = 1;
  	}
  
@@@ -247,7 -267,7 +251,7 @@@
  
  	    case CLI_OFF_SX_PLUS:
  		if(offdata[3] >= info->exeinfo.nsections)
- 		    *offset_min = 0;
+ 		    *offset_min = CLI_OFF_NONE;
  		else
  		    *offset_min = info->exeinfo.section[offdata[3]].raw + offdata[1];
  		break;
@@@ -257,9 -277,7 +261,7 @@@
  		return CL_EARG;
  	}
  
- 	if(!*offset_min)
- 	    *offset_max = 0;
- 	else
+ 	if(offset_max && *offset_min != CLI_OFF_NONE)
  	    *offset_max = *offset_min + offdata[2];
      }
  
@@@ -287,7 -305,7 +289,7 @@@ int cli_checkfp(int fd, cli_ctx *ctx
  	    return 0;
  	}
  
- 	if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, NULL) == CL_VIRUS) {
 -	if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, -1, NULL) == CL_VIRUS) {
++	if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, NULL, NULL) == CL_VIRUS) {
  	    cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
  	    free(digest);
  	    lseek(fd, pos, SEEK_SET);
@@@ -302,30 -320,18 +304,31 @@@
  
  int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
  {
 - 	unsigned char *buffer, *buff, *endbl, *upt;
 +    int ret = CL_EMEM;
 +    struct F_MAP *map = *ctx->fmap;
 +
 +    if((*ctx->fmap = fmap(desc, 0, 0))) {
 +	ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode);
 +	fmunmap(*ctx->fmap);
 +    }
 +    *ctx->fmap = map;
 +    return ret;
 +}
 +
 +
 +int cli_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode)
 +{
 + 	unsigned char *buff;
  	int ret = CL_CLEAN, type = CL_CLEAN, bytes;
- 	unsigned int i, evalcnt;
+ 	unsigned int i, evalcnt, bm_offmode = 0;
 -	uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0;
 +	uint32_t maxpatlen, offset = 0;
  	uint64_t evalids;
  	struct cli_ac_data gdata, tdata;
+ 	struct cli_bm_off toff;
  	cli_md5_ctx md5ctx;
  	unsigned char digest[16];
  	struct cli_matcher *groot = NULL, *troot = NULL;
 -	struct stat sb;
 -
 +	struct F_MAP *map = *ctx->fmap;
  
      if(!ctx->engine) {
  	cli_errmsg("cli_scandesc: engine == NULL\n");
@@@ -356,39 -362,70 +359,51 @@@
  	    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)
 -	if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, desc)))
 +	if((ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, groot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(groot, &gdata, map)))
  	    return ret;
  
      if(troot) {
 -	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, desc))) {
 +	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, troot->ac_reloff_num, CLI_DEFAULT_AC_TRACKLEN)) || (ret = cli_ac_caloff(troot, &tdata, map))) {
  	    if(!ftonly)
  		cli_ac_freedata(&gdata);
  	    return ret;
  	}
+ 	if(troot->bm_offmode) {
 -	    if(fstat(desc, &sb) != -1) {
 -		if(sb.st_size >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
 -		    if((ret = cli_bm_initoff(troot, &toff, desc))) {
 -			if(!ftonly)
 -			    cli_ac_freedata(&gdata);
 -			cli_ac_freedata(&tdata);
 -			return ret;
 -		    }
 -		    bm_offmode = 1;
++	    if(map->len >= CLI_DEFAULT_BM_OFFMODE_FSIZE) {
++		if((ret = cli_bm_initoff(troot, &toff, map))) {
++		    if(!ftonly)
++			cli_ac_freedata(&gdata);
++		    cli_ac_freedata(&tdata);
++		    return ret;
+ 		}
++		bm_offmode = 1;
+ 	    }
+ 	}
      }
  
      if(!ftonly && ctx->engine->md5_hdb)
  	cli_md5_init(&md5ctx);
  
 -    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) {
 -
 +    while(offset < map->len) {
 +	bytes = map->len - offset > SCANBUFF ? SCANBUFF : map->len - offset;
 +	if(!(buff = fmap_need_off_once(map, offset, bytes))) {
 +	    /* FIXME: FAIL HERE */
 +	}
  	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(buff, bytes, ctx->virname, troot, offset, map)) != CL_VIRUS)
 -	    if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, desc, bm_offmode ? &toff : NULL)) != CL_VIRUS)
 -		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
 -
++	    if(troot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, troot, offset, map, bm_offmode ? &toff : NULL)) != CL_VIRUS)
 +		ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, ftoffset, acmode, NULL);
- 
  	    if(ret == CL_VIRUS) {
  		if(!ftonly)
  		    cli_ac_freedata(&gdata);
  		cli_ac_freedata(&tdata);
+ 		if(bm_offmode)
+ 		    cli_bm_freeoff(&toff);
  
 -		if(cli_checkfp(desc, ctx))
 +		if(cli_checkfp(map->fd, ctx))
  		    return CL_CLEAN;
  		else
  		    return CL_VIRUS;
@@@ -396,14 -433,18 +411,16 @@@
  	}
  
  	if(!ftonly) {
- 	    if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, groot, offset, map)) != CL_VIRUS)
 -	    if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, desc, NULL)) != CL_VIRUS)
 -		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
 -
++	    if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, groot, offset, map, NULL)) != CL_VIRUS)
 +		ret = cli_ac_scanbuff(buff, bytes, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, ftoffset, acmode, NULL);
- 
  	    if(ret == CL_VIRUS) {
 -		free(buffer);
  		cli_ac_freedata(&gdata);
- 		if(troot)
+ 		if(troot) {
  		    cli_ac_freedata(&tdata);
+ 		    if(bm_offmode)
+ 			cli_bm_freeoff(&toff);
+ 		}
 -		if(cli_checkfp(desc, ctx))
 +		if(cli_checkfp(map->fd, ctx))
  		    return CL_CLEAN;
  		else
  		    return CL_VIRUS;
@@@ -414,13 -455,27 +431,13 @@@
  	    }
  
  	    if(ctx->engine->md5_hdb)
 -		cli_md5_update(&md5ctx, buff + shift, bytes);
 +		cli_md5_update(&md5ctx, buff + maxpatlen * (offset!=0), bytes - maxpatlen * (offset!=0));
  	}
  
 -	if(bytes + shift == SCANBUFF) {
 -	    memmove(buffer, endbl, maxpatlen);
 -	    offset += SCANBUFF;
 -
 -	    if(upt == buff) {
 -		upt = buffer;
 -		offset -= maxpatlen;
 -	    }
 -
 -	    shift = 0;
 -
 -	} else {
 -	    shift += bytes;
 -	}
 +	if(bytes < SCANBUFF) break;
 +	offset += SCANBUFF - maxpatlen;
      }
  
 -    free(buffer);
 -
      if(troot) {
  	for(i = 0; i < troot->ac_lsigs; i++) {
  	    evalcnt = 0;
@@@ -433,6 -488,8 +450,8 @@@
  	    }
  	}
  	cli_ac_freedata(&tdata);
+ 	if(bm_offmode)
+ 	    cli_bm_freeoff(&toff);
      }
  
      if(groot) {
@@@ -450,8 -507,8 +469,8 @@@
      }
  
      if(ret == CL_VIRUS) {
 -	lseek(desc, 0, SEEK_SET);
 -	if(cli_checkfp(desc, ctx))
 +	lseek(map->fd, 0, SEEK_SET);
 +	if(cli_checkfp(map->fd, ctx))
  	    return CL_CLEAN;
  	else
  	    return CL_VIRUS;
@@@ -459,7 -516,7 +478,7 @@@
  
      if(!ftonly && ctx->engine->md5_hdb) {
  	cli_md5_final(digest, &md5ctx);
- 	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, NULL) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, NULL) != CL_VIRUS))
 -	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, -1, NULL) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS))
++	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, NULL, NULL) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS))
  	    return CL_VIRUS;
      }
  
diff --combined libclamav/matcher.h
index 4e831c9,79c686f..863a781
--- a/libclamav/matcher.h
+++ b/libclamav/matcher.h
@@@ -33,7 -33,7 +33,7 @@@
  #include "matcher-ac.h"
  #include "matcher-bm.h"
  #include "hashtab.h"
 -
 +#include "fmap.h"
  #include "mpool.h"
  
  #define CLI_MATCH_WILDCARD	0xff00
@@@ -73,10 -73,10 +73,10 @@@ struct cli_matcher 
  
      /* Extended Boyer-Moore */
      uint8_t *bm_shift;
-     struct cli_bm_patt **bm_suffix;
+     struct cli_bm_patt **bm_suffix, **bm_pattab;
      struct cli_hashset md5_sizes_hs;
      uint32_t *soff, soff_len; /* for PE section sigs */
-     uint32_t bm_patterns, bm_reloff_num, bm_absoff_num;
+     uint32_t bm_offmode, bm_patterns, bm_reloff_num, bm_absoff_num;
  
      /* Extended Aho-Corasick */
      uint32_t ac_partsigs, ac_nodes, ac_patterns, ac_lsigs;
@@@ -140,9 -140,8 +140,9 @@@ 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_fmap_scandesc(cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode);
  
 -int cli_caloff(const char *offstr, struct cli_target_info *info, int fd, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max);
 +int cli_caloff(const char *offstr, struct cli_target_info *info, struct F_MAP *map, unsigned int target, uint32_t *offdata, uint32_t *offset_min, uint32_t *offset_max);
  
  int cli_checkfp(int fd, cli_ctx *ctx);
  
diff --combined libclamav/pe.c
index a85c4dd,9b80936..e9d4c4e
--- a/libclamav/pe.c
+++ b/libclamav/pe.c
@@@ -290,7 -290,7 +290,7 @@@ static off_t cli_seeksect(int fd, struc
      return ret+1;
  }
  
 -static unsigned int cli_md5sect(int fd, struct cli_exe_section *s, unsigned char *digest) {
 +static unsigned int cli_md5sect(struct F_MAP *map, struct cli_exe_section *s, unsigned char *digest) {
      void *hashme;
      cli_md5_ctx md5;
  
@@@ -299,21 -299,28 +299,21 @@@
  	return 0;
      }
  
 -    if(!cli_seeksect(fd, s)) return 0;
 -
 -    if(!(hashme=cli_malloc(s->rsz))) {
 -	cli_dbgmsg("cli_md5sect: out of memory\n");
 -	return 0;
 -    }
 -
 -    if(cli_readn(fd, hashme, s->rsz)!=s->rsz) {
 +    if(!s->rsz) return 0;
 +    if(!(hashme=fmap_need_off_once(map, s->raw, s->rsz))) {
  	cli_dbgmsg("cli_md5sect: unable to read section data\n");
  	return 0;
      }
  
      cli_md5_init(&md5);
      cli_md5_update(&md5, hashme, s->rsz);
 -    free(hashme);
      cli_md5_final(digest, &md5);
      return 1;
  }
  
 -static void cli_parseres_special(uint32_t base, uint32_t rva, int srcfd, struct cli_exe_section *exe_sections, uint16_t nsections, size_t fsize, uint32_t hdr_size, unsigned int level, uint32_t type, unsigned int *maxres, struct swizz_stats *stats) {
 +static void cli_parseres_special(uint32_t base, uint32_t rva, struct F_MAP *map, struct cli_exe_section *exe_sections, uint16_t nsections, size_t fsize, uint32_t hdr_size, unsigned int level, uint32_t type, unsigned int *maxres, struct swizz_stats *stats) {
      unsigned int err = 0, i;
 -    uint8_t resdir[16];
 +    uint8_t *resdir;
      uint8_t *entry, *oentry;
      uint16_t named, unnamed;
      uint32_t rawaddr = cli_rawaddr(rva, exe_sections, nsections, &err, fsize, hdr_size);
@@@ -321,7 -328,7 +321,7 @@@
  
      if(level>2 || !*maxres) return;
      *maxres-=1;
 -    if(err || (pread(srcfd,resdir, sizeof(resdir), rawaddr) != sizeof(resdir)))
 +    if(err || !(resdir = fmap_need_off_once(map, rawaddr, 16)))
  	    return;
      named = (uint16_t)cli_readint16(resdir+12);
      unnamed = (uint16_t)cli_readint16(resdir+14);
@@@ -329,13 -336,18 +329,13 @@@
      entries = /*named+*/unnamed;
      if (!entries)
  	    return;
 -    oentry = entry = cli_malloc(entries*8);
      rawaddr += named*8; /* skip named */
      /* this is just used in a heuristic detection, so don't give error on failure */
 -    if (!entry) {
 -	    cli_dbgmsg("cli_parseres_special: failed to allocate memory for resource directory:%lu\n", (unsigned long)entries);
 -	    return;
 -    }
 -    if (pread(srcfd, entry, entries*8, rawaddr+16) != entries*8) {
 +    if(!(entry = fmap_need_off(map, rawaddr+16, entries*8))) {
  	    cli_dbgmsg("cli_parseres_special: failed to read resource directory at:%lu\n", (unsigned long)rawaddr+16);
 -	    free(oentry);
  	    return;
      }
 +    oentry = entry;
      /*for (i=0; i<named; i++) {
  	uint32_t id, offs;
  	id = cli_readint32(entry);
@@@ -377,13 -389,13 +377,13 @@@
  	}
  	offs = cli_readint32(entry+4);
  	if(offs>>31)
 -		cli_parseres_special(base, base + (offs&0x7fffffff), srcfd, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
 +		cli_parseres_special(base, base + (offs&0x7fffffff), map, exe_sections, nsections, fsize, hdr_size, level+1, type, maxres, stats);
  	else {
  			offs = cli_readint32(entry+4);
  			rawaddr = cli_rawaddr(base + offs, exe_sections, nsections, &err, fsize, hdr_size);
 -			if (!err && pread(srcfd, resdir, sizeof(resdir), rawaddr) == sizeof(resdir)) {
 +			if (!err && (resdir = fmap_need_off_once(map, rawaddr, 16))) {
  				uint32_t isz = cli_readint32(resdir+4);
 -				char *str;
 +				uint8_t *str;
  				rawaddr = cli_rawaddr(cli_readint32(resdir), exe_sections, nsections, &err, fsize, hdr_size);
  				if (err || !isz || isz >= fsize || rawaddr+isz >= fsize) {
  					cli_dbgmsg("cli_parseres_special: invalid resource table entry: %lu + %lu\n", 
@@@ -392,15 -404,22 +392,15 @@@
  					stats->errors++;
  					continue;
  				}
 -				str = cli_malloc(isz);
 -				if (!str) {
 -					cli_dbgmsg("cli_parseres_special: failed to allocate string mem: %lu\n", (unsigned long)isz);
 -					continue;
 -				}
 -				if(pread(srcfd, str, isz, rawaddr) == isz) {
 +				if((str = fmap_need_off_once(map, rawaddr, isz)))
  					cli_detect_swizz_str(str, isz, stats, type);
  			}
  	}
      }
 -    free (oentry);
 +    fmap_unneed_ptr(map, oentry, entries*8);
  }
  
 -int cli_scanpe(int desc, cli_ctx *ctx)
 +int cli_scanpe(cli_ctx *ctx)
  {
  	uint16_t e_magic; /* DOS signature ("MZ") */
  	uint16_t nsections;
@@@ -414,9 -433,10 +414,9 @@@
  	    struct pe_image_optional_hdr32 opt32;
  	} pe_opt;
  	struct pe_image_section_hdr *section_hdr;
 -	struct stat sb;
 -	char sname[9], buff[4096], epbuff[4096], *tempfile;
 +	char sname[9], epbuff[4096], *tempfile;
  	uint32_t epsize;
 -	ssize_t bytes;
 +	ssize_t bytes, at;
  	unsigned int i, found, upx_success = 0, min = 0, max = 0, err, overlays = 0;
  	unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0;
  	int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
@@@ -428,7 -448,6 +428,7 @@@
  	struct cli_matcher *md5_sect;
  	char timestr[32];
  	struct pe_image_data_dir *dirs;
 +	struct F_MAP *map;
  
  
      if(!ctx) {
@@@ -436,8 -455,7 +436,8 @@@
  	return CL_ENULLARG;
      }
  
 -    if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
 +    map = *ctx->fmap;
 +    if(fmap_readn(map, &e_magic, 0, sizeof(e_magic)) != sizeof(e_magic)) {
  	cli_dbgmsg("Can't read DOS signature\n");
  	return CL_CLEAN;
      }
@@@ -447,13 -465,15 +447,13 @@@
  	return CL_CLEAN;
      }
  
 -    lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
 -
 -    if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
 +    if(fmap_readn(map, &e_lfanew, 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
  	cli_dbgmsg("Can't read new header address\n");
  	/* truncated header? */
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
@@@ -465,7 -485,13 +465,7 @@@
  	return CL_CLEAN;
      }
  
 -    if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
 -	/* probably not a PE file */
 -	cli_dbgmsg("Can't lseek to e_lfanew\n");
 -	return CL_CLEAN;
 -    }
 -
 -    if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
 +    if(fmap_readn(map, &file_hdr, e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
  	/* bad information in e_lfanew - probably not a PE file */
  	cli_dbgmsg("Can't read file header\n");
  	return CL_CLEAN;
@@@ -583,7 -609,7 +583,7 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	}
  	if(nsections)
  	    cli_warnmsg("PE file contains %d sections\n", nsections);
@@@ -603,22 -629,20 +603,22 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  	        *ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
  
 -    if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
 +    at = e_lfanew + sizeof(struct pe_image_file_hdr);
 +    if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
          cli_dbgmsg("Can't read optional file header\n");
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  	        *ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
 +    at += sizeof(struct pe_image_optional_hdr32);
  
      /* This will be a chicken and egg problem until we drop 9x */
      if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) {
@@@ -628,7 -652,7 +628,7 @@@
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	    return CL_CLEAN;
  	}
@@@ -644,7 -668,7 +644,7 @@@
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	    cli_dbgmsg("9x compatibility mode\n");
  	}
@@@ -653,7 -677,7 +653,7 @@@
      if(!pe_plus) { /* PE */
  	if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
  	    /* Seek to the end of the long header */
 -	    lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
 +	    at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
  	}
  
  	if(DCONF & PE_CONF_UPACK)
@@@ -681,16 -705,16 +681,16 @@@
  
      } else { /* PE+ */
          /* read the remaining part of the header */
 -        if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
 +        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)) {
  	    cli_dbgmsg("Can't read optional file header\n");
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	    return CL_CLEAN;
  	}
 -
 +	at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
  	vep = EC32(optional_hdr64.AddressOfEntryPoint);
  	hdr_size = EC32(optional_hdr64.SizeOfHeaders);
  	cli_dbgmsg("File format: PE32+\n");
@@@ -767,17 -791,22 +767,17 @@@
          cli_dbgmsg("Bad virtual alignemnt\n");
          if(ctx->virname)
  	    *ctx->virname = "Broken.Executable";
 -	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
      }
  
      if (DETECT_BROKEN && !native && (!(pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment)) || (pe_plus?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment))%0x200)) {
          cli_dbgmsg("Bad file alignemnt\n");
  	if(ctx->virname)
  	    *ctx->virname = "Broken.Executable";
 -	return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 -    }
 -
 -    if(fstat(desc, &sb) == -1) {
 -	cli_dbgmsg("fstat failed\n");
 -	return CL_ESTAT;
 +	return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
      }
  
 -    fsize = sb.st_size;
 +    fsize = map->len;
  
      section_hdr = (struct pe_image_section_hdr *) cli_calloc(nsections, sizeof(struct pe_image_section_hdr));
  
@@@ -797,7 -826,7 +797,7 @@@
      valign = (pe_plus)?EC32(optional_hdr64.SectionAlignment):EC32(optional_hdr32.SectionAlignment);
      falign = (pe_plus)?EC32(optional_hdr64.FileAlignment):EC32(optional_hdr32.FileAlignment);
  
 -    if(cli_readn(desc, section_hdr, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
 +    if(fmap_readn(map, section_hdr, at, sizeof(struct pe_image_section_hdr)*nsections) != (int)(nsections*sizeof(struct pe_image_section_hdr))) {
          cli_dbgmsg("Can't read section header\n");
  	cli_dbgmsg("Possibly broken PE file\n");
  	free(section_hdr);
@@@ -805,12 -834,11 +805,12 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
 -    
 +    at += sizeof(struct pe_image_section_hdr)*nsections;
 +
      for(i = 0; falign!=0x200 && i<nsections; i++) {
  	/* file alignment fallback mode - blah */
  	if (falign && section_hdr[i].SizeOfRawData && EC32(section_hdr[i].PointerToRawData)%falign && !(EC32(section_hdr[i].PointerToRawData)%0x200)) {
@@@ -875,7 -903,7 +875,7 @@@
  	        *ctx->virname = "Broken.Executable";
  	    free(section_hdr);
  	    free(exe_sections);
 -	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	}
  
  	if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */
@@@ -886,7 -914,7 +886,7 @@@
  		if(DETECT_BROKEN) {
  		    if(ctx->virname)
  		        *ctx->virname = "Broken.Executable";
 -		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  		}
  		return CL_CLEAN; /* no ninjas to see here! move along! */
  	    }
@@@ -900,12 -928,12 +900,11 @@@
  		for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) {
  		    if(md5_sect->soff[j] == exe_sections[i].rsz) {
  			unsigned char md5_dig[16];
- 			if(cli_md5sect(map, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, NULL) == CL_VIRUS) {
- 			    if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, NULL) != CL_VIRUS) {
- 
 -			if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, -1, NULL) == CL_VIRUS) {
 -			    if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS) {
 -
++			if(cli_md5sect(map, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_mdb, 0, NULL, NULL) == CL_VIRUS) {
++			    if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS) {
  				free(section_hdr);
  				free(exe_sections);
 -				return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +				return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  			    }
  			}
  			break;
@@@ -921,7 -949,7 +920,7 @@@
  	    if(DETECT_BROKEN) {
  	        if(ctx->virname)
  		    *ctx->virname = "Broken.Executable";
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	    return CL_CLEAN;
  	}
@@@ -933,7 -961,7 +932,7 @@@
  		    *ctx->virname = "Broken.Executable";
  		free(section_hdr);
  		free(exe_sections);
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	    min = exe_sections[i].rva;
  	    max = exe_sections[i].rva + exe_sections[i].rsz;
@@@ -944,7 -972,7 +943,7 @@@
  		    *ctx->virname = "Broken.Executable";
  		free(section_hdr);
  		free(exe_sections);
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	    if(exe_sections[i].rva < min)
  	        min = exe_sections[i].rva;
@@@ -964,7 -992,7 +963,7 @@@
  	if(DETECT_BROKEN) {
  	    if(ctx->virname)
  		*ctx->virname = "Broken.Executable";
 -	    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +	    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	}
  	return CL_CLEAN;
      }
@@@ -976,10 -1004,12 +975,10 @@@
  	return CL_CLEAN;
      }
  
 -    lseek(desc, ep, SEEK_SET);
 -    epsize = cli_readn(desc, epbuff, 4096);
 +    epsize = fmap_readn(map, epbuff, ep, 4096);
  
      CLI_UNPTEMP("DISASM",(exe_sections,0));
      disasmbuf((unsigned char*)epbuff, epsize, ndesc);
 -    lseek(ndesc, 0, SEEK_SET);
      ret = cli_scandesc(ndesc, ctx, CL_TYPE_PE_DISASM, 1, NULL, AC_SCAN_VIR);
      close(ndesc);
      CLI_TMPUNLK();
@@@ -992,7 -1022,7 +991,7 @@@
      if(overlays) {
  	int overlays_sz = fsize - overlays;
  	if(overlays_sz > 0) {
 -	    ret = cli_scanishield(desc, ctx, overlays, overlays_sz);
 +	    ret = cli_scanishield(map->fd, ctx, overlays, overlays_sz);
  	    if(ret != CL_CLEAN) {
  		free(exe_sections);
  		return ret;
@@@ -1010,7 -1040,7 +1009,7 @@@
  	    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)) {
  	        *ctx->virname = "W32.Parite.B";
  		free(exe_sections);
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	}
      }
@@@ -1093,7 -1123,7 +1092,7 @@@
  		if (op==kzdsize+0x48 && *kzcode==0x75 && kzlen-(int8_t)kzcode[1]-3<=kzinitlen && kzlen-(int8_t)kzcode[1]>=kzxorlen) {
  		    *ctx->virname = "W32.Kriz";
  		    free(exe_sections);
 -		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  		}
  		cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n");
  		kzstate++;
@@@ -1114,25 -1144,25 +1113,25 @@@
  
  	if(vsize >= 0x612c && rsize >= 0x612c && ((vsize & 0xff) == 0xec)) {
  		int bw = rsize < 0x7000 ? rsize : 0x7000;
 +		char *tbuff;
  
 -	    lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
 -	    if(cli_readn(desc, buff, 4096) == 4096) {
 -		if(cli_memstr(buff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
 +	    if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
 +		if(cli_memstr(tbuff, 4091, "\xe8\x2c\x61\x00\x00", 5)) {
  		    *ctx->virname = dam ? "W32.Magistr.A.dam" : "W32.Magistr.A";
  		    free(exe_sections);
 -		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  		} 
  	    }
  
  	} else if(rsize >= 0x7000 && vsize >= 0x7000 && ((vsize & 0xff) == 0xed)) {
  		int bw = rsize < 0x8000 ? rsize : 0x8000;
 +		char *tbuff;
  
 -	    lseek(desc, exe_sections[nsections - 1].raw + rsize - bw, SEEK_SET);
 -	    if(cli_readn(desc, buff, 4096) == 4096) {
 -		if(cli_memstr(buff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
 +	    if((tbuff = fmap_need_off_once(map, exe_sections[nsections - 1].raw + rsize - bw, 4096))) {
 +		if(cli_memstr(tbuff, 4091, "\xe8\x04\x72\x00\x00", 5)) {
  		    *ctx->virname = dam ? "W32.Magistr.B.dam" : "W32.Magistr.B";
  		    free(exe_sections);
 -		    return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		    return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  		} 
  	    }
  	}
@@@ -1145,9 -1175,15 +1144,9 @@@
  	unsigned int xsjs = 0;
  
  	if(exe_sections[0].rsz > CLI_MAX_ALLOCATION) break;
 -	if(!cli_seeksect(desc, &exe_sections[0])) break;
 -	if(!(code=cli_malloc(exe_sections[0].rsz))) {
 -	    free(exe_sections);
 -	    return CL_EMEM;
 -	}
 -	if(cli_readn(desc, code, exe_sections[0].rsz)!=exe_sections[0].rsz) {
 -	    free(exe_sections);
 -	    return CL_EREAD;
 -	}
 +
 +	if(!exe_sections[0].rsz) break;
 +	if(!(code=fmap_need_off_once(map, exe_sections[0].raw, exe_sections[0].rsz))) break;
  	for(i=0; i<exe_sections[0].rsz - 5; i++) {
  	    if((uint8_t)(code[i]-0xe8) > 1) continue;
  	    jump = cli_rawaddr(exe_sections[0].rva+i+5+cli_readint32(&code[i+1]), exe_sections, nsections, &err, fsize, hdr_size);
@@@ -1155,6 -1191,7 +1154,6 @@@
  	    if(xsjs % 128 == 0) {
  		if(xsjs == 1280) break;
  		if(!(jumps=(uint32_t *)cli_realloc2(jumps, (xsjs+128)*sizeof(uint32_t)))) {
 -		    free(code);
  		    free(exe_sections);
  		    return CL_EMEM;
  		}
@@@ -1173,15 -1210,17 +1172,15 @@@
  	    jumps[j]=jump;
  	    xsjs++;
  	}
  	if(!xsjs) break;
  	cli_dbgmsg("Polipos: Checking %d xsect jump(s)\n", xsjs);
  	for(i=0;i<xsjs;i++) {
 -	    lseek(desc, jumps[i], SEEK_SET);
 -	    if(cli_readn(desc, buff, 9) != 9) continue;
 -	    if((jump=cli_readint32(buff))==0x60ec8b55 || (buff[4]=='\xec' && ((jump==0x83ec8b55 && buff[6]=='\x60') || (jump==0x81ec8b55 && !buff[7] && !buff[8])))) {
 +	    if(!(code = fmap_need_off_once(map, jumps[i], 9))) continue;
 +	    if((jump=cli_readint32(code))==0x60ec8b55 || (code[4]=='\xec' && ((jump==0x83ec8b55 && code[6]=='\x60') || (jump==0x81ec8b55 && !code[7] && !code[8])))) {
  		*ctx->virname = "W32.Polipos.A";
  		free(jumps);
  		free(exe_sections);
 -		return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +		return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  	    }
  	}
  	free(jumps);
@@@ -1198,7 -1237,7 +1197,7 @@@
  		    if (!stats)
  			    ret = CL_EMEM;
  		    else {
 -			    cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), desc, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
 +			    cli_parseres_special(EC32(dirs[2].VirtualAddress), EC32(dirs[2].VirtualAddress), map, exe_sections, nsections, fsize, hdr_size, 0, 0, &m, stats);
  			    if ((ret = cli_detect_swizz(stats)) == CL_VIRUS) {
  				    *ctx->virname = "Trojan.Swizzor.Gen";
  			    }
@@@ -1207,7 -1246,7 +1206,7 @@@
  		    if (ret != CL_CLEAN) {
  			    free(exe_sections);
  			    if(ret == CL_VIRUS)
 -				return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
 +				return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
  			    return ret;
  		    }
  	    }
@@@ -1230,7 -1269,6 +1229,7 @@@
      /* MEW support */
      if (found && (DCONF & PE_CONF_MEW) && epsize>=16 && epbuff[0]=='\xe9') {
  	uint32_t fileoffset;
 +	char *tbuff;
  
  	fileoffset = (vep + cli_readint32(epbuff + 1) + 5);
  	while (fileoffset == 0x154 || fileoffset == 0x158) {
@@@ -1239,20 -1277,29 +1238,20 @@@
  	    cli_dbgmsg ("MEW: found MEW characteristics %08X + %08X + 5 = %08X\n", 
  			cli_readint32(epbuff + 1), vep, cli_readint32(epbuff + 1) + vep + 5);
  
 -	    if(lseek(desc, fileoffset, SEEK_SET) == -1) {
 -	        cli_dbgmsg("MEW: lseek() failed\n");
 -		free(exe_sections);
 -		return CL_ESEEK;
 -	    }
 -
 -	    if((bytes = read(desc, buff, 0xb0)) != 0xb0) {
 -	        cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %lu\n", fileoffset, fileoffset, (unsigned long)bytes);
 +	    if(!(tbuff = fmap_need_off_once(map, fileoffset, 0xb0)))
  		break;
  	    if (fileoffset == 0x154) cli_dbgmsg("MEW: Win9x compatibility was set!\n");
  	    else cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n");
  
 -	    if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) {
 +	    if((offdiff = cli_readint32(tbuff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) {
  	        cli_dbgmsg("MEW: ESI is not in proper section\n");
  		break;
  	    }
  	    offdiff -= exe_sections[i + 1].rva;
  
 -	    if(!cli_seeksect(desc, &exe_sections[i + 1])) {
 -		free(exe_sections);
 -		return CL_ESEEK;
 +	    if(!exe_sections[i + 1].rsz) {
 +		cli_dbgmsg("MEW: mew section is empty\n");
 +		break;
  	    }
  	    ssize = exe_sections[i + 1].vsz;
  	    dsize = exe_sections[i].vsz;
@@@ -1262,19 -1309,20 +1261,19 @@@
  	    CLI_UNPSIZELIMITS("MEW", MAX(ssize, dsize));
  	    CLI_UNPSIZELIMITS("MEW", MAX(ssize + dsize, exe_sections[i + 1].rsz));
  
 +	    if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
 +	        cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
 +		break;
 +	    }
 +
  	    /* allocate needed buffer */
  	    if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
  	        free(exe_sections);
  		return CL_EMEM;
  	    }
  
 -	    if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
 -	        cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
 -		free(src);
 -		break;
 -	    }
 -
 -	    if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
 -	      cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
 +	    if((bytes = fmap_readn(map, src + dsize, exe_sections[i + 1].raw, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
 +		cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
  		free(exe_sections);
  		free(src);
  		return CL_EREAD;
@@@ -1282,13 -1330,13 +1281,13 @@@
  	    cli_dbgmsg("MEW: %u (%08x) bytes read\n", (unsigned int)bytes, (unsigned int)bytes);
  
  	    /* count offset to lzma proc, if lzma used, 0xe8 -> call */
 -	    if (buff[0x7b] == '\xe8') {
 -	        if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4)) {
 +	    if (tbuff[0x7b] == '\xe8') {
 +	        if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(tbuff + 0x7c) + fileoffset + 0x80, 4)) {
  		    cli_dbgmsg("MEW: lzma proc out of bounds!\n");
  		    free(src);
  		    break; /* to next unpacker in chain */
  		}
 -		uselzma = cli_readint32(buff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
 +		uselzma = cli_readint32(tbuff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
  	    } else {
  	        uselzma = 0;
  	    }
@@@ -1385,7 -1433,8 +1384,7 @@@
  		return CL_EMEM;
  	    }
  
 -	    lseek(desc, 0, SEEK_SET);
 -	    if(read(desc, dest, ssize) != ssize) {
 +	    if(fmap_readn(map, dest, 0, ssize) != ssize) {
  	        cli_dbgmsg("Upack: Can't read raw data of section 0\n");
  		free(dest);
  		break;
@@@ -1393,7 -1442,9 +1392,7 @@@
  
  	    if(upack) memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize);
  
 -	    lseek(desc, exe_sections[1].uraw, SEEK_SET);
 -
 -	    if(read(desc, dest + exe_sections[1].rva - off, exe_sections[1].ursz) != exe_sections[1].ursz) {
 +	    if(fmap_readn(map, dest + exe_sections[1].rva - off, exe_sections[1].uraw, exe_sections[1].ursz) != exe_sections[1].ursz) {
  		cli_dbgmsg("Upack: Can't read raw data of section 1\n");
  		free(dest);
  		break;
@@@ -1434,27 -1485,31 +1433,27 @@@
  	    return CL_EMEM;
  	}
  
 -	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
 +	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
  	    cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
  	    free(exe_sections);
 -	    free(src);
  	    return CL_ESEEK;
  	}
  
  	dest = src + newedx - exe_sections[i + 1].rva;
  	if(newedx < exe_sections[i + 1].rva || !CLI_ISCONTAINED(src, ssize, dest, 4)) {
  	    cli_dbgmsg("FSG: New ESP out of bounds\n");
 -	    free(src);
  	    break;
  	}
  
  	newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase);
  	if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
  	    cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx);
 -	    free(src);
  	    break;
  	}
   
  	dest = src + newedx - exe_sections[i + 1].rva;
  	if(!CLI_ISCONTAINED(src, ssize, dest, 32)) {
  	    cli_dbgmsg("FSG: New stack out of bounds\n");
 -	    free(src);
  	    break;
  	}
  
@@@ -1465,16 -1520,19 +1464,16 @@@
  
  	if(newedi != exe_sections[i].rva) {
  	    cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, exe_sections[i].rva);
 -	    free(src);
  	    break;
  	}
  
  	if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
  	    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
 -	    free(src);
  	    break;
  	}
  
  	if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newebx, 16)) {
  	    cli_dbgmsg("FSG: Array of functions out of bounds\n");
 -	    free(src);
  	    break;
  	}
  
@@@ -1487,8 -1545,8 +1486,8 @@@
  	    return CL_EMEM;
  	}
  
 -	CLI_UNPTEMP("FSG",(src,dest,exe_sections,0));
 -	CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,(src,dest,0));
 +	CLI_UNPTEMP("FSG",(dest,exe_sections,0));
 +	CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,(dest,0));
  	break;
      }
  
@@@ -1513,18 -1571,25 +1512,18 @@@
  	    return CL_CLEAN;
  	}
  
 -	if(!(gp = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
 +	if(!(t = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
  	    cli_dbgmsg("FSG: Support data out of padding area\n");
  	    break;
  	}
  
 -	lseek(desc, gp, SEEK_SET);
 -	gp = exe_sections[i + 1].raw - gp;
 -
 -	CLI_UNPSIZELIMITS("FSG", gp)
 +	gp = exe_sections[i + 1].raw - t;
  
 -	if((support = (char *) cli_malloc(gp)) == NULL) {
 -	    free(exe_sections);
 -	    return CL_EMEM;
 -	}
 +	CLI_UNPSIZELIMITS("FSG", gp);
  
 -	if((int)cli_readn(desc, support, gp) != (int)gp) {
 +	if(!(support = fmap_need_off_once(map, t, gp))) {
  	    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
  	    free(exe_sections);
 -	    free(support);
  	    return CL_EREAD;
  	}
  
@@@ -1534,11 -1599,13 +1533,11 @@@
  
  	if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
  	    cli_dbgmsg("FSG: Source buffer out of section bounds\n");
 -	    free(support);
  	    break;
  	}
  
  	if(newedi != exe_sections[i].rva) {
  	    cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva);
 -	    free(support);
  	    break;
  	}
  
@@@ -1561,11 -1628,13 +1560,11 @@@
  	}
  
  	if(t >= gp - 4 || cli_readint32(support + t)) {
 -	    free(support);
  	    break;
  	}
  
  	if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
  	    free(exe_sections);
 -	    free(support);
  	    return CL_EMEM;
  	}
  
@@@ -1573,15 -1642,25 +1572,15 @@@
  	for(t = 1; t <= (uint32_t)sectcnt; t++)
  	    sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 - EC32(optional_hdr32.ImageBase);
  
 -	free(support);
 -
 -	if((src = (char *) cli_malloc(ssize)) == NULL) {
 -	    free(exe_sections);
 -	    free(sections);
 -	    return CL_EMEM;
 -	}
 -
 -	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
 +	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
  	    cli_dbgmsg("Can't read raw data of section %d\n", i);
  	    free(exe_sections);
  	    free(sections);
 -	    free(src);
  	    return CL_EREAD;
  	}
  
  	if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
  	    free(exe_sections);
 -	    free(src);
  	    free(sections);
  	    return CL_EMEM;
  	}
@@@ -1589,8 -1668,8 +1588,8 @@@
  	oldep = vep + 161 + 6 + cli_readint32(epbuff+163);
  	cli_dbgmsg("FSG: found old EP @%x\n", oldep);
  
 -	CLI_UNPTEMP("FSG",(src,dest,sections,exe_sections,0));
 -	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(src,dest,sections,0));
 +	CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
 +	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
  	break; /* were done with 1.33 */
      }
  
@@@ -1600,7 -1679,8 +1599,7 @@@
  	/* FSG support - v. 1.31 */
  
  	int sectcnt = 0;
 -	uint32_t t;
 -	uint32_t gp = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size);
 +	uint32_t gp, t = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size);
  	char *support;
  	uint32_t newesi = cli_readint32(epbuff+11) - EC32(optional_hdr32.ImageBase);
  	uint32_t newedi = cli_readint32(epbuff+6) - EC32(optional_hdr32.ImageBase);
@@@ -1610,6 -1690,7 +1609,6 @@@
  	ssize = exe_sections[i + 1].rsz;
  	dsize = exe_sections[i].vsz;
  
 -
  	if(err) {
  	    cli_dbgmsg("FSG: Support data out of padding area\n");
  	    break;
@@@ -1633,13 -1714,20 +1632,13 @@@
  	    return CL_CLEAN;
  	}
  
 -	lseek(desc, gp, SEEK_SET);
 -	gp = exe_sections[i + 1].raw - gp;
 +	gp = exe_sections[i + 1].raw - t;
  
  	CLI_UNPSIZELIMITS("FSG", gp)
  
 -	if((support = (char *) cli_malloc(gp)) == NULL) {
 -	    free(exe_sections);
 -	    return CL_EMEM;
 -	}
 -
 -	if(cli_readn(desc, support, gp) != (int)gp) {
 +	if(!(support = fmap_need_off_once(map, t, gp))) {
  	    cli_dbgmsg("Can't read %d bytes from padding area\n", gp); 
  	    free(exe_sections);
 -	    free(support);
  	    return CL_EREAD;
  	}
  
@@@ -1660,11 -1748,13 +1659,11 @@@
  	}
  
  	if(t >= gp-10 || cli_readint32(support + t + 6) != 2) {
 -	    free(support);
  	    break;
  	}
  
  	if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) {
  	    free(exe_sections);
 -	    free(support);
  	    return CL_EMEM;
  	}
  
@@@ -1673,21 -1763,25 +1672,21 @@@
  	    sections[t+1].rva = (((support[t*2]|(support[t*2+1]<<8))-2)<<12)-EC32(optional_hdr32.ImageBase);
  	}
  
 -	free(support);
 -
  	if((src = (char *) cli_malloc(ssize)) == NULL) {
  	    free(exe_sections);
  	    free(sections);
  	    return CL_EMEM;
  	}
  
 -	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
 +	if(!exe_sections[i + 1].rsz || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
  	    cli_dbgmsg("FSG: Can't read raw data of section %d\n", i);
  	    free(exe_sections);
  	    free(sections);
 -	    free(src);
  	    return CL_EREAD;
  	}
  
  	if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
  	    free(exe_sections);
 -	    free(src);
  	    free(sections);
  	    return CL_EMEM;
  	}
@@@ -1696,8 -1790,8 +1695,8 @@@
  	oldep = vep + gp + 6 + cli_readint32(src+gp+2+oldep);
  	cli_dbgmsg("FSG: found old EP @%x\n", oldep);
  
 -	CLI_UNPTEMP("FSG",(src,dest,sections,exe_sections,0));
 -	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(src,dest,sections,0));
 +	CLI_UNPTEMP("FSG",(dest,sections,exe_sections,0));
 +	CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,(dest,sections,0));
  	break; /* were done with 1.31 */
      }
  
@@@ -1718,17 -1812,25 +1717,17 @@@
  	    return CL_CLEAN;
  	}
  
 -	if((src = (char *) cli_malloc(ssize)) == NULL) {
 +	if(!exe_sections[i + 1].raw || !(src = fmap_need_off_once(map, exe_sections[i + 1].raw, ssize))) {
 +	    cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1);
  	    free(exe_sections);
 -	    return CL_EMEM;
 +	    return CL_EREAD;
  	}
  
  	if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) {
  	    free(exe_sections);
  	    return CL_EMEM;
  	}
  
 -	if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
 -	    cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1);
 -	    free(exe_sections);
 -	    free(src);
 -	    free(dest);
 -	    return CL_EREAD;
 -	}
 -
  	/* try to detect UPX code */
  	if(cli_memstr(UPX_NRV2B, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, epbuff + 0x69 + 8, 13)) {
  	    cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n");
@@@ -1802,11 -1904,13 +1801,11 @@@
  
  	if(!upx_success) {
  	    cli_dbgmsg("UPX: All decompressors failed\n");
 -	    free(src);
  	    free(dest);
  	}
      }
  
      if(upx_success) {
 -	free(src);
  	free(exe_sections);
  
  	CLI_UNPTEMP("UPX/FSG",(dest,0));
@@@ -1874,7 -1978,7 +1873,7 @@@
  
  	    for(i = 0 ; i < nsections; i++) {
  		if(exe_sections[i].raw) {
 -		    if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + exe_sections[i].rva - min, exe_sections[i].ursz) != exe_sections[i].ursz) {
 +		    if(!exe_sections[i].rsz || fmap_readn(map, dest + exe_sections[i].rva - min, exe_sections[i].raw, exe_sections[i].ursz) != exe_sections[i].ursz) {
  			free(exe_sections);
  			free(dest);
  			return CL_CLEAN;
@@@ -1903,7 -2007,8 +1902,7 @@@
  	    return CL_EMEM;
  	}
  
 -	lseek(desc, 0, SEEK_SET);
 -	if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
 +	if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
  	    cli_dbgmsg("PESpin: Can't read %lu bytes\n", (unsigned long)fsize);
  	    free(spinned);
  	    free(exe_sections);
@@@ -1967,7 -2072,8 +1966,7 @@@
  	    return CL_EMEM;
  	}
  
 -	lseek(desc, 0, SEEK_SET);
 -	if((size_t) cli_readn(desc, spinned, fsize) != fsize) {
 +	if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) {
  	    cli_dbgmsg("yC: Can't read %lu bytes\n", (unsigned long)fsize);
  	    free(spinned);
  	    free(exe_sections);
@@@ -2004,7 -2110,8 +2003,7 @@@
  	    free(exe_sections);
  	    return CL_EMEM;
  	}
 -	lseek(desc, 0, SEEK_SET);
 -	if((size_t) cli_readn(desc, src, head) != head) {
 +	if((size_t) fmap_readn(map, src, 0, head) != head) {
  	    cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", head);
  	    free(src);
  	    free(exe_sections);
@@@ -2012,8 -2119,9 +2011,8 @@@
  	}
          for(i = 0 ; i < (unsigned int)nsections-1; i++) {
  	    if(!exe_sections[i].rsz) continue;
 -	    if(!cli_seeksect(desc, &exe_sections[i])) break;
              if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
 -            if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
 +            if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
          }
          if(i+1!=nsections) {
              cli_dbgmsg("WWpack: Probably hacked/damaged file.\n");
@@@ -2025,7 -2133,7 +2024,7 @@@
  	    free(exe_sections);
  	    return CL_EMEM;
  	}
 -	if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, packer, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
 +	if(!exe_sections[nsections - 1].rsz || (size_t) fmap_readn(map, packer, exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) {
  	    cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz);
  	    free(src);
  	    free(packer);
@@@ -2057,8 -2165,9 +2056,8 @@@
  	}
          for(i = 0 ; i < (unsigned int)nsections; i++) {
  	    if(!exe_sections[i].rsz) continue;
 -	    if(!cli_seeksect(desc, &exe_sections[i])) break;
              if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break;
 -            if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
 +            if(fmap_readn(map, src+exe_sections[i].rva, exe_sections[i].raw, exe_sections[i].rsz)!=exe_sections[i].rsz) break;
          }
          if(i!=nsections) {
              cli_dbgmsg("Aspack: Probably hacked/damaged Aspack file.\n");
@@@ -2077,13 -2186,14 +2076,13 @@@
  	uint32_t eprva = vep;
  	uint32_t start_of_stuff, ssize, dsize, rep = ep;
  	unsigned int nowinldr;
 -	char nbuff[24];
 +	char *nbuff;
  	char *src=epbuff, *dest;
  
  	if (*epbuff=='\xe9') { /* bitched headers */
  	    eprva = cli_readint32(epbuff+1)+vep+5;
  	    if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) break;
 -	    if (lseek(desc, rep, SEEK_SET)==-1) break;
 -	    if (cli_readn(desc, nbuff, 24)!=24) break;
 +	    if (!(nbuff = fmap_need_off_once(map, rep, 24))) break;
  	    src = nbuff;
  	}
  
@@@ -2092,9 -2202,11 +2091,9 @@@
  	nowinldr = 0x54-cli_readint32(src+17);
  	cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr);
  
 -	if (lseek(desc, rep-nowinldr, SEEK_SET)==-1) break;
 -	if (cli_readn(desc, nbuff, 4)!=4) break;
 +	if(!(nbuff = fmap_need_off_once(map, rep-nowinldr, 4))) break;
  	start_of_stuff=rep+cli_readint32(nbuff);
 -	if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
 -	if (cli_readn(desc, nbuff, 20)!=20) break;
 +	if(!(nbuff = fmap_need_off_once(map, start_of_stuff, 20))) break;
  	src = nbuff;
  	if (!cli_readint32(nbuff)) {
  	    start_of_stuff+=4; /* FIXME: more to do */
@@@ -2106,31 -2218,39 +2105,31 @@@
  
  	CLI_UNPSIZELIMITS("NsPack", MAX(ssize,dsize));
  
 -	if ( !ssize || !dsize || dsize != exe_sections[0].vsz) break;
 -	if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break;
 +	if (!ssize || !dsize || dsize != exe_sections[0].vsz) break;
  	if (!(dest=cli_malloc(dsize))) break;
  	/* memset(dest, 0xfc, dsize); */
  
 -	if (!(src=cli_malloc(ssize))) {
 +	if(!(src = fmap_need_off(map, start_of_stuff, ssize))) {
  	    free(dest);
  	    break;
  	}
  	/* memset(src, 0x00, ssize); */
 -	cli_readn(desc, src, ssize);
  
  	eprva+=0x27a;
  	if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) {
  	  free(dest);
 -	  free(src);
  	  break;
  	}
 -	if (lseek(desc, rep, SEEK_SET)==-1) {
 +	if(!(nbuff = fmap_need_off_once(map, rep, 5))) {
  	  free(dest);
 -	  free(src);
 -	  break;
 -	}
 -	if (cli_readn(desc, nbuff, 5)!=5) {
 -	  free(dest);
 -	  free(src);
  	  break;
  	}
 +	fmap_unneed_off(map, start_of_stuff, ssize);
  	eprva=eprva+5+cli_readint32(nbuff+1);
  	cli_dbgmsg("NsPack: OEP = %08x\n", eprva);
  
 -	CLI_UNPTEMP("NsPack",(src,dest,exe_sections,0));
 -	CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,(src,dest,0));
 +	CLI_UNPTEMP("NsPack",(dest,exe_sections,0));
 +	CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,(dest,0));
  	break;
      }
  
@@@ -2140,7 -2260,7 +2139,7 @@@
      return CL_CLEAN;
  }
  
 -int cli_peheader(int desc, struct cli_exe_info *peinfo)
 +int cli_peheader(struct F_MAP *map, struct cli_exe_info *peinfo)
  {
  	uint16_t e_magic; /* DOS signature ("MZ") */
  	uint32_t e_lfanew; /* address of new exe header */
@@@ -2153,18 -2273,24 +2152,18 @@@
  	    struct pe_image_optional_hdr32 opt32;
  	} pe_opt;
  	struct pe_image_section_hdr *section_hdr;
 -	struct stat sb;
  	int i;
  	unsigned int err, pe_plus = 0;
  	uint32_t valign, falign, hdr_size;
  	size_t fsize;
 +	ssize_t at;
  
      cli_dbgmsg("in cli_peheader\n");
  
 -    if(fstat(desc, &sb) == -1) {
 -	cli_dbgmsg("fstat failed\n");
 -	return -1;
 -    }
 -
 -    fsize = sb.st_size - peinfo->offset;
 -
 -    if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
 +    fsize = map->len - peinfo->offset;
 +    if(fmap_readn(map, &e_magic, peinfo->offset, sizeof(e_magic)) != sizeof(e_magic)) {
  	cli_dbgmsg("Can't read DOS signature\n");
 -	return -1;
 +	return CL_CLEAN;
      }
  
      if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
@@@ -2172,7 -2298,10 +2171,7 @@@
  	return -1;
      }
  
 -    lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
 -
 -    if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
 -	cli_dbgmsg("Can't read new header address\n");
 +    if(fmap_readn(map, &e_lfanew, peinfo->offset + 58 + sizeof(e_magic), sizeof(e_lfanew)) != sizeof(e_lfanew)) {
  	/* truncated header? */
  	return -1;
      }
@@@ -2183,7 -2312,13 +2182,7 @@@
  	return -1;
      }
  
 -    if(lseek(desc, peinfo->offset + e_lfanew, SEEK_SET) < 0) {
 -	/* probably not a PE file */
 -	cli_dbgmsg("Can't lseek to e_lfanew\n");
 -	return -1;
 -    }
 -
 -    if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
 +    if(fmap_readn(map, &file_hdr, peinfo->offset + e_lfanew, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
  	/* bad information in e_lfanew - probably not a PE file */
  	cli_dbgmsg("Can't read file header\n");
  	return -1;
@@@ -2201,29 -2336,26 +2200,29 @@@
  	return -1;
      }
  
 -    if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
 +    at = peinfo->offset + e_lfanew + sizeof(struct pe_image_file_hdr);
 +    if(fmap_readn(map, &optional_hdr32, at, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
          cli_dbgmsg("Can't read optional file header\n");
  	return -1;
      }
 +    at += sizeof(struct pe_image_optional_hdr32);
  
      if(EC16(optional_hdr64.Magic)==PE32P_SIGNATURE) { /* PE+ */
          if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) {
  	    cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n");
  	    return -1;
  	}
 -        if(cli_readn(desc, &optional_hdr32 + 1, sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32)) {
 +	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)) {
  	    cli_dbgmsg("Can't read optional file header\n");
  	    return -1;
  	}
 +	at += sizeof(struct pe_image_optional_hdr64) - sizeof(struct pe_image_optional_hdr32);
  	hdr_size = EC32(optional_hdr64.SizeOfHeaders);
  	pe_plus=1;
      } else { /* PE */
  	if (EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr32)) {
  	    /* Seek to the end of the long header */
 -	    lseek(desc, (EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32)), SEEK_CUR);
 +	    at += EC16(file_hdr.SizeOfOptionalHeader)-sizeof(struct pe_image_optional_hdr32);
  	}
  	hdr_size = EC32(optional_hdr32.SizeOfHeaders);
      }
@@@ -2249,7 -2381,7 +2248,7 @@@
  	return -1;
      }
  
 -    if(cli_readn(desc, section_hdr, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) {
 +    if(fmap_readn(map, section_hdr, at, peinfo->nsections * sizeof(struct pe_image_section_hdr)) != peinfo->nsections * sizeof(struct pe_image_section_hdr)) {
          cli_dbgmsg("Can't read section header\n");
  	cli_dbgmsg("Possibly broken PE file\n");
  	free(section_hdr);
@@@ -2257,7 -2389,6 +2256,7 @@@
  	peinfo->section = NULL;
  	return -1;
      }
 +    at += sizeof(struct pe_image_section_hdr)*peinfo->nsections;
  
      for(i = 0; falign!=0x200 && i<peinfo->nsections; i++) {
  	/* file alignment fallback mode - blah */
diff --combined libclamav/phishcheck.c
index f456b1d,987716e..5bb0ddb
--- a/libclamav/phishcheck.c
+++ b/libclamav/phishcheck.c
@@@ -1198,13 -1198,13 +1198,13 @@@ static int hash_match(const struct rege
  	    h[64]='\0';
  	    cli_dbgmsg("Looking up hash %s for %s(%u)%s(%u)\n", h, host, (unsigned)hlen, path, (unsigned)plen);
  	    if (prefix_matched) {
- 		if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,NULL) == CL_VIRUS) {
 -		if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,-1,NULL) == CL_VIRUS) {
++		if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,NULL,NULL) == CL_VIRUS) {
  		    cli_dbgmsg("prefix matched\n");
  		    *prefix_matched = 1;
  		} else
  		    return CL_SUCCESS;
  	    }
- 	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,NULL) == CL_VIRUS) {
 -	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
++	    if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
  		cli_dbgmsg("This hash matched: %s\n", h);
  		switch(*virname) {
  		    case 'W':
diff --combined libclamav/regex_list.c
index 5ae5a02,db47d67..df19a53
--- a/libclamav/regex_list.c
+++ b/libclamav/regex_list.c
@@@ -455,7 -455,7 +455,7 @@@ static int add_hash(struct regex_matche
  
  	if (fl != 'W' && pat->length == 32 &&
  	    cli_hashset_contains(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)) &&
- 	    cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,NULL) == CL_VIRUS) {
 -	    cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
++	    cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
  	    if (*vname == 'W') {
  		/* hash is whitelisted in local.gdb */
  		cli_dbgmsg("Skipping hash %s\n", pattern);

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list