[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:07:25 UTC 2010
The following commit has been merged in the debian/unstable branch:
commit 63979bf21e2c11730fa4f8b74b1694387baad5a7
Merge: e6f5ac515713d048a2a6e028255a58cbe03d83cf b183aa786bcc29084d10239973455513469de3b5
Author: aCaB <acab at clamav.net>
Date: Fri Oct 9 22:07:33 2009 +0200
Merge remote branch 'origin/fmap4all'
diff --combined libclamav/Makefile.am
index 9710937,0a976a1..4a27cea
--- a/libclamav/Makefile.am
+++ b/libclamav/Makefile.am
@@@ -309,6 -309,8 +309,8 @@@ libclamav_la_SOURCES =
version.h\
mpool.c\
mpool.h \
+ fmap.c \
+ fmap.h \
default.h\
sha256.c\
sha256.h\
@@@ -346,8 -348,8 +348,8 @@@ version.h: version.h.tm
version.h.tmp:
@test -f version.h || touch version.h;\
rm -f $@;\
- REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null)";\
- if test $$? -ne 0; then\
+ REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null || echo "exported")";\
+ if test "$$REVISION" = "exported"; then\
REVISION="r$$(LANG=C svnversion "$(top_srcdir)" 2>/dev/null || echo exported)";\
if test "$$REVISION" = "rexported"; then\
REVISION="";\
diff --combined libclamav/Makefile.in
index bb018c6,ea34250..7d86e2c
--- a/libclamav/Makefile.in
+++ b/libclamav/Makefile.in
@@@ -145,10 -145,10 +145,10 @@@ am__libclamav_la_SOURCES_DIST = clamav.
7z/Archive/7z/7zExtract.c 7z/Archive/7z/7zExtract.h explode.c \
explode.h textnorm.c textnorm.h dlp.c dlp.h jsparse/js-norm.c \
jsparse/js-norm.h jsparse/lexglobal.h jsparse/textbuf.h uniq.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 type_desc.h bytecode_api.c \
+ uniq.h version.c version.h mpool.c mpool.h fmap.c fmap.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 type_desc.h bytecode_api.c \
bytecode_api_decl.c bytecode_api.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 \
@@@ -193,11 -193,11 +193,11 @@@
libclamav_la-textnorm.lo libclamav_la-dlp.lo \
libclamav_la-js-norm.lo libclamav_la-uniq.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 \
- libclamav_la-bytecode_api.lo libclamav_la-bytecode_api_decl.lo \
- $(am__objects_1)
+ libclamav_la-fmap.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 libclamav_la-bytecode_api.lo \
+ libclamav_la-bytecode_api_decl.lo $(am__objects_1)
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
@@@ -583,10 -583,10 +583,10 @@@ libclamav_la_SOURCES = clamav.h matcher
7z/Archive/7z/7zExtract.c 7z/Archive/7z/7zExtract.h explode.c \
explode.h textnorm.c textnorm.h dlp.c dlp.h jsparse/js-norm.c \
jsparse/js-norm.h jsparse/lexglobal.h jsparse/textbuf.h uniq.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 type_desc.h bytecode_api.c \
+ uniq.h version.c version.h mpool.c mpool.h fmap.c fmap.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 type_desc.h bytecode_api.c \
bytecode_api_decl.c bytecode_api.h $(am__append_7)
noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la
COMMON_CLEANFILES = version.h version.h.tmp *.gcda *.gcno
@@@ -739,6 -739,7 +739,7 @@@ distclean-compile
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-entconv.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-explode.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-filetypes.Plo at am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-fmap.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-fsg.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-hashtab.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libclamav_la-htmlnorm.Plo at am__quote@
@@@ -1510,6 -1511,14 +1511,14 @@@ libclamav_la-mpool.lo: mpool.
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-mpool.lo `test -f 'mpool.c' || echo '$(srcdir)/'`mpool.c
+ libclamav_la-fmap.lo: fmap.c
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-fmap.lo -MD -MP -MF $(DEPDIR)/libclamav_la-fmap.Tpo -c -o libclamav_la-fmap.lo `test -f 'fmap.c' || echo '$(srcdir)/'`fmap.c
+ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-fmap.Tpo $(DEPDIR)/libclamav_la-fmap.Plo
+ @am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='fmap.c' object='libclamav_la-fmap.lo' libtool=yes @AMDEPBACKSLASH@
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-fmap.lo `test -f 'fmap.c' || echo '$(srcdir)/'`fmap.c
+
libclamav_la-sha256.lo: sha256.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-sha256.lo -MD -MP -MF $(DEPDIR)/libclamav_la-sha256.Tpo -c -o libclamav_la-sha256.lo `test -f 'sha256.c' || echo '$(srcdir)/'`sha256.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libclamav_la-sha256.Tpo $(DEPDIR)/libclamav_la-sha256.Plo
@@@ -2028,8 -2037,8 +2037,8 @@@ version.h: version.h.tm
version.h.tmp:
@test -f version.h || touch version.h;\
rm -f $@;\
- REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null)";\
- if test $$? -ne 0; then\
+ REVISION="$$(LANG=C cd "$(top_srcdir)"; git describe --always 2>/dev/null || echo "exported")";\
+ if test "$$REVISION" = "exported"; then\
REVISION="r$$(LANG=C svnversion "$(top_srcdir)" 2>/dev/null || echo exported)";\
if test "$$REVISION" = "rexported"; then\
REVISION="";\
diff --combined libclamav/binhex.c
index d3a429a,eb926c3..705f683
--- a/libclamav/binhex.c
+++ b/libclamav/binhex.c
@@@ -103,32 -103,22 +103,25 @@@ static char const rcsid[] = "$Id: binhe
#include <stdio.h>
#include <memory.h>
#include <sys/stat.h>
-#include "others.h"
+#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
+#include <sys/mman.h>
+#endif
+#include "others.h"
#include "mbox.h"
#include "binhex.h"
+ #include "fmap.h"
int
- cli_binhex(const char *dir, int desc)
+ cli_binhex(const char *dir, fmap_t *map)
{
- #ifndef HAVE_MMAP
- cli_warnmsg("File not decoded - binhex decoding needs mmap() (for now)\n");
- return CL_CLEAN;
- #else
- struct stat statb;
char *buf, *start, *line;
size_t size;
long bytesleft;
message *m;
fileblob *fb;
- if(fstat(desc, &statb) < 0)
- return CL_EOPEN;
-
- size = (size_t)statb.st_size;
+ size = (size_t)map->len;
if(size == 0)
return CL_CLEAN;
@@@ -137,8 -127,8 +130,8 @@@
if(m == NULL)
return CL_EMEM;
- start = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
- if(buf == MAP_FAILED) {
+ start = buf = fmap_need_off_once(map, 0, size);
+ if(!buf) {
messageDestroy(m);
return CL_EMAP;
}
@@@ -149,16 -139,16 +142,16 @@@
line = NULL;
while(bytesleft > 0) {
- int length = 0;
+ int length = bytesleft;
char *ptr, *newline;
/*printf("%d: ", bytesleft);*/
for(ptr = buf; bytesleft && (*ptr != '\n') && (*ptr != '\r'); ptr++) {
--bytesleft;
}
+ length -= bytesleft;
/*printf("%d: ", length);*/
newline = cli_realloc(line, (size_t)(length + 1));
@@@ -182,7 -172,6 +175,6 @@@
buf = ++ptr;
bytesleft--;
}
- munmap(start, size);
if(line)
free(line);
@@@ -208,5 -197,4 +200,4 @@@
return CL_CLEAN; /* a lie - but it gets things going */
/* return CL_EIO; */ /* probably CL_EMEM, but we can't tell at this layer */
return CL_EMEM;
- #endif
}
diff --combined libclamav/chmunpack.c
index 64c582d,47fd17a..3f4a557
--- a/libclamav/chmunpack.c
+++ b/libclamav/chmunpack.c
@@@ -31,11 -31,9 +31,9 @@@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
#include <string.h>
+ #include "fmap.h"
#include "others.h"
#include "mspack.h"
#include "cltypes.h"
@@@ -54,6 -52,10 +52,6 @@@
#pragma pack 1
#endif
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
#define CHM_CHUNK_HDR_LEN (0x14)
#define CHM_CONTROL_LEN (0x18)
@@@ -104,26 -106,12 +102,12 @@@ typedef struct lzx_content_tag
#define chm_endian_convert_64(x) le64_to_host(x)
/* Read in a block of data from either the mmap area or the given fd */
- static int chm_read_data(int fd, char *dest, off_t offset, off_t len,
- char *m_area, off_t m_length)
+ static int chm_read_data(fmap_t *map, char *dest, off_t offset, off_t len)
{
- if ((offset < 0) || (len < 0) || ((offset+len) < 0)) {
- return FALSE;
- }
- if (m_area != NULL) {
- if ((offset+len) > m_length) {
- return FALSE;
- }
- memcpy(dest, m_area+offset, len);
- } else {
- if (lseek(fd, offset, SEEK_SET) != offset) {
- return FALSE;
- }
- if (cli_readn(fd, dest, len) != len) {
- return FALSE;
- }
- }
- return TRUE;
+ void *src = fmap_need_off_once(map, offset, len);
+ if(!src) return FALSE;
+ memcpy(dest, src, len);
+ return TRUE;
}
static uint64_t chm_copy_file_data(int ifd, int ofd, uint64_t len)
@@@ -169,56 -157,11 +153,11 @@@ static void itsf_print_header(chm_itsf_
}
}
- static int itsf_read_header(int fd, chm_itsf_header_t *itsf_hdr, char *m_area, off_t m_length)
+ static int itsf_read_header(chm_metadata_t *metadata)
{
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- if (!chm_read_data(fd, (char *) itsf_hdr, 0, CHM_ITSF_MIN_LEN,
- m_area, m_length)) {
- return FALSE;
- }
- #else
- if (cli_readn(fd, &itsf_hdr->signature, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->version, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->header_len, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->unknown, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->last_modified, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->lang_id, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->dir_clsid, 16) != 16) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->stream_clsid, 16) != 16) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->sec0_offset, 8) != 8) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->sec0_len, 8) != 8) {
- return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->dir_offset, 8) != 8) {
+ chm_itsf_header_t *itsf_hdr = &metadata->itsf_hdr;
+ if (!chm_read_data(metadata->map, (char *)itsf_hdr, 0, CHM_ITSF_MIN_LEN))
return FALSE;
- }
- if (cli_readn(fd, &itsf_hdr->dir_len, 8) != 8) {
- return FALSE;
- }
- if (itsf_hdr->version > 2) {
- if (cli_readn(fd, &itsf_hdr->data_offset, 8) != 8) {
- return FALSE;
- }
- }
- #endif
if (memcmp(itsf_hdr->signature, "ITSF", 4) != 0) {
cli_dbgmsg("ITSF signature mismatch\n");
return FALSE;
@@@ -257,64 -200,11 +196,11 @@@ static void itsp_print_header(chm_itsp_
cli_dbgmsg("Lang ID:\t%u\n\n", itsp_hdr->lang_id);
}
- static int itsp_read_header(int fd, chm_itsp_header_t *itsp_hdr, off_t offset,
- char *m_area, off_t m_length)
+ static int itsp_read_header(chm_metadata_t *metadata, off_t offset)
{
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- if (!chm_read_data(fd, (char *) itsp_hdr, offset, CHM_ITSP_LEN,
- m_area, m_length)) {
- return FALSE;
- }
- #else
- if (lseek(fd, offset, SEEK_SET) != offset) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->signature, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->version, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->header_len, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->unknown1, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->block_len, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->blockidx_intvl, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->index_depth, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->index_root, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->index_head, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->index_tail, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->unknown2, 4) != 4) {
+ chm_itsp_header_t *itsp_hdr = &metadata->itsp_hdr;
+ if (!chm_read_data(metadata->map, (char *)itsp_hdr, offset, CHM_ITSP_LEN))
return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->num_blocks, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->lang_id, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->system_clsid, 16) != 16) {
- return FALSE;
- }
- if (cli_readn(fd, &itsp_hdr->unknown4, 16) != 16) {
- return FALSE;
- }
- #endif
if (memcmp(itsp_hdr->signature, "ITSP", 4) != 0) {
cli_dbgmsg("ITSP signature mismatch\n");
return FALSE;
@@@ -404,7 -294,7 +290,7 @@@ static int read_control_entries(chm_met
return TRUE;
}
- static int prepare_file(int fd, chm_metadata_t *metadata)
+ static int prepare_file(chm_metadata_t *metadata)
{
uint64_t name_len, section;
@@@ -432,7 -322,7 +318,7 @@@
return CL_BREAK;
}
- static int read_chunk(chm_metadata_t *metadata, int fd)
+ static int read_chunk(chm_metadata_t *metadata)
{
cli_dbgmsg("in read_chunk\n");
@@@ -440,29 -330,15 +326,15 @@@
return CL_EFORMAT;
}
- if (metadata->m_area != NULL) {
- if (metadata->chunk_offset > metadata->m_length) {
- return CL_EFORMAT;
- }
- if ((metadata->chunk_offset + metadata->itsp_hdr.block_len) > metadata->m_length) {
- return CL_EFORMAT;
- }
- metadata->chunk_data = metadata->m_area + metadata->chunk_offset;
-
- } else {
- if (!metadata->chunk_data) {
- metadata->chunk_data = (char *) cli_malloc(metadata->itsp_hdr.block_len);
- if (!metadata->chunk_data) {
- return CL_EMEM;
- }
- }
- if (lseek(fd, metadata->chunk_offset, SEEK_SET) != metadata->chunk_offset) {
- goto abort;
- }
- if ((uint32_t) cli_readn(fd, metadata->chunk_data, metadata->itsp_hdr.block_len) != metadata->itsp_hdr.block_len) {
- goto abort;
- }
+ if (metadata->chunk_offset > metadata->m_length) {
+ return CL_EFORMAT;
+ }
+ if ((metadata->chunk_offset + metadata->itsp_hdr.block_len) > metadata->m_length) {
+ return CL_EFORMAT;
}
+ metadata->chunk_data = fmap_need_off_once(metadata->map, metadata->chunk_offset, metadata->itsp_hdr.block_len);
+ if(!metadata->chunk_data) return CL_EFORMAT;
+
metadata->chunk_current = metadata->chunk_data + CHM_CHUNK_HDR_LEN;
metadata->chunk_end = metadata->chunk_data + metadata->itsp_hdr.block_len;
@@@ -470,19 -346,10 +342,10 @@@
metadata->chunk_entries = (uint16_t)((((uint8_t const *)(metadata->chunk_data))[metadata->itsp_hdr.block_len-2] << 0)
| (((uint8_t const *)(metadata->chunk_data))[metadata->itsp_hdr.block_len-1] << 8));
} else if (memcmp(metadata->chunk_data, "PMGI", 4) != 0) {
- if (!metadata->m_area && metadata->chunk_data) {
- free(metadata->chunk_data);
- }
return CL_BREAK;
}
return CL_SUCCESS;
- abort:
- if (!metadata->m_area && metadata->chunk_data) {
- free(metadata->chunk_data);
- metadata->chunk_data = NULL;
- }
- return CL_EFORMAT;
}
static void print_sys_control(lzx_control_t *lzx_control)
@@@ -501,7 -368,7 +364,7 @@@
cli_dbgmsg("Cache Size:\t%d\n\n", lzx_control->cache_size);
}
- static int read_sys_control(int fd, chm_metadata_t *metadata, lzx_control_t *lzx_control)
+ static int read_sys_control(chm_metadata_t *metadata, lzx_control_t *lzx_control)
{
off_t offset;
@@@ -513,34 -380,10 +376,10 @@@
return FALSE;
}
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- if (!chm_read_data(fd, (char *) lzx_control, offset, CHM_CONTROL_LEN,
- metadata->m_area, metadata->m_length)) {
- return FALSE;
- }
- #else
- if (lseek(fd, offset, SEEK_SET) != offset) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_control->length, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_control->signature, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_control->version, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_control->reset_interval, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_control->window_size, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_control->cache_size, 4) != 4) {
+ if (!chm_read_data(metadata->map, (char *) lzx_control, offset, CHM_CONTROL_LEN)) {
return FALSE;
}
- #endif
+
lzx_control->length = chm_endian_convert_32(lzx_control->length);
lzx_control->version = chm_endian_convert_32(lzx_control->version);
lzx_control->reset_interval = chm_endian_convert_32(lzx_control->reset_interval);
@@@ -578,7 -421,7 +417,7 @@@ static void print_sys_content(lzx_conte
cli_dbgmsg("Length:\t%lu\n\n", (unsigned long int) lzx_content->length);
}
- static int read_sys_content(int fd, chm_metadata_t *metadata, lzx_content_t *lzx_content)
+ static int read_sys_content(chm_metadata_t *metadata, lzx_content_t *lzx_content)
{
lzx_content->offset = metadata->itsf_hdr.data_offset + metadata->sys_content.offset;
lzx_content->length = metadata->sys_content.length;
@@@ -602,7 -445,7 +441,7 @@@ static void print_sys_reset_table(lzx_r
cli_dbgmsg("Frame Len:\t%lu\n\n", (unsigned long int) lzx_reset_table->frame_len);
}
- static int read_sys_reset_table(int fd, chm_metadata_t *metadata, lzx_reset_table_t *lzx_reset_table)
+ static int read_sys_reset_table(chm_metadata_t *metadata, lzx_reset_table_t *lzx_reset_table)
{
off_t offset;
@@@ -619,34 -462,10 +458,10 @@@
/* Save the entry offset for later use */
lzx_reset_table->rt_offset = offset-4;
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- if (!chm_read_data(fd, (char *) lzx_reset_table, offset, CHM_RESET_TABLE_LEN,
- metadata->m_area, metadata->m_length)) {
- return FALSE;
- }
- #else
- if (lseek(fd, offset, SEEK_SET) != offset) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_reset_table->num_entries, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_reset_table->entry_size, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_reset_table->table_offset, 4) != 4) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_reset_table->uncom_len, 8) != 8) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_reset_table->com_len, 8) != 8) {
- return FALSE;
- }
- if (cli_readn(fd, &lzx_reset_table->frame_len, 8) != 8) {
+ if (!chm_read_data(metadata->map, (char *) lzx_reset_table, offset, CHM_RESET_TABLE_LEN)) {
return FALSE;
}
- #endif
+
lzx_reset_table->num_entries = chm_endian_convert_32(lzx_reset_table->num_entries);
lzx_reset_table->entry_size = chm_endian_convert_32(lzx_reset_table->entry_size);
lzx_reset_table->table_offset = chm_endian_convert_32(lzx_reset_table->table_offset);
@@@ -680,7 -499,7 +495,7 @@@ static int chm_decompress_stream(int fd
char filename[1024];
struct cab_file file;
- snprintf(filename, 1024, "%s/clamav-unchm.bin", dirname);
+ snprintf(filename, 1024, "%s"PATHSEP"clamav-unchm.bin", dirname);
tmpfd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
if (tmpfd<0) {
cli_dbgmsg("open failed for %s\n", filename);
@@@ -692,13 -511,13 +507,13 @@@
goto abort;
}
- if (!read_sys_control(fd, metadata, &lzx_control)) {
+ if (!read_sys_control(metadata, &lzx_control)) {
goto abort;
}
- if (!read_sys_content(fd, metadata, &lzx_content)) {
+ if (!read_sys_content(metadata, &lzx_content)) {
goto abort;
}
- if (!read_sys_reset_table(fd, metadata, &lzx_reset_table)) {
+ if (!read_sys_reset_table(metadata, &lzx_reset_table)) {
goto abort;
}
@@@ -756,7 -575,7 +571,7 @@@
lzx_decompress(stream, length);
lzx_free(stream);
-#ifndef C_WINDOWS
+#ifndef _WIN32
/* Delete the file */
if(cli_unlink(filename))
retval = -1;
@@@ -780,7 -599,7 +595,7 @@@ static int chm_init_metadata(chm_metada
}
metadata->sys_control.length = metadata->sys_content.length = metadata->sys_reset.length = 0;
- metadata->m_area = NULL;
+ metadata->map = NULL;
metadata->ufd = -1;
metadata->num_chunks = metadata->chunk_entries = 0;
metadata->chunk_data = NULL;
@@@ -792,17 -611,10 +607,10 @@@ void cli_chm_close(chm_metadata_t *meta
if (metadata->ufd >= 0) {
close(metadata->ufd);
}
- if (!metadata->m_area && metadata->chunk_data) {
- free(metadata->chunk_data);
- }
- #ifdef HAVE_MMAP
- if (metadata->m_area) {
- munmap(metadata->m_area, metadata->m_length);
- }
- #endif
+ funmap(metadata->map);
}
- int cli_chm_extract_file(int fd, char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
+ int cli_chm_extract_file(char *dirname, chm_metadata_t *metadata, cli_ctx *ctx)
{
char filename[1024];
uint64_t len;
@@@ -813,7 -625,7 +621,7 @@@
cli_dbgmsg("seek in uncompressed stream failed\n");
return CL_EFORMAT;
}
- snprintf(filename, 1024, "%s/%lu.chm", dirname, (unsigned long int) metadata->file_offset);
+ snprintf(filename, 1024, "%s"PATHSEP"%lu.chm", dirname, (unsigned long int) metadata->file_offset);
metadata->ofd = open(filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
if (metadata->ofd < 0) {
return CL_ECREAT;
@@@ -828,7 -640,7 +636,7 @@@
return CL_SUCCESS;
}
- int cli_chm_prepare_file(int fd, char *dirname, chm_metadata_t *metadata)
+ int cli_chm_prepare_file(chm_metadata_t *metadata)
{
int retval;
@@@ -839,13 -651,13 +647,13 @@@
if (metadata->num_chunks == 0) {
return CL_BREAK;
}
- if ((retval = read_chunk(metadata, fd)) != CL_SUCCESS) {
+ if ((retval = read_chunk(metadata)) != CL_SUCCESS) {
return retval;
}
metadata->num_chunks--;
metadata->chunk_offset += metadata->itsp_hdr.block_len;
}
- retval = prepare_file(fd, metadata);
+ retval = prepare_file(metadata);
} while (retval == CL_BREAK); /* Ran out of chunk entries before finding a file */
return retval;
}
@@@ -861,25 -673,23 +669,23 @@@ int cli_chm_open(int fd, const char *di
return retval;
}
- #ifdef HAVE_MMAP
if (fstat(fd, &statbuf) == 0) {
if (statbuf.st_size < CHM_ITSF_MIN_LEN) {
- goto abort;
+ return CL_ESTAT;
}
metadata->m_length = statbuf.st_size;
- metadata->m_area = (char *) mmap(NULL, metadata->m_length, PROT_READ, MAP_PRIVATE, fd, 0);
- if (metadata->m_area == MAP_FAILED) {
- metadata->m_area = NULL;
+ metadata->map = fmap(fd, 0, metadata->m_length);
+ if (!metadata->map) {
+ return CL_EMAP;
}
}
- #endif
- if (!itsf_read_header(fd, &metadata->itsf_hdr, metadata->m_area, metadata->m_length)) {
+ if (!itsf_read_header(metadata)) {
goto abort;
}
itsf_print_header(&metadata->itsf_hdr);
- if (!itsp_read_header(fd, &metadata->itsp_hdr, metadata->itsf_hdr.dir_offset, metadata->m_area, metadata->m_length)) {
+ if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) {
goto abort;
}
itsp_print_header(&metadata->itsp_hdr);
@@@ -903,7 -713,7 +709,7 @@@
}
while (metadata->num_chunks) {
- if (read_chunk(metadata, fd) != CL_SUCCESS) {
+ if (read_chunk(metadata) != CL_SUCCESS) {
cli_dbgmsg("read_chunk failed\n");
goto abort;
}
@@@ -932,10 -742,6 +738,6 @@@
return CL_SUCCESS;
abort:
- #ifdef HAVE_MMAP
- if (metadata->m_area) {
- munmap(metadata->m_area, metadata->m_length);
- }
- #endif
+ funmap(metadata->map);
return CL_EFORMAT;
}
diff --combined libclamav/elf.c
index 9239640,f47db3a..3a978c8
--- a/libclamav/elf.c
+++ b/libclamav/elf.c
@@@ -63,7 -63,7 +63,7 @@@ static uint32_t cli_rawaddr(uint32_t va
return vaddr - EC32(ph[i].p_vaddr, conv) + EC32(ph[i].p_offset, conv);
}
- int cli_scanelf(int desc, cli_ctx *ctx)
+ int cli_scanelf(cli_ctx *ctx)
{
struct elf_file_hdr32 file_hdr;
struct elf_section_hdr32 *section_hdr;
@@@ -72,11 -72,12 +72,12 @@@
uint32_t entry, fentry, shoff, phoff, i;
uint8_t conv = 0, err;
unsigned int format;
+ fmap_t *map = *ctx->fmap;
cli_dbgmsg("in cli_scanelf\n");
- if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
+ if(fmap_readn(map, &file_hdr, 0, sizeof(file_hdr)) != sizeof(file_hdr)) {
/* Not an ELF file? */
cli_dbgmsg("ELF: Can't read file header\n");
return CL_CLEAN;
@@@ -95,8 -96,7 +96,7 @@@
if(format == 2) {
struct elf_file_hdr64 file_hdr64;
- lseek(desc, 0, SEEK_SET);
- if(read(desc, &file_hdr64, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
+ if(fmap_readn(map, &file_hdr64, 0, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
/* Not an ELF file? */
cli_dbgmsg("ELF: Can't read file header\n");
return CL_CLEAN;
@@@ -216,7 -216,7 +216,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_EFORMAT;
}
@@@ -229,21 -229,13 +229,13 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_EFORMAT;
}
phoff = EC32(file_hdr.e_phoff, conv);
cli_dbgmsg("ELF: Program header table offset: %d\n", phoff);
- if((uint32_t) lseek(desc, phoff, SEEK_SET) != phoff) {
- if(DETECT_BROKEN) {
- if(ctx->virname)
- *ctx->virname = "Broken.Executable";
- return CL_VIRUS;
- }
- return CL_CLEAN;
- }
program_hdr = (struct elf_program_hdr32 *) cli_calloc(phnum, phentsize);
if(!program_hdr) {
@@@ -256,12 -248,13 +248,13 @@@
for(i = 0; i < phnum; i++) {
err = 0;
if(format == 1) {
- if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
+ if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
err = 1;
+ phoff += sizeof(struct elf_program_hdr32);
} else {
struct elf_program_hdr64 program_hdr64;
- if(read(desc, &program_hdr64, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
+ if(fmap_readn(map, &program_hdr64, phoff, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
err = 1;
} else {
program_hdr[i].p_type = program_hdr64.p_type;
@@@ -273,6 -266,7 +266,7 @@@
program_hdr[i].p_flags = program_hdr64.p_flags;
program_hdr[i].p_align = program_hdr64.p_align;
}
+ phoff += sizeof(program_hdr64);
}
if(err) {
@@@ -282,7 -276,7 +276,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN;
}
@@@ -303,7 -297,7 +297,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_EFORMAT;
}
@@@ -320,7 -314,7 +314,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_EFORMAT;
}
@@@ -331,22 -325,13 +325,13 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_EFORMAT;
}
shoff = EC32(file_hdr.e_shoff, conv);
cli_dbgmsg("ELF: Section header table offset: %d\n", shoff);
- if((uint32_t) lseek(desc, shoff, SEEK_SET) != shoff) {
- /* Possibly broken end of file */
- if(DETECT_BROKEN) {
- if(ctx->virname)
- *ctx->virname = "Broken.Executable";
- return CL_VIRUS;
- }
- return CL_CLEAN;
- }
section_hdr = (struct elf_section_hdr32 *) cli_calloc(shnum, shentsize);
if(!section_hdr) {
@@@ -359,12 -344,13 +344,13 @@@
for(i = 0; i < shnum; i++) {
err = 0;
if(format == 1) {
- if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
+ if(fmap_readn(map, §ion_hdr[i], shoff, sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
err = 1;
+ shoff += sizeof(struct elf_section_hdr32);
} else {
struct elf_section_hdr64 section_hdr64;
- if(read(desc, §ion_hdr64, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
+ if(fmap_readn(map, §ion_hdr64, shoff, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
err = 1;
} else {
section_hdr[i].sh_name = section_hdr64.sh_name;
@@@ -378,6 -364,7 +364,7 @@@
section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
}
+ shoff += sizeof(section_hdr64);
}
if(err) {
@@@ -387,7 -374,7 +374,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN;
}
@@@ -468,7 -455,7 +455,7 @@@
return CL_CLEAN;
}
- int cli_elfheader(int desc, struct cli_exe_info *elfinfo)
+ int cli_elfheader(fmap_t *map, struct cli_exe_info *elfinfo)
{
struct elf_file_hdr32 file_hdr;
struct elf_section_hdr32 *section_hdr;
@@@ -480,7 -467,7 +467,7 @@@
cli_dbgmsg("in cli_elfheader\n");
- if(read(desc, &file_hdr, sizeof(file_hdr)) != sizeof(file_hdr)) {
+ if(fmap_readn(map, &file_hdr, 0, sizeof(file_hdr)) != sizeof(file_hdr)) {
/* Not an ELF file? */
cli_dbgmsg("ELF: Can't read file header\n");
return -1;
@@@ -499,8 -486,7 +486,7 @@@
if(format == 2) {
struct elf_file_hdr64 file_hdr64;
- lseek(desc, 0, SEEK_SET);
- if(read(desc, &file_hdr64, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
+ if(!fmap_readn(map, &file_hdr64, 0, sizeof(file_hdr64)) != sizeof(file_hdr64)) {
/* Not an ELF file? */
cli_dbgmsg("ELF: Can't read file header\n");
return -1;
@@@ -547,9 -533,6 +533,6 @@@
}
phoff = EC32(file_hdr.e_phoff, conv);
- if((uint32_t) lseek(desc, phoff, SEEK_SET) != phoff) {
- return -1;
- }
program_hdr = (struct elf_program_hdr32 *) cli_calloc(phnum, phentsize);
if(!program_hdr) {
@@@ -560,12 -543,13 +543,13 @@@
for(i = 0; i < phnum; i++) {
err = 0;
if(format == 1) {
- if(read(desc, &program_hdr[i], sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
+ if(fmap_readn(map, &program_hdr[i], phoff, sizeof(struct elf_program_hdr32)) != sizeof(struct elf_program_hdr32))
err = 1;
+ phoff += sizeof(struct elf_program_hdr32);
} else {
struct elf_program_hdr64 program_hdr64;
- if(read(desc, &program_hdr64, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
+ if(fmap_readn(map, &program_hdr64, phoff, sizeof(program_hdr64)) != sizeof(program_hdr64)) {
err = 1;
} else {
program_hdr[i].p_type = program_hdr64.p_type;
@@@ -577,6 -561,7 +561,7 @@@
program_hdr[i].p_flags = program_hdr64.p_flags;
program_hdr[i].p_align = program_hdr64.p_align;
}
+ phoff += sizeof(program_hdr64);
}
if(err) {
@@@ -610,10 -595,6 +595,6 @@@
}
shoff = EC32(file_hdr.e_shoff, conv);
- if((uint32_t) lseek(desc, shoff, SEEK_SET) != shoff) {
- /* Possibly broken end of file */
- return -1;
- }
elfinfo->section = (struct cli_exe_section *) cli_calloc(elfinfo->nsections, sizeof(struct cli_exe_section));
if(!elfinfo->section) {
@@@ -632,12 -613,13 +613,13 @@@
for(i = 0; i < shnum; i++) {
err = 0;
if(format == 1) {
- if(read(desc, §ion_hdr[i], sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
+ if(fmap_readn(map, §ion_hdr[i], shoff, sizeof(struct elf_section_hdr32)) != sizeof(struct elf_section_hdr32))
err = 1;
+ shoff += sizeof(struct elf_section_hdr32);
} else {
struct elf_section_hdr64 section_hdr64;
- if(read(desc, §ion_hdr64, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
+ if(fmap_readn(map, §ion_hdr64, shoff, sizeof(section_hdr64)) != sizeof(section_hdr64)) {
err = 1;
} else {
section_hdr[i].sh_name = section_hdr64.sh_name;
@@@ -651,6 -633,7 +633,7 @@@
section_hdr[i].sh_addralign = section_hdr64.sh_addralign;
section_hdr[i].sh_entsize = section_hdr64.sh_entsize;
}
+ shoff += sizeof(section_hdr64);
}
if(err) {
diff --combined libclamav/htmlnorm.c
index b777491,3a270d8..2588698
--- a/libclamav/htmlnorm.c
+++ b/libclamav/htmlnorm.c
@@@ -39,10 -39,8 +39,8 @@@
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
+ #include "fmap.h"
#include "others.h"
#include "htmlnorm.h"
@@@ -180,15 -178,23 +178,23 @@@ static unsigned char *cli_readchunk(FIL
/* Try and use the memory buffer first */
if (m_area) {
- start = ptr = m_area->buffer + m_area->offset;
- end = m_area->buffer + m_area->length;
+ /* maximum we can copy into the buffer,
+ * we could have less than max_len bytes available */
+ chunk_len = MIN(m_area->length-m_area->offset, max_len-1);
+ if(!chunk_len) {
+ free(chunk);
+ return NULL;
+ }
+ if(m_area->map)
+ ptr = (unsigned char *)fmap_need_off_once(m_area->map, m_area->offset, chunk_len);
+ else
+ ptr = m_area->buffer + m_area->offset;
+ start = ptr;
+ end = ptr - m_area->offset + m_area->length;
if (start >= end) {
free(chunk);
return NULL;
}
- /* maximum we can copy into the buffer,
- * we could have less than max_len bytes available */
- chunk_len = MIN(end-start, max_len-1);
/* look for NULL chars */
ptr = memchr(start, 0, chunk_len);
@@@ -209,18 -215,20 +215,20 @@@
chunk_len = 0;
ptr = start;
}
+ if(m_area->map)
+ ptr = (unsigned char *)fmap_need_ptr_once(m_area->map, ptr, end - ptr);
/* we have unknown number of NULL chars,
* copy char-by-char and skip them */
while((ptr < end) && (chunk_len < max_len-1)) {
const unsigned char c = *ptr++;
+ /* we can't use chunk_len to determine how many bytes we read, since
+ * we skipped chars */
if(c) {
chunk[chunk_len++] = c;
}
}
+ m_area->offset += ptr - start;
chunk[chunk_len] = '\0';
- /* we can't use chunk_len to determine how many bytes we read, since
- * we skipped chars */
- m_area->offset = ptr - m_area->buffer;
}
if(ptr && ptr < end && !isspace(*ptr)) {
/* we hit max_len, rewind to a space */
@@@ -648,7 -656,7 +656,7 @@@ static int cli_html_normalise(int fd, m
tag_args.value = NULL;
tag_args.contents = NULL;
if (dirname) {
- snprintf(filename, 1024, "%s/rfc2397", dirname);
+ snprintf(filename, 1024, "%s"PATHSEP"rfc2397", dirname);
if (mkdir(filename, 0700) && errno != EEXIST) {
file_buff_o2 = file_buff_text = NULL;
goto abort;
@@@ -661,7 -669,7 +669,7 @@@
}
/* this will still contains scripts that are inside comments */
- snprintf(filename, 1024, "%s/nocomment.html", dirname);
+ snprintf(filename, 1024, "%s"PATHSEP"nocomment.html", dirname);
file_buff_o2->fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
if (file_buff_o2->fd == -1) {
cli_dbgmsg("open failed: %s\n", filename);
@@@ -678,7 -686,7 +686,7 @@@
goto abort;
}
- snprintf(filename, 1024, "%s/notags.html", dirname);
+ snprintf(filename, 1024, "%s"PATHSEP"notags.html", dirname);
file_buff_text->fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
if(file_buff_text->fd == -1) {
cli_dbgmsg("open failed: %s\n", filename);
@@@ -1477,7 -1485,7 +1485,7 @@@
if (!file_tmp_o1) {
goto abort;
}
- snprintf(filename, 1024, "%s/rfc2397", dirname);
+ snprintf(filename, 1024, "%s"PATHSEP"rfc2397", dirname);
tmp_file = cli_gentemp(filename);
if(!tmp_file) {
goto abort;
@@@ -1697,37 -1705,21 +1705,21 @@@ int html_normalise_mem(unsigned char *i
m_area.buffer = in_buff;
m_area.length = in_size;
m_area.offset = 0;
+ m_area.map = NULL;
return cli_html_normalise(-1, &m_area, dirname, hrefs, dconf);
}
- int html_normalise_fd(int fd, const char *dirname, tag_arguments_t *hrefs,const struct cli_dconf* dconf)
+ int html_normalise_map(fmap_t *map, const char *dirname, tag_arguments_t *hrefs,const struct cli_dconf* dconf)
{
- #if HAVE_MMAP
int retval=FALSE;
m_area_t m_area;
- struct stat statbuf;
-
- if (fstat(fd, &statbuf) == 0) {
- m_area.length = statbuf.st_size;
- m_area.buffer = (unsigned char *) mmap(NULL, m_area.length, PROT_READ, MAP_PRIVATE, fd, 0);
- m_area.offset = 0;
- if (m_area.buffer == MAP_FAILED) {
- cli_dbgmsg("mmap HTML failed\n");
- retval = cli_html_normalise(fd, NULL, dirname, hrefs, dconf);
- } else {
- cli_dbgmsg("mmap'ed file\n");
- retval = cli_html_normalise(-1, &m_area, dirname, hrefs, dconf);
- munmap(m_area.buffer, m_area.length);
- }
- } else {
- cli_dbgmsg("fstat HTML failed\n");
- retval = cli_html_normalise(fd, NULL, dirname, hrefs, dconf);
- }
+
+ m_area.length = map->len;
+ m_area.offset = 0;
+ m_area.map = map;
+ retval = cli_html_normalise(-1, &m_area, dirname, hrefs, dconf);
return retval;
- #else
- return cli_html_normalise(fd, NULL, dirname, hrefs, dconf);
- #endif
}
int html_screnc_decode(int fd, const char *dirname)
@@@ -1750,7 -1742,7 +1742,7 @@@
return FALSE;
}
- snprintf((char*)filename, 1024, "%s/screnc.html", dirname);
+ snprintf((char*)filename, 1024, "%s"PATHSEP"screnc.html", dirname);
ofd = open((const char*)filename, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
if (ofd < 0) {
diff --combined libclamav/ishield.c
index 58bbc5e,2346897..fa340b9
--- a/libclamav/ishield.c
+++ b/libclamav/ishield.c
@@@ -24,8 -24,6 +24,6 @@@
#include "clamav-config.h"
#endif
- #define _XOPEN_SOURCE 500
-
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@@ -39,16 -37,18 +37,17 @@@
#if HAVE_STRINGS_H
#include <strings.h>
#endif
+#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
+#include <sys/mman.h>
+#endif
#include <zlib.h>
#include "scanners.h"
#include "cltypes.h"
#include "others.h"
+ #include "fmap.h"
#include "ishield.h"
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
#ifndef LONG_MAX
#define LONG_MAX ((-1UL)>>1)
#endif
@@@ -65,6 -65,14 +64,14 @@@
/* PACKED things go here */
+ struct IS_HDR {
+ uint32_t magic;
+ uint32_t unk1; /* version ??? */
+ uint32_t unk2; /* ??? */
+ uint32_t data_off;
+ uint32_t data_sz; /* ??? */
+ } __attribute__((packed));
+
struct IS_FB {
char fname[0x104]; /* MAX_PATH */
uint32_t unk1; /* 6 */
@@@ -181,21 -189,22 +188,22 @@@ struct IS_FILEITEM
- static int is_dump_and_scan(int desc, cli_ctx *ctx, off_t off, size_t fsize);
+ static int is_dump_and_scan(cli_ctx *ctx, off_t off, size_t fsize);
static const uint8_t skey[] = { 0xec, 0xca, 0x79, 0xf8 }; /* ~0x13, ~0x35, ~0x86, ~0x07 */
/* Extracts the content of MSI based IS */
- int cli_scanishield_msi(int desc, cli_ctx *ctx, off_t off) {
- uint8_t buf[BUFSIZ];
+ int cli_scanishield_msi(cli_ctx *ctx, off_t off) {
+ uint8_t *buf;
unsigned int fcount, scanned = 0;
int ret;
+ fmap_t *map = *ctx->fmap;
cli_dbgmsg("in ishield-msi\n");
- lseek(desc, off, SEEK_SET);
- if(cli_readn(desc, buf, 0x20) != 0x20) {
+ if(!(buf = fmap_need_off_once(map, off, 0x20))) {
cli_dbgmsg("ishield-msi: short read for header\n");
return CL_CLEAN;
}
+ off += 0x20;
if(cli_readint32(buf + 8) | cli_readint32(buf + 0xc) | cli_readint32(buf + 0x10) | cli_readint32(buf + 0x14) | cli_readint32(buf + 0x18) | cli_readint32(buf + 0x1c))
return CL_CLEAN;
if(!(fcount = cli_readint32(buf))) {
@@@ -211,16 -220,20 +219,20 @@@
uint64_t csize;
z_stream z;
- if(cli_readn(desc, &fb, sizeof(fb)) != sizeof(fb)) {
+ if(fmap_readn(map, &fb, off, sizeof(fb)) != sizeof(fb)) {
cli_dbgmsg("ishield-msi: short read for fileblock\n");
return CL_CLEAN;
}
+ off += sizeof(fb);
fb.fname[sizeof(fb.fname)-1] = '\0';
csize = le64_to_host(fb.csize);
-
+ if(!CLI_ISCONTAINED(0, map->len, off, csize)) {
+ cli_dbgmsg("ishield-msi: next stream is out of file, giving up\n");
+ return CL_CLEAN;
+ }
if(ctx->engine->maxfilesize && csize > ctx->engine->maxfilesize) {
cli_dbgmsg("ishield-msi: skipping stream due to size limits (%lu vs %lu)\n", (unsigned long int) csize, (unsigned long int) ctx->engine->maxfilesize);
- lseek(desc, csize, SEEK_CUR);
+ off += csize;
continue;
}
@@@ -241,20 -254,21 +253,21 @@@
inflateInit(&z);
ret = CL_SUCCESS;
while(csize) {
- unsigned int sz = csize < sizeof(buf) ? csize : sizeof(buf);
- z.avail_in = cli_readn(desc, buf, sz);
- if(z.avail_in <= 0) {
+ uint8_t buf2[BUFSIZ];
+ z.avail_in = MIN(csize, sizeof(buf2));
+ if(fmap_readn(map, buf2, off, z.avail_in) != z.avail_in) {
cli_dbgmsg("ishield-msi: premature EOS or read fail\n");
- break;
+ break;
}
+ off += z.avail_in;
for(i=0; i<z.avail_in; i++, lameidx++) {
- uint8_t c = buf[i];
+ uint8_t c = buf2[i];
c = (c>>4) | (c<<4);
c ^= key[(lameidx & 0x3ff) % keylen];
- buf[i] = c;
+ buf2[i] = c;
}
csize -= z.avail_in;
- z.next_in = buf;
+ z.next_in = buf2;
do {
int inf;
z.avail_out = sizeof(obuf);
@@@ -263,7 -277,7 +276,7 @@@
if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
cli_dbgmsg("ishield-msi: bad stream\n");
csize = 0;
- lseek(desc, csize, SEEK_CUR);
+ off += csize;
break;
}
if (cli_writen(ofd, obuf, sizeof(obuf) - z.avail_out) < 0) {
@@@ -273,7 -287,7 +286,7 @@@
}
if(ctx->engine->maxfilesize && z.total_out > ctx->engine->maxfilesize) {
cli_dbgmsg("ishield-msi: trimming output file due to size limits (%lu vs %lu)\n", z.total_out, (unsigned long int) ctx->engine->maxfilesize);
- lseek(desc, csize, SEEK_CUR);
+ off += csize;
csize = 0;
break;
}
@@@ -319,55 -333,47 +332,47 @@@ struct IS_CABSTUFF
};
static void md5str(uint8_t *sum);
- static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c);
- static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize);
+ static int is_parse_hdr(cli_ctx *ctx, struct IS_CABSTUFF *c);
+ static int is_extract_cab(cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize);
/* Extract the content of older (non-MSI) IS */
- int cli_scanishield(int desc, cli_ctx *ctx, off_t off, size_t sz) {
+ int cli_scanishield(cli_ctx *ctx, off_t off, size_t sz) {
char *fname, *path, *version, *strsz, *eostr, *data;
- char buf[2048];
- int rd, ret = CL_CLEAN;
+ int ret = CL_CLEAN;
long fsize;
off_t coff = off;
struct IS_CABSTUFF c = { NULL, -1, 0, 0 };
+ fmap_t *map = *ctx->fmap;
while(ret == CL_CLEAN) {
- rd = pread(desc, buf, sizeof(buf), coff);
- if(rd <= 0)
- break;
+ fname = fmap_need_offstr(map, coff, 2048);
+ if(!fname) break;
+ coff += strlen(fname) + 1;
- fname = buf;
- if(!*fname) break;
- path = memchr(fname, 0, rd);
- if(!path)
- break;
+ path = fmap_need_offstr(map, coff, 2048);
+ if(!path) break;
+ coff += strlen(path) + 1;
- path++;
- rd -= (path - buf);
- if(rd<=0 || !(version = memchr(path, 0, rd)))
- break;
+ version = fmap_need_offstr(map, coff, 2048);
+ if(!version) break;
+ coff += strlen(version) + 1;
- version++;
- rd -= (version - path);
- if(rd<=0 || !(strsz = memchr(version, 0, rd)))
- break;
+ strsz = fmap_need_offstr(map, coff, 2048);
+ if(!strsz) break;
+ coff += strlen(strsz) + 1;
- strsz++;
- rd -= (strsz - version);
- if(rd<=0 || !(data = memchr(strsz, 0, rd)))
- break;
+ data = &strsz[strlen(strsz) + 1];
- data++;
fsize = strtol(strsz, &eostr, 10);
if(fsize < 0 || fsize == LONG_MAX ||
!*strsz || !eostr || eostr == strsz || *eostr ||
(unsigned long)fsize >= sz ||
- data - buf >= sz - fsize
+ data - fname >= sz - fsize
) break;
cli_dbgmsg("ishield: @%lx found file %s (%s) - version %s - size %lu\n", (unsigned long int) coff, fname, path, version, (unsigned long int) fsize);
- sz -= (data - buf) + fsize;
- coff += (data - buf);
+ sz -= (data - fname) + fsize;
+
if(!strncasecmp(fname, "data", 4)) {
long cabno;
if(!strcasecmp(fname + 4, "1.hdr")) {
@@@ -401,20 -407,21 +406,21 @@@
}
}
- ret = is_dump_and_scan(desc, ctx, coff, fsize);
+ fmap_unneed_ptr(map, fname, data-fname);
+ ret = is_dump_and_scan(ctx, coff, fsize);
coff += fsize;
}
if(ret == CL_CLEAN && (c.cabcnt || c.hdr != -1)) {
- if((ret = is_parse_hdr(desc, ctx, &c)) == CL_CLEAN) {
+ if((ret = is_parse_hdr(ctx, &c)) == CL_CLEAN) {
unsigned int i;
if(c.hdr != -1) {
cli_dbgmsg("ishield: scanning data1.hdr\n");
- ret = is_dump_and_scan(desc, ctx, c.hdr, c.hdrsz);
+ ret = is_dump_and_scan(ctx, c.hdr, c.hdrsz);
}
for(i=0; i<c.cabcnt && ret == CL_CLEAN; i++) {
cli_dbgmsg("ishield: scanning data%u.cab\n", c.cabs[i].cabno);
- ret = is_dump_and_scan(desc, ctx, c.cabs[i].off, c.cabs[i].sz);
+ ret = is_dump_and_scan(ctx, c.cabs[i].off, c.cabs[i].sz);
}
} else if( ret == CL_BREAK ) ret = CL_CLEAN;
}
@@@ -424,9 -431,10 +430,10 @@@
/* Utility func to scan a fd @ a given offset and size */
- static int is_dump_and_scan(int desc, cli_ctx *ctx, off_t off, size_t fsize) {
- char *fname, buf[BUFSIZ];
+ static int is_dump_and_scan(cli_ctx *ctx, off_t off, size_t fsize) {
+ char *fname, *buf;
int ofd, ret = CL_CLEAN;
+ fmap_t *map = *ctx->fmap;
if(!fsize) {
cli_dbgmsg("ishield: skipping empty file\n");
@@@ -441,19 -449,18 +448,18 @@@
return CL_ECREAT;
}
while(fsize) {
- size_t rd = fsize < sizeof(buf) ? fsize : sizeof(buf);
- int got = pread(desc, buf, rd, off);
- if(got <= 0) {
+ size_t rd = MIN(fsize, map->pgsz);
+ if(!(buf = fmap_need_off_once(map, off, rd))) {
cli_dbgmsg("ishield: read error\n");
ret = CL_EREAD;
break;
}
- if(cli_writen(ofd, buf, got) <= 0) {
+ if(cli_writen(ofd, buf, rd) <= 0) {
ret = CL_EWRITE;
break;
}
- fsize -= got;
- off += got;
+ fsize -= rd;
+ off += rd;
}
if(!fsize) {
cli_dbgmsg("ishield: extracted to %s\n", fname);
@@@ -467,29 -474,13 +473,13 @@@
return ret;
}
-
- struct IS_HDR {
- uint32_t magic;
- uint32_t unk1; /* version ??? */
- uint32_t unk2; /* ??? */
- uint32_t data_off;
- uint32_t data_sz; /* ??? */
- };
-
-
- #define IS_FREE_HDR if(map) munmap(map, mp_hdrsz); else free(hdr);
- #if HAVE_MMAP
- #define IS_MAX_NOMAP_SZ 0x100000
- #else
- #define IS_MAX_NOMAP_SZ CLI_MAX_ALLOCATION
- #endif
-
/* Process data1.hdr and extracts all the available files from dataX.cab */
- static int is_parse_hdr(int desc, cli_ctx *ctx, struct IS_CABSTUFF *c) {
+ static int is_parse_hdr(cli_ctx *ctx, struct IS_CABSTUFF *c) {
uint32_t h1_data_off, objs_files_cnt, objs_dirs_off;
unsigned int off, i, scanned = 0;
int ret = CL_BREAK;
- char hash[33], *hdr, *map = NULL;
+ char hash[33], *hdr;
+ fmap_t *map = *ctx->fmap;
size_t mp_hdrsz;
struct IS_HDR *h1;
@@@ -501,52 -492,29 +491,29 @@@
return CL_CLEAN;
}
- if(c->hdrsz < IS_MAX_NOMAP_SZ) {
- if(!(hdr = (char *)cli_malloc(c->hdrsz)))
- return CL_EMEM;
- if(pread(desc, hdr, c->hdrsz, c->hdr) < (ssize_t)c->hdrsz) {
- cli_errmsg("is_parse_hdr: short read for header\n");
- free(hdr);
- return CL_EREAD; /* hdr must be within bounds, it's k to hard fail here */
- }
- } else {
- #if defined(HAVE_MMAP) && defined(HAVE_CLI_GETPAGESIZE)
- int psz = cli_getpagesize();
- off_t mp_hdr = (c->hdr / psz) * psz;
- mp_hdrsz = c->hdrsz + c->hdr - mp_hdr;
- if((map = mmap(NULL, mp_hdrsz, PROT_READ, MAP_PRIVATE, desc, mp_hdr))==MAP_FAILED) {
- cli_errmsg("is_parse_hdr: mmap failed\n");
- return CL_EMEM;
- }
- hdr = map + c->hdr - mp_hdr;
- #else
- cli_warnmsg("is_parse_hdr: hdr too big and mmap is not usable\n");
- return CL_CLEAN;
- #endif
- }
-
- h1 = (struct IS_HDR *)hdr;
- if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)h1), sizeof(*h1))) {
+ if(!(h1 = fmap_need_off(map, c->hdr, c->hdrsz))) {
cli_dbgmsg("is_parse_hdr: not enough room for H1\n");
- IS_FREE_HDR;
return CL_CLEAN;
}
+ hdr = (char *)h1;
h1_data_off = le32_to_host(h1->data_off);
- objs = (struct IS_OBJECTS *)(hdr + h1_data_off);
- if(!CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)objs), sizeof(*objs))) {
- cli_dbgmsg("is_parse_hdr: not enough room for OBJECTS\n");
- IS_FREE_HDR;
- return CL_CLEAN;
+ objs = (struct IS_OBJECTS *)fmap_need_ptr(map, hdr + h1_data_off, sizeof(*objs));
+ if(!objs) {
+ cli_dbgmsg("is_parse_hdr: not enough room for OBJECTS\n");
+ funmap(map);
+ return CL_CLEAN;
}
cli_dbgmsg("is_parse_hdr: magic %x, unk1 %x, unk2 %x, data_off %x, data_sz %x\n",
- h1->magic, h1->unk1, h1->unk2, h1_data_off, h1->data_sz);
+ h1->magic, h1->unk1, h1->unk2, h1_data_off, h1->data_sz);
if(le32_to_host(h1->magic) != 0x28635349) {
- cli_dbgmsg("is_parse_hdr: bad magic. wrong version?\n");
- IS_FREE_HDR;
- return CL_CLEAN;
+ cli_dbgmsg("is_parse_hdr: bad magic. wrong version?\n");
+ funmap(map);
+ return CL_CLEAN;
}
+ fmap_unneed_ptr(map, h1, sizeof(*h1));
+
/* cli_errmsg("COMPONENTS\n"); */
/* off = le32_to_host(objs->comps_off) + h1_data_off; */
/* for(i=1; ; i++) { */
@@@ -583,11 -551,12 +550,12 @@@
objs_files_cnt = le32_to_host(objs->files_cnt);
off = h1_data_off + objs_dirs_off + le32_to_host(objs->dir_sz2);
+ fmap_unneed_ptr(map, objs, sizeof(*objs));
for(i=0; i<objs_files_cnt ;i++) {
- struct IS_FILEITEM *file = (struct IS_FILEITEM *)(&hdr[off]);
+ struct IS_FILEITEM *file = (struct IS_FILEITEM *)fmap_need_off(map, c->hdr + off, sizeof(*file));
- if(CLI_ISCONTAINED(hdr, c->hdrsz, ((char *)file), sizeof(*file))) {
- const char *dir_name = "", *file_name = "";
+ if(file) {
+ const char *emptyname = "", *dir_name = emptyname, *file_name = emptyname;
uint32_t dir_rel = h1_data_off + objs_dirs_off + 4 * le32_to_host(file->dir_id); /* rel off of dir entry from array of rel ptrs */
uint32_t file_rel = objs_dirs_off + h1_data_off + le32_to_host(file->str_name_off); /* rel off of fname */
uint64_t file_stream_off, file_size, file_csize;
@@@ -595,12 -564,12 +563,12 @@@
memcpy(hash, file->md5, 16);
md5str((uint8_t *)hash);
- if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[dir_rel], 4)) {
+ if(fmap_need_ptr_once(map, &hdr[dir_rel], 4)) {
dir_rel = cli_readint32(&hdr[dir_rel]) + h1_data_off + objs_dirs_off;
- if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[dir_rel], 1) && memchr(&hdr[dir_rel], 0, c->hdrsz - dir_rel))
+ if(fmap_need_str(map, &hdr[dir_rel], c->hdrsz - dir_rel))
dir_name = &hdr[dir_rel];
}
- if(CLI_ISCONTAINED(hdr, c->hdrsz, &hdr[file_rel], 1) && memchr(&hdr[file_rel], 0, c->hdrsz - file_rel))
+ if(fmap_need_str(map, &hdr[file_rel], c->hdrsz - file_rel))
file_name = &hdr[file_rel];
file_stream_off = le64_to_host(file->stream_off);
@@@ -640,10 -609,13 +608,13 @@@
scanned++;
if (ctx->engine->maxfiles && scanned >= ctx->engine->maxfiles) {
cli_dbgmsg("is_parse_hdr: File limit reached (max: %u)\n", ctx->engine->maxfiles);
- IS_FREE_HDR;
+ if(file_name != emptyname)
+ fmap_unneed_ptr(map, (void *)file_name, strlen(file_name)+1);
+ if(dir_name != emptyname)
+ fmap_unneed_ptr(map, (void *)dir_name, strlen(dir_name)+1);
return CL_EMAXFILES;
}
- cabret = is_extract_cab(desc, ctx, file_stream_off + c->cabs[j].off, file_size, file_csize);
+ cabret = is_extract_cab(ctx, file_stream_off + c->cabs[j].off, file_size, file_csize);
} else {
ret = CL_CLEAN;
cli_dbgmsg("is_parse_hdr: stream out of file\n");
@@@ -657,7 -629,10 +628,10 @@@
cabret = CL_CLEAN;
}
if(cabret != CL_CLEAN) {
- IS_FREE_HDR;
+ if(file_name != emptyname)
+ fmap_unneed_ptr(map, (void *)file_name, strlen(file_name)+1);
+ if(dir_name != emptyname)
+ fmap_unneed_ptr(map, (void *)dir_name, strlen(dir_name)+1);
return cabret;
}
} else {
@@@ -668,13 -643,17 +642,17 @@@
default:
cli_dbgmsg("is_parse_hdr: skipped unknown file entry %u\n", i);
}
+ if(file_name != emptyname)
+ fmap_unneed_ptr(map, (void *)file_name, strlen(file_name)+1);
+ if(dir_name != emptyname)
+ fmap_unneed_ptr(map, (void *)dir_name, strlen(dir_name)+1);
+ fmap_unneed_ptr(map, file, sizeof(*file));
} else {
ret = CL_CLEAN;
cli_dbgmsg("is_parse_hdr: FILEITEM out of bounds\n");
}
off += sizeof(*file);
}
- IS_FREE_HDR;
return ret;
}
@@@ -694,55 -673,25 +672,25 @@@ static void md5str(uint8_t *sum)
#define IS_CABBUFSZ 65536
- static int is_extract_cab(int desc, cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize) {
+ static int is_extract_cab(cli_ctx *ctx, uint64_t off, uint64_t size, uint64_t csize) {
uint8_t *inbuf, *outbuf;
char *tempfile;
- FILE *in;
int ofd, ret = CL_CLEAN;
z_stream z;
uint64_t outsz = 0;
int success = 0;
+ fmap_t *map = *ctx->fmap;
- if((ofd=dup(desc)) < 0) {
- cli_errmsg("is_extract_cab: dup failed\n");
- return CL_EDUP;
- }
- if(!(in = fdopen(ofd, "rb"))) {
- cli_errmsg("is_extract_cab: fdopen failed\n");
- close(ofd);
- return CL_EOPEN;
- }
- #if HAVE_FSEEKO
- if(fseeko(in, (off_t)off, SEEK_SET))
- #else
- if(fseek(in, (long)off, SEEK_SET))
- #endif
- {
- cli_dbgmsg("is_extract_cab: fseek failed\n");
- fclose(in);
- return CL_ESEEK;
- }
- if(!(inbuf = cli_malloc(IS_CABBUFSZ))) {
- fclose(in);
- return CL_EMEM;
- }
- if(!(outbuf = cli_malloc(IS_CABBUFSZ))) {
- free(inbuf);
- fclose(in);
+ if(!(outbuf = cli_malloc(IS_CABBUFSZ)))
return CL_EMEM;
- }
+
if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) {
- free(inbuf);
free(outbuf);
- fclose(in);
- return CL_EMEM;
}
if((ofd = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
cli_errmsg("is_extract_cab: failed to create file %s\n", tempfile);
free(tempfile);
- free(inbuf);
free(outbuf);
- fclose(in);
return CL_ECREAT;
}
@@@ -754,11 -703,12 +702,12 @@@
break;
}
csize -= 2;
- if(!fread(outbuf, 2, 1, in)) {
+ if(!(inbuf = fmap_need_off_once(map, off, 2))) {
cli_dbgmsg("is_extract_cab: short read for chunk size\n");
break;
}
- chunksz = outbuf[0] | (outbuf[1] << 8);
+ off += 2;
+ chunksz = inbuf[0] | (inbuf[1] << 8);
if(!chunksz) {
cli_dbgmsg("is_extract_cab: zero sized chunk\n");
continue;
@@@ -768,10 -718,11 +717,11 @@@
break;
}
csize -= chunksz;
- if(!fread(inbuf, chunksz, 1, in)) {
+ if(!(inbuf = fmap_need_off_once(map, off, chunksz))) {
cli_dbgmsg("is_extract_cab: short read for chunk\n");
break;
}
+ off += chunksz;
memset(&z, 0, sizeof(z));
inflateInit2(&z, -MAX_WBITS);
z.next_in = (uint8_t *)inbuf;
@@@ -804,8 -755,6 +754,6 @@@
inflateEnd(&z);
if(!success) break;
}
- fclose(in);
- free(inbuf);
free(outbuf);
if(success) {
if (outsz != size)
diff --combined libclamav/libclamav.map
index 0654dbc,dba0127..5da8320
--- a/libclamav/libclamav.map
+++ b/libclamav/libclamav.map
@@@ -32,7 -32,6 +32,7 @@@ CLAMAV_PUBLIC
};
CLAMAV_PRIVATE {
global:
+ cli_gettmpdir;
cli_strtok;
cli_strtokenize;
cli_cvdunpack;
@@@ -63,7 -62,7 +63,7 @@@
cli_str2hex;
cli_md5file;
cli_md5stream;
- html_normalise_fd;
+ html_normalise_map;
cli_utf16toascii;
cli_malloc;
@@@ -156,6 -155,8 +156,8 @@@
cli_bytecode_context_setparam_ptr;
cli_bytecode_context_getresult_int;
cli_bytecode_context_clear;
+ fmap;
+ funmap;
local:
*;
};
diff --combined libclamav/macho.c
index a158ae9,5caeed6..5a1e43d
--- a/libclamav/macho.c
+++ b/libclamav/macho.c
@@@ -176,7 -176,7 +176,7 @@@ struct macho_fat_arc
if(DETECT_BROKEN) { \
if(ctx->virname) \
*ctx->virname = "Broken.Executable"; \
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS; \
+ return CL_VIRUS; \
} \
return CL_EFORMAT
@@@ -201,7 -201,7 +201,7 @@@ static uint32_t cli_rawaddr(uint32_t va
return vaddr - sects[i].rva + sects[i].raw;
}
- int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo)
+ int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo)
{
struct macho_hdr hdr;
struct macho_load_cmd load_cmd;
@@@ -213,14 -213,17 +213,17 @@@
unsigned int arch = 0, ep = 0, err;
struct cli_exe_section *sections = NULL;
char name[16];
+ fmap_t *map = *ctx->fmap;
+ ssize_t at;
if(fileinfo)
matcher = 1;
- if(read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ if(fmap_readn(map, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) {
cli_dbgmsg("cli_scanmacho: Can't read header\n");
return matcher ? -1 : CL_EFORMAT;
}
+ at = sizeof(hdr);
if(hdr.magic == 0xfeedface) {
conv = 0;
@@@ -311,7 -314,7 +314,7 @@@
}
if(m64)
- lseek(fd, 4, SEEK_CUR);
+ at += 4;
hdr.ncmds = EC32(hdr.ncmds, conv);
if(!hdr.ncmds || hdr.ncmds > 1024) {
@@@ -320,11 -323,12 +323,12 @@@
}
for(i = 0; i < hdr.ncmds; i++) {
- if(read(fd, &load_cmd, sizeof(load_cmd)) != sizeof(load_cmd)) {
+ if(fmap_readn(map, &load_cmd, at, sizeof(load_cmd)) != sizeof(load_cmd)) {
cli_dbgmsg("cli_scanmacho: Can't read load command\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(load_cmd);
/*
if((m64 && EC32(load_cmd.cmdsize, conv) % 8) || (!m64 && EC32(load_cmd.cmdsize, conv) % 4)) {
cli_dbgmsg("cli_scanmacho: Invalid command size (%u)\n", EC32(load_cmd.cmdsize, conv));
@@@ -335,19 -339,21 +339,21 @@@
load_cmd.cmd = EC32(load_cmd.cmd, conv);
if((m64 && load_cmd.cmd == 0x19) || (!m64 && load_cmd.cmd == 0x01)) { /* LC_SEGMENT */
if(m64) {
- if(read(fd, &segment_cmd64, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
+ if(fmap_readn(map, &segment_cmd64, at, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) {
cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(segment_cmd64);
nsects = EC32(segment_cmd64.nsects, conv);
strncpy(name, segment_cmd64.segname, 16);
} else {
- if(read(fd, &segment_cmd, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
+ if(fmap_readn(map, &segment_cmd, at, sizeof(segment_cmd)) != sizeof(segment_cmd)) {
cli_dbgmsg("cli_scanmacho: Can't read segment command\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(segment_cmd);
nsects = EC32(segment_cmd.nsects, conv);
strncpy(name, segment_cmd.segname, 16);
}
@@@ -374,11 -380,12 +380,12 @@@
for(j = 0; j < nsects; j++) {
if(m64) {
- if(read(fd, §ion64, sizeof(section64)) != sizeof(section64)) {
+ if(fmap_readn(map, §ion64, at, sizeof(section64)) != sizeof(section64)) {
cli_dbgmsg("cli_scanmacho: Can't read section\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(section64);
sections[sect].rva = EC64(section64.addr, conv);
sections[sect].vsz = EC64(section64.size, conv);
sections[sect].raw = EC32(section64.offset, conv);
@@@ -386,11 -393,12 +393,12 @@@
sections[sect].rsz = sections[sect].vsz + (section64.align - (sections[sect].vsz % section64.align)) % section64.align; /* most likely we can assume it's the same as .vsz */
strncpy(name, section64.sectname, 16);
} else {
- if(read(fd, §ion, sizeof(section)) != sizeof(section)) {
+ if(fmap_readn(map, §ion, at, sizeof(section)) != sizeof(section)) {
cli_dbgmsg("cli_scanmacho: Can't read section\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(section);
sections[sect].rva = EC32(section.addr, conv);
sections[sect].vsz = EC32(section.size, conv);
sections[sect].raw = EC32(section.offset, conv);
@@@ -414,17 -422,18 +422,18 @@@
cli_dbgmsg("MACHO: ------------------\n");
} else if(arch && (load_cmd.cmd == 0x4 || load_cmd.cmd == 0x5)) { /* LC_(UNIX)THREAD */
- lseek(fd, 8, SEEK_CUR);
+ at += 8;
switch(arch) {
case 1: /* x86 */
{
struct macho_thread_state_x86 thread_state_x86;
- if(read(fd, &thread_state_x86, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) {
+ if(fmap_readn(map, &thread_state_x86, at, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) {
cli_dbgmsg("cli_scanmacho: Can't read thread_state_x86\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(thread_state_x86);
break;
}
@@@ -432,11 -441,12 +441,12 @@@
{
struct macho_thread_state_ppc thread_state_ppc;
- if(read(fd, &thread_state_ppc, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) {
+ if(fmap_readn(map, &thread_state_ppc, at, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) {
cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(thread_state_ppc);
ep = EC32(thread_state_ppc.srr0, conv);
break;
}
@@@ -445,11 -455,12 +455,12 @@@
{
struct macho_thread_state_ppc64 thread_state_ppc64;
- if(read(fd, &thread_state_ppc64, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) {
+ if(fmap_readn(map, &thread_state_ppc64, at, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) {
cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc64\n");
free(sections);
RETURN_BROKEN;
}
+ at += sizeof(thread_state_ppc64);
ep = EC64(thread_state_ppc64.srr0, conv);
break;
}
@@@ -460,7 -471,7 +471,7 @@@
}
} else {
if(EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd))
- lseek(fd, EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd), SEEK_CUR);
+ at += EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd);
}
}
@@@ -490,12 -501,14 +501,14 @@@
}
}
- int cli_machoheader(int fd, struct cli_exe_info *fileinfo)
+ int cli_machoheader(fmap_t *map, struct cli_exe_info *fileinfo)
{
- return cli_scanmacho(fd, NULL, fileinfo);
+ cli_ctx ctx;
+ ctx.fmap = ↦
+ return cli_scanmacho(&ctx, fileinfo);
}
- int cli_scanmacho_unibin(int fd, cli_ctx *ctx)
+ int cli_scanmacho_unibin(cli_ctx *ctx)
{
struct macho_fat_header fat_header;
struct macho_fat_arch fat_arch;
@@@ -503,16 -516,14 +516,14 @@@
int ret = CL_CLEAN;
struct stat sb;
off_t pos;
+ fmap_t *map = *ctx->fmap;
+ ssize_t at;
- if(fstat(fd, &sb) == -1) {
- cli_dbgmsg("cli_scanmacho_unibin: fstat failed for fd %d\n", fd);
- return CL_ESTAT;
- }
-
- if(read(fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header)) {
+ if(fmap_readn(map, &fat_header, 0, sizeof(fat_header)) != sizeof(fat_header)) {
cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_header\n");
return CL_EFORMAT;
}
+ at = sizeof(fat_header);
if(fat_header.magic == 0xcafebabe) {
conv = 0;
@@@ -533,18 -544,17 +544,17 @@@
}
cli_dbgmsg("UNIBIN: Number of architectures: %u\n", (unsigned int) fat_header.nfats);
for(i = 0; i < fat_header.nfats; i++) {
- if(read(fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch)) {
+ if(fmap_readn(map, &fat_arch, at, sizeof(fat_arch)) != sizeof(fat_arch)) {
cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_arch\n");
RETURN_BROKEN;
}
- pos = lseek(fd, 0, SEEK_CUR);
+ at += sizeof(fat_arch);
fat_arch.offset = EC32(fat_arch.offset, conv);
fat_arch.size = EC32(fat_arch.size, conv);
cli_dbgmsg("UNIBIN: Binary %u of %u\n", i + 1, fat_header.nfats);
cli_dbgmsg("UNIBIN: File offset: %u\n", fat_arch.offset);
cli_dbgmsg("UNIBIN: File size: %u\n", fat_arch.size);
- ret = cli_dumpscan(fd, fat_arch.offset, fat_arch.size, ctx);
- lseek(fd, pos, SEEK_SET);
+ ret = cli_dumpscan(map->fd, fat_arch.offset, fat_arch.size, ctx);
if(ret == CL_VIRUS)
break;
}
diff --combined libclamav/matcher-ac.c
index f1a2537,5d0f64b..efe859e
--- a/libclamav/matcher-ac.c
+++ b/libclamav/matcher-ac.c
@@@ -47,36 -47,9 +47,36 @@@
#define AC_SPECIAL_ALT_CHAR 1
#define AC_SPECIAL_ALT_STR 2
-#define AC_SPECIAL_LINE_START 3
-#define AC_SPECIAL_LINE_END 4
-#define AC_SPECIAL_BOUNDARY 5
+#define AC_SPECIAL_LINE_MARKER 3
+#define AC_SPECIAL_BOUNDARY 4
+
+#define AC_BOUNDARY_LEFT 1
+#define AC_BOUNDARY_LEFT_NEGATIVE 2
+#define AC_BOUNDARY_RIGHT 4
+#define AC_BOUNDARY_RIGHT_NEGATIVE 8
+#define AC_LINE_MARKER_LEFT 16
+#define AC_LINE_MARKER_LEFT_NEGATIVE 32
+#define AC_LINE_MARKER_RIGHT 64
+#define AC_LINE_MARKER_RIGHT_NEGATIVE 128
+
+static char boundary[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 1, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
{
@@@ -724,17 -697,8 +724,17 @@@ int cli_ac_chklsig(const char *expr, co
} \
break; \
\
+ case AC_SPECIAL_LINE_MARKER: \
+ if(b == '\n') { \
+ match = !special->negative; \
+ } else if(b == '\r' && (bp + 1 < length && buffer[bp + 1] == '\n')) { \
+ bp++; \
+ match = !special->negative; \
+ } \
+ break; \
+ \
case AC_SPECIAL_BOUNDARY: \
- if(memchr("\x22\x27\x20\x2f\x3d\x2d\x5f\x3e\x0a\x0d", b, 10)) \
+ if(boundary[b]) \
match = !special->negative; \
break; \
\
@@@ -760,7 -724,7 +760,7 @@@
match = 0; \
}
-inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
+inline static int ac_findmatch(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t *end)
{
uint32_t bp, match;
uint16_t wc, i, j, specialcnt = pattern->special_pattern;
@@@ -781,38 -745,6 +781,38 @@@
}
*end = bp;
+ if(pattern->boundary & AC_BOUNDARY_LEFT) {
+ match = !!(pattern->boundary & AC_BOUNDARY_LEFT_NEGATIVE);
+ if(!fileoffset || (offset && (boundary[buffer[offset - 1]] == 1 || boundary[buffer[offset - 1]] == 3)))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
+ if(pattern->boundary & AC_BOUNDARY_RIGHT) {
+ match = !!(pattern->boundary & AC_BOUNDARY_RIGHT_NEGATIVE);
+ if((length <= SCANBUFF) && (bp == length || boundary[buffer[bp]] >= 2))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
+ if(pattern->boundary & AC_LINE_MARKER_LEFT) {
+ match = !!(pattern->boundary & AC_LINE_MARKER_LEFT_NEGATIVE);
+ if(!fileoffset || (offset && (buffer[offset - 1] == '\n')))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
+ if(pattern->boundary & AC_LINE_MARKER_RIGHT) {
+ match = !!(pattern->boundary & AC_LINE_MARKER_RIGHT_NEGATIVE);
+ if((length <= SCANBUFF) && (bp == length || buffer[bp] == '\n' || (buffer[bp] == '\r' && bp + 1 < length && buffer[bp + 1] == '\n')))
+ match = !match;
+ if(!match)
+ return 0;
+ }
+
if(!(pattern->ch[1] & CLI_MATCH_IGNORE)) {
bp += pattern->ch_mindist[1];
for(i = pattern->ch_mindist[1]; i <= pattern->ch_maxdist[1]; i++) {
@@@ -922,28 -854,23 +922,23 @@@ 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, fmap_t *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);
@@@ -952,7 -879,7 +947,7 @@@
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;
@@@ -1032,7 -959,7 +1027,7 @@@ int cli_ac_scanbuff(const unsigned cha
if(!root->ac_root)
return CL_CLEAN;
- if(!mdata) {
+ if(!mdata && (root->ac_partsigs || root->ac_lsigs || root->ac_reloff_num)) {
cli_errmsg("cli_ac_scanbuff: mdata == NULL\n");
return CL_ENULLARG;
}
@@@ -1069,7 -996,7 +1064,7 @@@
}
}
pt = patt;
- if(ac_findmatch(buffer, bp, length, patt, &matchend)) {
+ if(ac_findmatch(buffer, bp, offset + bp - patt->prefix_length, length, patt, &matchend)) {
while(pt) {
if((pt->type && !(mode & AC_SCAN_FT)) || (!pt->type && !(mode & AC_SCAN_VIR))) {
pt = pt->next_same;
@@@ -1171,7 -1098,7 +1166,7 @@@
} else { /* !pt->type */
if(pt->lsigid[0]) {
mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
- pt = pt->next;
+ pt = pt->next_same;
continue;
}
@@@ -1184,7 -1111,7 +1179,7 @@@
newres->next = *res;
*res = newres;
- pt = pt->next;
+ pt = pt->next_same;
continue;
} else {
if(virname)
@@@ -1213,7 -1140,7 +1208,7 @@@
} else {
if(pt->lsigid[0]) {
mdata->lsigcnt[pt->lsigid[1]][pt->lsigid[2]]++;
- pt = pt->next;
+ pt = pt->next_same;
continue;
}
@@@ -1226,7 -1153,7 +1221,7 @@@
newres->next = *res;
*res = newres;
- pt = pt->next;
+ pt = pt->next_same;
continue;
} else {
if(virname)
@@@ -1408,6 -1335,7 +1403,6 @@@ int cli_ac_addsig(struct cli_matcher *r
}
}
strcat(hexnew, start);
- strcat(hexnew, "()");
if(!(start = strchr(pt, ')'))) {
mpool_free(root->mempool, newspecial);
@@@ -1420,37 -1348,6 +1415,37 @@@
error = CL_EMALFDB;
break;
}
+
+ if(!strcmp(pt, "B")) {
+ if(!*start) {
+ new->boundary |= AC_BOUNDARY_RIGHT;
+ if(newspecial->negative)
+ new->boundary |= AC_BOUNDARY_RIGHT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ } else if(pt - 1 == hexcpy) {
+ new->boundary |= AC_BOUNDARY_LEFT;
+ if(newspecial->negative)
+ new->boundary |= AC_BOUNDARY_LEFT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ }
+ } else if(!strcmp(pt, "L")) {
+ if(!*start) {
+ new->boundary |= AC_LINE_MARKER_RIGHT;
+ if(newspecial->negative)
+ new->boundary |= AC_LINE_MARKER_RIGHT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ } else if(pt - 1 == hexcpy) {
+ new->boundary |= AC_LINE_MARKER_LEFT;
+ if(newspecial->negative)
+ new->boundary |= AC_LINE_MARKER_LEFT_NEGATIVE;
+ mpool_free(root->mempool, newspecial);
+ continue;
+ }
+ }
+ strcat(hexnew, "()");
new->special++;
newtable = (struct cli_ac_special **) mpool_realloc(root->mempool, new->special_table, new->special * sizeof(struct cli_ac_special *));
if(!newtable) {
@@@ -1465,9 -1362,11 +1460,9 @@@
if(!strcmp(pt, "B")) {
newspecial->type = AC_SPECIAL_BOUNDARY;
- /* TODO
- } else if(strcmp(pt, "S")) {
- newspecial->type = AC_SPECIAL_LINE_START;
- } else if(strcmp(pt, "E")) {
- newspecial->type = AC_SPECIAL_LINE_END;
+ } else if(!strcmp(pt, "L")) {
+ newspecial->type = AC_SPECIAL_LINE_MARKER;
+ /*
} else if(strcmp(pt, "W")) {
newspecial->type = AC_SPECIAL_WHITE;
*/
@@@ -1638,7 -1537,7 +1633,7 @@@
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_special(root->mempool, new);
diff --combined libclamav/matcher-ac.h
index f18f3c6,1bc5bab..c69a701
--- a/libclamav/matcher-ac.h
+++ b/libclamav/matcher-ac.h
@@@ -25,6 -25,7 +25,7 @@@
#include "filetypes.h"
#include "cltypes.h"
+ #include "fmap.h"
#define AC_CH_MAXDIST 32
@@@ -61,7 -62,6 +62,7 @@@ struct cli_ac_patt
uint8_t depth;
uint16_t rtype, type;
uint32_t offdata[4], offset_min, offset_max;
+ uint32_t boundary;
};
struct cli_ac_node {
@@@ -87,7 -87,7 +88,7 @@@ void cli_ac_freedata(struct cli_ac_dat
int cli_ac_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, void **customdata, struct cli_ac_result **res, const struct cli_matcher *root, struct cli_ac_data *mdata, uint32_t offset, cli_file_t ftype, struct cli_matched_type **ftoffset, unsigned int mode, const cli_ctx *ctx);
int cli_ac_buildtrie(struct cli_matcher *root);
int cli_ac_init(struct cli_matcher *root, uint8_t mindepth, uint8_t maxdepth);
- 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, fmap_t *map);
void cli_ac_free(struct cli_matcher *root);
int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, uint32_t sigid, uint16_t parts, uint16_t partno, uint16_t rtype, uint16_t type, uint32_t mindist, uint32_t maxdist, const char *offset, const uint32_t *lsigid, unsigned int options);
diff --combined libclamav/matcher-bm.c
index 05de59d,b32727a..5c42164
--- 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;
}
@@@ -145,26 -145,21 +145,21 @@@ static int qcompare(const void *a, cons
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, fmap_t *map)
{
int ret;
unsigned int i;
struct cli_bm_patt *patt;
struct cli_target_info info;
if(!root->bm_patterns) {
- data->offtab = data->offset = 0;
+ data->offtab = data->offset = NULL;
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));
@@@ -183,7 -178,7 +178,7 @@@
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);
@@@ -243,7 -238,7 +238,7 @@@ void cli_bm_free(struct cli_matcher *ro
}
}
- int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, 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, fmap_t *map, struct cli_bm_off *offdata)
++int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata)
{
uint32_t i, j, off, off_min, off_max;
uint8_t found, pchain, shift;
@@@ -339,17 -334,10 +334,17 @@@
}
}
+ if(found && (p->boundary & BM_BOUNDARY_EOL)) {
+ if(off != length) {
+ p = p->next;
+ continue;
+ }
+ }
+
if(found && p->length + p->prefix_length == j) {
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)
@@@ -361,15 -349,13 +356,15 @@@
off_max = p->offset_max;
}
off = offset + i - p->prefix_length - BM_MIN_LENGTH + BM_BLOCK_SIZE;
- if(off_max < off || off_min > off) {
+ if(off_min == CLI_OFF_NONE || off_max < off || off_min > off) {
p = p->next;
continue;
}
}
if(virname)
*virname = p->virname;
+ if(patt)
+ *patt = p;
if(info.exeinfo.section)
free(info.exeinfo.section);
return CL_VIRUS;
diff --combined libclamav/matcher-bm.h
index 3996e98,a1ec133..6fe480f
--- a/libclamav/matcher-bm.h
+++ b/libclamav/matcher-bm.h
@@@ -24,9 -24,8 +24,10 @@@
#include "matcher.h"
#include "filetypes.h"
#include "cltypes.h"
+ #include "fmap.h"
+#define BM_BOUNDARY_EOL 1
+
struct cli_bm_patt {
unsigned char *pattern, *prefix;
char *virname;
@@@ -35,7 -34,6 +36,7 @@@
uint16_t length, prefix_length;
uint16_t cnt;
unsigned char pattern0;
+ uint32_t boundary, filesize;
};
struct cli_bm_off {
@@@ -44,9 -42,9 +45,9 @@@
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_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, fmap_t *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_bm_patt **patt, 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, fmap_t *map, struct cli_bm_off *offdata);
++int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata);
void cli_bm_free(struct cli_matcher *root);
#endif
diff --combined libclamav/matcher.c
index e0e0008,bd22558..d39dbf7
--- a/libclamav/matcher.c
+++ b/libclamav/matcher.c
@@@ -45,6 -45,7 +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)
{
@@@ -76,7 -77,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, NULL, troot, offset, -1, NULL)) != CL_VIRUS)
- if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, troot, offset, NULL, NULL)) != CL_VIRUS)
++ if(troot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, 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)
@@@ -89,7 -90,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, NULL, groot, offset, -1, NULL)) != CL_VIRUS)
- if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, groot, offset, NULL, NULL)) != CL_VIRUS)
++ if(groot->ac_only || (ret = cli_bm_scanbuff(buffer, length, virname, NULL, 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)
@@@ -104,15 -105,12 +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, fmap_t *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)(fmap_t *, 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) {
@@@ -208,14 -206,8 +206,8 @@@
}
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;
@@@ -229,22 -221,14 +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 = CLI_OFF_NONE;
if(offset_max)
*offset_max = CLI_OFF_NONE;
return CL_SUCCESS;
}
- lseek(fd, pos, SEEK_SET);
info->status = 1;
}
@@@ -277,12 -261,8 +261,12 @@@
return CL_EARG;
}
- if(offset_max && *offset_min != CLI_OFF_NONE)
- *offset_max = *offset_min + offdata[2];
+ if(offset_max) {
+ if(*offset_min != CLI_OFF_NONE)
+ *offset_max = *offset_min + offdata[2];
+ else
+ *offset_max = CLI_OFF_NONE;
+ }
}
return CL_SUCCESS;
@@@ -291,12 -271,8 +275,12 @@@
int cli_checkfp(int fd, cli_ctx *ctx)
{
unsigned char *digest;
+ char md5[33];
+ unsigned int i;
const char *virname;
off_t pos;
+ struct stat sb;
+ const struct cli_bm_patt *patt = NULL;
if((pos = lseek(fd, 0, SEEK_CUR)) == -1) {
@@@ -307,30 -283,18 +291,30 @@@
lseek(fd, 0, SEEK_SET);
if(ctx->engine->md5_fp) {
+ if(fstat(fd, &sb) == -1) {
+ cli_errmsg("cli_checkfp(): fstat(%d) failed\n", fd);
+ lseek(fd, pos, SEEK_SET);
+ return 0;
+ }
+
if(!(digest = cli_md5digest(fd))) {
cli_errmsg("cli_checkfp(): Can't generate MD5 checksum\n");
lseek(fd, pos, SEEK_SET);
return 0;
}
- if(cli_bm_scanbuff(digest, 16, &virname, &patt, ctx->engine->md5_fp, 0, -1, NULL) == CL_VIRUS && patt->filesize == sb.st_size) {
- if(cli_bm_scanbuff(digest, 16, &virname, ctx->engine->md5_fp, 0, NULL, NULL) == CL_VIRUS) {
++ if(cli_bm_scanbuff(digest, 16, &virname, &patt, ctx->engine->md5_fp, 0, NULL, NULL) == CL_VIRUS && patt->filesize == sb.st_size) {
cli_dbgmsg("cli_checkfp(): Found false positive detection (fp sig: %s)\n", virname);
free(digest);
lseek(fd, pos, SEEK_SET);
return 1;
}
+
+ for(i = 0; i < 16; i++)
+ sprintf(md5 + i * 2, "%02x", digest[i]);
+ md5[32] = 0;
+ cli_dbgmsg("FP SIGNATURE: %s:%u:%s\n", md5, (unsigned int) sb.st_size, *ctx->virname ? *ctx->virname : "Name");
+
free(digest);
}
@@@ -340,18 -304,31 +324,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;
+ fmap_t *map = *ctx->fmap;
+
+ if((*ctx->fmap = fmap(desc, 0, 0))) {
+ ret = cli_fmap_scandesc(ctx, ftype, ftonly, ftoffset, acmode);
+ funmap(*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, 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;
-
+ fmap_t *map = *ctx->fmap;
if(!ctx->engine) {
cli_errmsg("cli_scandesc: engine == NULL\n");
@@@ -382,34 -359,25 +379,25 @@@
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;
}
}
}
@@@ -417,78 -385,58 +405,50 @@@
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 = MIN(map->len - offset, SCANBUFF);
+ if(!(buff = fmap_need_off_once(map, offset, bytes)))
+ break;
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, NULL, 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)
++ if(troot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, NULL, 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) {
- free(buffer);
if(!ftonly)
cli_ac_freedata(&gdata);
cli_ac_freedata(&tdata);
if(bm_offmode)
cli_bm_freeoff(&toff);
-
- if(cli_checkfp(map->fd, ctx))
- return CL_CLEAN;
- else
- return CL_VIRUS;
+ return CL_VIRUS;
}
}
if(!ftonly) {
- if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, NULL, 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)
++ if(groot->ac_only || (ret = cli_bm_scanbuff(buff, bytes, ctx->virname, NULL, 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) {
cli_ac_freedata(&tdata);
if(bm_offmode)
cli_bm_freeoff(&toff);
}
- if(cli_checkfp(map->fd, ctx))
- return CL_CLEAN;
- else
- return CL_VIRUS;
-
+ return CL_VIRUS;
-
} else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
if(ret > type)
type = ret;
}
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 += bytes - maxpatlen;
}
- free(buffer);
-
if(troot) {
for(i = 0; i < troot->ac_lsigs; i++) {
evalcnt = 0;
@@@ -519,14 -467,17 +479,13 @@@
cli_ac_freedata(&gdata);
}
- if(ret == CL_VIRUS) {
- lseek(map->fd, 0, SEEK_SET);
- if(cli_checkfp(map->fd, ctx))
- return CL_CLEAN;
- else
- return CL_VIRUS;
- }
+ if(ret == CL_VIRUS)
+ return CL_VIRUS;
if(!ftonly && ctx->engine->md5_hdb) {
+ const struct cli_bm_patt *patt;
cli_md5_final(digest, &md5ctx);
- fstat(desc, &sb);
- if(cli_bm_scanbuff(digest, 16, ctx->virname, &patt, ctx->engine->md5_hdb, 0, -1, NULL) == CL_VIRUS && patt->filesize == sb.st_size && (cli_bm_scanbuff(digest, 16, NULL, &patt, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS || patt->filesize != sb.st_size))
- 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))
++ if(cli_bm_scanbuff(digest, 16, ctx->virname, &patt, ctx->engine->md5_hdb, 0, NULL, NULL) == CL_VIRUS && patt->filesize == map->len && (cli_bm_scanbuff(digest, 16, NULL, &patt, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS || patt->filesize != map->len))
return CL_VIRUS;
}
diff --combined libclamav/mbox.c
index ce768be,55823c5..e963515
--- a/libclamav/mbox.c
+++ b/libclamav/mbox.c
@@@ -20,6 -20,10 +20,6 @@@
static char const rcsid[] = "$Id: mbox.c,v 1.381 2007/02/15 12:26:44 njh Exp $";
-#ifdef _MSC_VER
-#include <winsock.h> /* only needed in CL_EXPERIMENTAL */
-#endif
-
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
@@@ -50,7 -54,9 +50,7 @@@
#include <sys/param.h>
#endif
#include "clamav.h"
-#ifndef C_WINDOWS
#include <dirent.h>
-#endif
#include <limits.h>
#include <signal.h>
@@@ -72,6 -78,7 +72,7 @@@
#include "mbox.h"
#include "dconf.h"
#include "md5.h"
+ #include "fmap.h"
#define DCONF_PHISHING mctx->ctx->dconf->phishing
@@@ -135,8 -142,7 +136,8 @@@ typedef enum
#include "phishcheck.h"
-#ifndef C_WINDOWS
+#ifndef _WIN32
+#include <sys/time.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@@ -146,7 -152,33 +147,7 @@@
#endif
#endif
-#ifndef C_WINDOWS
-#define closesocket(s) close(s)
-#define SOCKET int
-#endif
-
#include <fcntl.h>
-#ifndef C_WINDOWS
-#include <sys/time.h>
-#endif
-
-#ifndef HAVE_IN_PORT_T
-typedef unsigned short in_port_t;
-#endif
-
-#ifndef HAVE_IN_ADDR_T
-typedef unsigned int in_addr_t;
-#endif
-
-#if (!defined(EALREADY)) && (defined(WSAEALREADY))
-#define EALREADY WSAEALREADY
-#endif
-#if (!defined(EINPROGRESS)) && (defined(WSAEINPROGRESS))
-#define EINPROGRESS WSAEINPROGRESS
-#endif
-#if (!defined(EISCONN)) && (defined(WSAEISCONN))
-#define EISCONN WSAEISCONN
-#endif
/*
* Use CL_SCAN_PARTIAL_MESSAGE to handle messages covered by section 7.3.2 of RFC1341.
@@@ -186,7 -218,7 +187,7 @@@ typedef struct mbox_ctx
#endif
static int cli_parse_mbox(const char *dir, int desc, cli_ctx *ctx);
- static message *parseEmailFile(FILE *fin, const table_t *rfc821Table, const char *firstLine, const char *dir);
+ static message *parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821Table, const char *firstLine, const char *dir);
static message *parseEmailHeaders(message *m, const table_t *rfc821Table);
static int parseEmailHeader(message *m, const char *line, const table_t *rfc821Table);
static mbox_status parseEmailBody(message *messageIn, text *textIn, mbox_ctx *mctx, unsigned int recursion_level);
@@@ -201,7 -233,7 +202,7 @@@ static char *rfc2047(const char *in)
static char *rfc822comments(const char *in, char *out);
static int rfc1341(message *m, const char *dir);
static bool usefulHeader(int commandNumber, const char *cmd);
- static char *getline_from_mbox(char *buffer, size_t len, FILE *fin);
+ static char *getline_from_mbox(char *buffer, size_t len, fmap_t *map, size_t *at);
static bool isBounceStart(mbox_ctx *mctx, const char *line);
static bool exportBinhexMessage(mbox_ctx *mctx, message *m);
static int exportBounceMessage(mbox_ctx *ctx, text *start);
@@@ -300,774 -332,10 +301,6 @@@ static const struct tableinit
static pthread_mutex_t tables_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
- #ifdef NEW_WORLD
- #include "matcher.h"
- #undef PARTIAL_DIR
- #endif
-
- #ifdef NEW_WORLD
- /*
- * Files larger than this are scanned with the old method, should be
- * StreamMaxLength, I guess
- * If NW_MAX_FILE_SIZE is not defined, all files go through the
- * new method. This definition is for machines very tight on RAM, or
- * with large StreamMaxLength values
- */
- #define MAX_ALLOCATION 134217728 /* see libclamav/others.c */
- #define NW_MAX_FILE_SIZE MAX_ALLOCATION
-
- struct scanlist {
- const char *start;
- size_t size;
- encoding_type decoder; /* only BASE64 and QUOTEDPRINTABLE for now */
- struct scanlist *next;
- };
-
- static struct map {
- const char *offset; /* sorted */
- const char *word;
- struct map *next;
- } *map, *tail;
-
- static int save_text(cli_ctx *ctx, const char *dir, const char *start, size_t len);
- static void create_map(const char *begin, const char *end);
- static void add_to_map(const char *offset, const char *word);
- static const char *find_in_map(const char *offset, const char *word);
- static void free_map(void);
-
- /*
- * This could be the future. Instead of parsing and decoding it just decodes.
- *
- * USE IT AT YOUR PERIL, a large number of viruses are not detected with this
- * method, possibly because the decoded files must be exact and not have
- * extra data at the start or end, which this code will produce.
- *
- * Currently only supports base64 and quoted-printable
- *
- * You may also see a lot of warnings. For the moment it falls back to old
- * world mode if it doesn't know what to do - that'll be removed.
- * The code is untidy...
- *
- * FIXME: Some mailbox scans are slower with this method. I suspect that it's
- * because the scan can proceed to the end of the file rather than the end
- * of the attachment which can mean than later emails are scanned many times
- *
- * FIXME: quoted printable doesn't know when to stop, so size related virus
- * matching breaks
- *
- * TODO: Fall through to cli_parse_mbox() too often
- *
- * TODO: Add support for systems without mmap()
- *
- * TODO: partial_dir fall through
- *
- * FIXME: Some EICAR gets through
- */
- int
- cli_mbox(const char *dir, int desc, cli_ctx *ctx)
- {
- char *start, *ptr, *line;
- const char *last, *p, *q;
- size_t size;
- struct stat statb;
- message *m;
- fileblob *fb;
- int ret = CL_CLEAN;
- int wasAlloced;
- struct scanlist *scanlist, *scanelem;
-
- if(dir == NULL) {
- cli_dbgmsg("cli_mbox called with NULL dir\n");
- return CL_ENULLARG;
- }
- if(fstat(desc, &statb) < 0)
- return CL_EOPEN;
-
- size = statb.st_size;
-
- if(size == 0)
- return CL_CLEAN;
-
- #ifdef NW_MAX_FILE_SIZE
- if(size > NW_MAX_FILE_SIZE)
- return cli_parse_mbox(dir, desc, ctx);
- #endif
-
- /*cli_warnmsg("NEW_WORLD is new code - use at your own risk.\n");*/
- #ifdef PARTIAL_DIR
- cli_warnmsg("PARTIAL_DIR doesn't work in the NEW_WORLD yet\n");
- #endif
-
- start = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
- if(start == MAP_FAILED)
- return CL_EMAP;
-
- cli_dbgmsg("mmap'ed mbox\n");
-
- ptr = cli_malloc(size);
- if(ptr) {
- memcpy(ptr, start, size);
- munmap(start, size);
- start = ptr;
- wasAlloced = 1;
- } else
- wasAlloced = 0;
-
- /* last points to the last *valid* address in the array */
- last = &start[size - 1];
-
- create_map(start, last);
-
- scanelem = scanlist = NULL;
- q = start;
- /*
- * FIXME: mismatch of const char * and char * here and in later calls
- * to find_in_map()
- */
- while((p = find_in_map(q, "base64")) != NULL) {
- cli_dbgmsg("Found base64\n");
- if(scanelem) {
- scanelem->next = cli_malloc(sizeof(struct scanlist));
- scanelem = scanelem->next;
- } else
- scanlist = scanelem = cli_malloc(sizeof(struct scanlist));
- scanelem->next = NULL;
- scanelem->decoder = BASE64;
- q = scanelem->start = &p[6];
- if(((p = find_in_map(q, "\nFrom ")) != NULL) ||
- ((p = find_in_map(q, "base64")) != NULL) ||
- ((p = find_in_map(q, "quoted-printable")) != NULL)) {
- scanelem->size = (size_t)(p - q);
- q = p;
- } else {
- scanelem->size = (size_t)(last - scanelem->start) + 1;
- break;
- }
- cli_dbgmsg("base64: last %u q %u\n", (unsigned int)last, (unsigned int)q);
- assert(scanelem->size <= size);
- }
-
- q = start;
- while((p = find_in_map(q, "quoted-printable")) != NULL) {
- if(p != q)
- switch(p[-1]) {
- case ' ':
- case ':':
- case '=': /* wrong but allow it */
- break;
- default:
- q = &p[16];
- cli_dbgmsg("Ignore quoted-printable false positive\n");
- continue; /* false positive */
- }
-
- cli_dbgmsg("Found quoted-printable\n");
- #ifdef notdef
- /*
- * The problem with quoted printable is recognising when to stop
- * parsing
- */
- if(scanelem) {
- scanelem->next = cli_malloc(sizeof(struct scanlist));
- scanelem = scanelem->next;
- } else
- scanlist = scanelem = cli_malloc(sizeof(struct scanlist));
- scanelem->next = NULL;
- scanelem->decoder = QUOTEDPRINTABLE;
- q = scanelem->start = &p[16];
- cli_dbgmsg("qp: last %u q %u\n", (unsigned int)last, (unsigned int)q);
- if(((p = find_in_map(q, "\nFrom ")) != NULL) ||
- ((p = find_in_map(q, "quoted-printable")) != NULL) ||
- ((p = find_in_map(q, "base64")) != NULL)) {
- scanelem->size = (size_t)(p - q);
- q = p;
- cli_dbgmsg("qp: scanelem->size = %u\n", scanelem->size);
- } else {
- scanelem->size = (size_t)(last - scanelem->start) + 1;
- break;
- }
- assert(scanelem->size <= size);
- #else
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
-
- free_map();
- return cli_parse_mbox(dir, desc, ctx);
- #endif
- }
-
- if(scanlist == NULL) {
- const struct tableinit *tableinit;
- bool anyHeadersFound = FALSE;
- bool hasuuencode = FALSE;
- cli_file_t type;
-
- /* FIXME: message: There could of course be no decoder needed... */
- for(tableinit = rfc821headers; tableinit->key; tableinit++)
- if(find_in_map(start, tableinit->key)) {
- anyHeadersFound = TRUE;
- break;
- }
-
- if((!anyHeadersFound) &&
- ((p = find_in_map(start, "\nbegin ")) != NULL) &&
- (isuuencodebegin(++p)))
- /* uuencoded part */
- hasuuencode = TRUE;
- else {
- cli_dbgmsg("Nothing encoded, looking for a text part to save\n");
- ret = save_text(ctx, dir, start, size);
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
-
- free_map();
- if(ret != CL_EFORMAT)
- return ret;
- ret = CL_CLEAN;
- }
-
- free_map();
-
- type = cli_filetype(start, size, ctx->engine);
-
- if((type == CL_TYPE_TEXT_ASCII) &&
- (strncmp(start, "Microsoft Mail Internet Headers", 31) == 0))
- type = CL_TYPE_MAIL;
-
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
-
- if(anyHeadersFound || hasuuencode) {
- /* TODO: reduce the number of falls through here */
- if(hasuuencode)
- /* TODO: fast track visa */
- cli_dbgmsg("New world - fall back to old uudecoder\n");
- else
- cli_dbgmsg("cli_mbox: unknown encoder, type %d\n", type);
- if(type == CL_TYPE_MAIL)
- return cli_parse_mbox(dir, desc, ctx);
- cli_dbgmsg("Unknown filetype %d, return CLEAN\n", type);
- return CL_CLEAN;
- }
-
- #if 0 /* I don't believe this is needed any more */
- /*
- * The message could be a plain text phish
- * FIXME: Can't get to the option whether we are looking for
- * phishes or not, so assume we are, this slows things a
- * lot
- * Should be
- * if((type == CL_TYPE_MAIL) && (!(no-phishing))
- */
- if(type == CL_TYPE_MAIL)
- return cli_parse_mbox(dir, desc, ctx);
- #endif
- cli_dbgmsg("cli_mbox: I believe it's plain text (type == %d) which must be clean\n",
- type);
- return CL_CLEAN;
- }
- #if 0
- if(wasAlloced) {
- const char *max = NULL;
-
- for(scanelem = scanlist; scanelem; scanelem = scanelem->next) {
- const char *end = &scanelem->start[scanelem->size];
-
- if(end > max)
- max = end;
- }
-
- if(max < last)
- printf("could free %d bytes\n", (int)(last - max));
- }
- #endif
-
- for(scanelem = scanlist; scanelem; scanelem = scanelem->next) {
- if(scanelem->decoder == BASE64) {
- const char *b64start = scanelem->start;
- size_t b64size = scanelem->size;
-
- cli_dbgmsg("b64size = %lu\n", b64size);
- while((*b64start != '\n') && (*b64start != '\r')) {
- b64start++;
- b64size--;
- }
- /*
- * Look for the end of the headers
- */
- while(b64start < last) {
- if(*b64start == ';') {
- b64start++;
- b64size--;
- } else if((memcmp(b64start, "\n\n", 2) == 0) ||
- (memcmp(b64start, "\r\r", 2) == 0)) {
- b64start += 2;
- b64size -= 2;
- break;
- } else if(memcmp(b64start, "\r\n\r\n", 4) == 0) {
- b64start += 4;
- b64size -= 4;
- break;
- } else if(memcmp(b64start, "\n \n", 3) == 0) {
- /*
- * Some viruses are broken and have
- * one space character at the end of
- * the headers
- */
- b64start += 3;
- b64size -= 3;
- break;
- } else if(memcmp(b64start, "\r\n \r\n", 5) == 0) {
- /*
- * Some viruses are broken and have
- * one space character at the end of
- * the headers
- */
- b64start += 5;
- b64size -= 5;
- break;
- }
- b64start++;
- b64size--;
- }
-
- if(b64size > 0L)
- while((!isalnum(*b64start)) && (*b64start != '/')) {
- if(b64size-- == 0L)
- break;
- b64start++;
- }
-
- if(b64size > 0L) {
- int lastline;
- char *tmpfilename;
- unsigned char *uptr;
-
- cli_dbgmsg("cli_mbox: decoding %ld base64 bytes\n", b64size);
- if((fb = fileblobCreate()) == NULL) {
- free_map();
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
-
- return CL_EMEM;
- }
-
- tmpfilename = cli_gentemp(dir);
- if(tmpfilename == NULL) {
- free_map();
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
- fileblobDestroy(fb);
-
- return CL_EMEM;
- }
- fileblobSetFilename(fb, dir, tmpfilename);
- free(tmpfilename);
-
- line = NULL;
-
- m = messageCreate();
- if(m == NULL) {
- free_map();
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
- fileblobDestroy(fb);
-
- return CL_EMEM;
- }
- messageSetEncoding(m, "base64");
-
- messageSetCTX(m, ctx);
- fileblobSetCTX(fb, ctx);
-
- lastline = 0;
- do {
- int length = 0, datalen;
- char *newline, *equal;
- unsigned char *bigbuf, *data;
- unsigned char smallbuf[1024];
- const char *cptr;
-
- /*printf("%ld: ", b64size); fflush(stdout);*/
-
- for(cptr = b64start; b64size && (*cptr != '\n') && (*cptr != '\r'); cptr++) {
- length++;
- --b64size;
- }
-
- /*printf("%d: ", length); fflush(stdout);*/
-
- newline = cli_realloc(line, length + 1);
- if(newline == NULL)
- break;
- line = newline;
-
- memcpy(line, b64start, length);
- line[length] = '\0';
-
- equal = strchr(line, '=');
- if(equal) {
- lastline++;
- *equal = '\0';
- }
- /*puts(line);*/
-
- #if 0
- if(messageAddStr(m, line) < 0)
- break;
- #endif
- if(length >= (int)sizeof(smallbuf)) {
- datalen = length + 2;
- data = bigbuf = cli_malloc(datalen);
- if(data == NULL)
- break;
- } else {
- bigbuf = NULL;
- data = smallbuf;
- datalen = sizeof(data) - 1;
- }
- uptr = decodeLine(m, BASE64, line, data, datalen);
-
- if(uptr == NULL) {
- if(bigbuf)
- free(bigbuf);
- break;
- }
- /*cli_dbgmsg("base64: write %u bytes\n", (size_t)(uptr - data));*/
- datalen = fileblobAddData(fb, data, (size_t)(uptr - data));
- if(bigbuf)
- free(bigbuf);
-
- if(datalen < 0)
- break;
- if(fileblobContainsVirus(fb))
- break;
-
- if((b64size > 0) && (*cptr == '\r')) {
- b64start = ++cptr;
- --b64size;
- }
- if((b64size > 0) && (*cptr == '\n')) {
- b64start = ++cptr;
- --b64size;
- }
- if(lastline)
- break;
- } while(b64size > 0L);
-
- if(m->base64chars) {
- unsigned char data[4];
-
- uptr = base64Flush(m, data);
- if(uptr) {
- /*cli_dbgmsg("base64: flush %u bytes\n", (size_t)(uptr - data));*/
- (void)fileblobAddData(fb, data, (size_t)(uptr - data));
- }
- }
- if(fb)
- fileblobDestroy(fb);
- else
- ret = -1;
-
- messageDestroy(m);
- free(line);
- }
- } else if(scanelem->decoder == QUOTEDPRINTABLE) {
- const char *quotedstart = scanelem->start;
- size_t quotedsize = scanelem->size;
-
- cli_dbgmsg("quotedsize = %lu\n", quotedsize);
- while(*quotedstart != '\n') {
- quotedstart++;
- quotedsize--;
- }
- /*
- * Look for the end of the headers
- */
- while(quotedstart < last) {
- if(*quotedstart == ';') {
- quotedstart++;
- quotedsize--;
- } else if((*quotedstart == '\n') || (*quotedstart == '\r')) {
- quotedstart++;
- quotedsize--;
- if((*quotedstart == '\n') || (*quotedstart == '\r')) {
- quotedstart++;
- quotedsize--;
- break;
- }
- }
- quotedstart++;
- quotedsize--;
- }
-
- while(!isalnum(*quotedstart)) {
- quotedstart++;
- quotedsize--;
- }
-
- if(quotedsize > 0L) {
- cli_dbgmsg("cli_mbox: decoding %ld quoted-printable bytes\n", quotedsize);
-
- m = messageCreate();
- if(m == NULL) {
- free_map();
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
-
- return CL_EMEM;
- }
- messageSetEncoding(m, "quoted-printable");
- messageSetCTX(m, ctx);
-
- line = NULL;
-
- do {
- int length = 0;
- char *newline;
- const char *cptr;
-
- /*printf("%ld: ", quotedsize); fflush(stdout);*/
-
- for(cptr = quotedstart; quotedsize && (*cptr != '\n') && (*cptr != '\r'); cptr++) {
- length++;
- --quotedsize;
- }
-
- /*printf("%d: ", length); fflush(stdout);*/
-
- newline = cli_realloc(line, length + 1);
- if(newline == NULL)
- break;
- line = newline;
-
- memcpy(line, quotedstart, length);
- line[length] = '\0';
-
- /*puts(line);*/
-
- if(messageAddStr(m, line) < 0)
- break;
-
- if((quotedsize > 0) && (*cptr == '\r')) {
- quotedstart = ++cptr;
- --quotedsize;
- }
- if((quotedsize > 0) && (*cptr == '\n')) {
- quotedstart = ++cptr;
- --quotedsize;
- }
- } while(quotedsize > 0L);
-
- free(line);
- fb = messageToFileblob(m, dir, 1);
- messageDestroy(m);
-
- if(fb)
- fileblobDestroy(fb);
- else
- ret = -1;
- }
- }
- }
- scanelem = scanlist;
-
- /*
- * There could be a phish in the plain text part, so save that
- * FIXME: Can't get to the option whether we are looking for
- * phishes or not, so assume we are, this slows things a
- * lot
- * Should be
- * if((type == CL_TYPE_MAIL) && (!(no-phishing))
- */
- ret = save_text(ctx, dir, start, size);
-
- free_map();
-
- while(scanelem) {
- struct scanlist *n = scanelem->next;
-
- free(scanelem);
- scanelem = n;
- }
-
- if(wasAlloced)
- free(start);
- else
- munmap(start, size);
-
- /*
- * FIXME: Need to run cl_scandir() here and return that value
- */
- cli_dbgmsg("cli_mbox: ret = %d\n", ret);
- if(ret != CL_EFORMAT)
- return ret;
-
- cli_dbgmsg("New world - don't know what to do - fall back to old world\n");
- /* Fall back for now */
- lseek(desc, 0L, SEEK_SET);
- return cli_parse_mbox(dir, desc, ctx);
- }
-
- /*
- * Save a text part - it could contain phish or jscript
- */
- static int
- save_text(cli_ctx *ctx, const char *dir, const char *start, size_t len)
- {
- const char *p;
-
- if((p = find_in_map(start, "\n\n")) || (p = find_in_map(start, "\r\n\r\n"))) {
- const char *q;
- fileblob *fb;
- char *tmpfilename;
-
- if(((q = find_in_map(start, "base64")) == NULL) &&
- ((q = find_in_map(start, "quoted_printable")) == NULL)) {
- cli_dbgmsg("It's all plain text!\n");
- if(*p == '\r')
- p += 4;
- else
- p += 2;
- len -= (p - start);
- } else if(((q = find_in_map(p, "\nFrom ")) == NULL) &&
- ((q = find_in_map(p, "base64")) == NULL) &&
- ((q = find_in_map(p, "quoted-printable")) == NULL))
- cli_dbgmsg("Can't find end of plain text - assume it's all\n");
- else
- len = (size_t)(q - p);
-
- if(len < 5) {
- cli_dbgmsg("save_text: Too small\n");
- return CL_EFORMAT;
- }
- if(ctx->scanned)
- *ctx->scanned += len / CL_COUNT_PRECISION;
-
- /*
- * This doesn't work, cli_scanbuff isn't designed to be used
- * in this way. It gets the "filetype" wrong and then
- * doesn't scan correctly
- */
- if(cli_scanbuff((char *)p, len, 0, ctx, CL_TYPE_BINARY_DATA, NULL) == CL_VIRUS) {
- cli_dbgmsg("save_text: found %s\n", *ctx->virname);
- return CL_VIRUS;
- }
-
- fb = fileblobCreate();
- if(fb == NULL)
- return CL_EMEM;
-
- tmpfilename = cli_gentemp(dir);
-
- if(tmpfilename == NULL) {
- fileblobDestroy(fb);
- return CL_ETMPFILE;
- }
- cli_dbgmsg("save plain bit to %s, %u bytes\n",
- tmpfilename, len);
-
- fileblobSetFilename(fb, dir, tmpfilename);
- free(tmpfilename);
-
- (void)fileblobAddData(fb, (const unsigned char *)p, len);
- fileblobDestroy(fb);
- return CL_SUCCESS;
- }
- cli_dbgmsg("No text part found to save\n");
- return CL_EFORMAT;
- }
-
- static void
- create_map(const char *begin, const char *end)
- {
- const struct wordlist {
- const char *word;
- int len;
- } wordlist[] = {
- { "base64", 6 },
- { "quoted-printable", 16 },
- { "\nbegin ", 7 },
- { "\nFrom ", 6 },
- { "\n\n", 2 },
- { "\r\n\r\n", 4 },
- { NULL, 0 }
- };
-
- if(map) {
- cli_dbgmsg("create_map called without free_map\n");
- free_map();
- }
- while(begin < end) {
- const struct wordlist *word;
-
- for(word = wordlist; word->word; word++) {
- if((end - begin) < word->len)
- continue;
- if(strncasecmp(begin, word->word, word->len) == 0) {
- add_to_map(begin, word->word);
- break;
- }
- }
- begin++;
- }
- }
-
- /* To sort map, assume 'offset' is presented in sorted order */
- static void
- add_to_map(const char *offset, const char *word)
- {
- if(map) {
- tail->next = cli_malloc(sizeof(struct map)); /* FIXME: verify */
- tail = tail->next;
- } else
- map = tail = cli_malloc(sizeof(struct map)); /* FIXME: verify */
-
- tail->offset = offset;
- tail->word = word;
- tail->next = NULL;
- }
-
- static const char *
- find_in_map(const char *offset, const char *word)
- {
- const struct map *item;
-
- for(item = map; item; item = item->next)
- if(item->offset >= offset)
- if(strcasecmp(word, item->word) == 0)
- return item->offset;
-
- return NULL;
- }
-
- static void
- free_map(void)
- {
- while(map) {
- struct map *next = map->next;
-
- free(map);
- map = next;
- }
- map = NULL;
- }
-
- #else /*!NEW_WORLD*/
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
int
cli_mbox(const char *dir, int desc, cli_ctx *ctx)
{
@@@ -1077,7 -345,6 +310,6 @@@
}
return cli_parse_mbox(dir, desc, ctx);
}
- #endif
/*
* TODO: when signal handling is added, need to remove temp files when a
@@@ -1099,62 -366,16 +331,16 @@@ cli_parse_mbox(const char *dir, int des
{
int retcode, i;
message *body;
- FILE *fd;
char buffer[RFC2821LENGTH + 1];
mbox_ctx mctx;
- #ifdef HAVE_BACKTRACE
- void (*segv)(int);
- #endif
static table_t *rfc821, *subtype;
- #ifdef SAVE_TMP
- char tmpfilename[16];
- int tmpfd;
- #endif
+ size_t at = 0;
+ fmap_t *map = *ctx->fmap;
- #ifdef NEW_WORLD
- cli_dbgmsg("fall back to old world\n");
- #else
cli_dbgmsg("in mbox()\n");
- #endif
-
- i = dup(desc);
- if((fd = fdopen(i, "rb")) == NULL) {
- cli_errmsg("Can't open descriptor %d\n", desc);
- close(i);
- return CL_EOPEN;
- }
- rewind(fd); /* bug 240 */
- #ifdef SAVE_TMP
- /*
- * Copy the incoming mail for debugging, so that if it falls over
- * we have a copy of the offending email. This is debugging code
- * that you shouldn't of course install in a live environment. I am
- * not interested in hearing about security issues with this section
- * of the parser.
- */
- strcpy(tmpfilename, "/tmp/mboxXXXXXX");
- tmpfd = mkstemp(tmpfilename);
- if(tmpfd < 0) {
- perror(tmpfilename);
- cli_errmsg("Can't make debugging file\n");
- } else {
- FILE *tmpfp = fdopen(tmpfd, "w");
- if(tmpfp) {
- while(fgets(buffer, sizeof(buffer) - 1, fd) != NULL)
- fputs(buffer, tmpfp);
- fclose(tmpfp);
- rewind(fd);
- } else
- cli_errmsg("Can't fdopen debugging file\n");
- }
- #endif
- if(fgets(buffer, sizeof(buffer) - 1, fd) == NULL) {
+ if(!fmap_gets(map, buffer, &at, sizeof(buffer) - 1)) {
/* empty message */
- fclose(fd);
- #ifdef SAVE_TMP
- if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
return CL_CLEAN;
}
#ifdef CL_THREAD_SAFE
@@@ -1169,10 -390,6 +355,6 @@@
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&tables_mutex);
#endif
- fclose(fd);
- #ifdef SAVE_TMP
- if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
return CL_EMEM;
}
}
@@@ -1180,10 -397,6 +362,6 @@@
pthread_mutex_unlock(&tables_mutex);
#endif
- #ifdef HAVE_BACKTRACE
- segv = signal(SIGSEGV, sigsegv);
- #endif
-
retcode = CL_SUCCESS;
body = NULL;
@@@ -1226,16 -439,8 +404,8 @@@
int messagenumber;
message *m = messageCreate();
- if(m == NULL) {
- fclose(fd);
- #ifdef HAVE_BACKTRACE
- signal(SIGSEGV, segv);
- #endif
- #ifdef SAVE_TMP
- if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
+ if(m == NULL)
return CL_EMEM;
- }
lastLineWasEmpty = FALSE;
messagenumber = 1;
@@@ -1291,16 -496,14 +461,14 @@@
* Fast track visa to uudecode.
* TODO: binhex, yenc
*/
- if(uudecodeFile(m, buffer, dir, fd) < 0)
+ if(uudecodeFile(m, buffer, dir, map, &at) < 0)
if(messageAddStr(m, buffer) < 0)
break;
} else
/* at this point, the \n has been removed */
if(messageAddStr(m, buffer) < 0)
break;
- } while(fgets(buffer, sizeof(buffer) - 1, fd) != NULL);
-
- fclose(fd);
+ } while(fmap_gets(map, buffer, &at, sizeof(buffer) - 1));
if(retcode == CL_SUCCESS) {
cli_dbgmsg("Extract attachments from email %d\n", messagenumber);
@@@ -1317,24 -520,21 +485,21 @@@
* CommuniGate Pro format: ignore headers until
* blank line
*/
- while((fgets(buffer, sizeof(buffer) - 1, fd) != NULL) &&
+ while(fmap_gets(map, buffer, &at, sizeof(buffer) - 1) &&
(strchr("\r\n", buffer[0]) == NULL))
;
- LOCKFILE(fd);
/* getline_from_mbox could be using unlocked_stdio(3),
* so lock file here */
/*
* Ignore any blank lines at the top of the message
*/
while(strchr("\r\n", buffer[0]) &&
- (getline_from_mbox(buffer, sizeof(buffer) - 1, fd) != NULL))
+ (getline_from_mbox(buffer, sizeof(buffer) - 1, map, &at) != NULL))
;
buffer[sizeof(buffer) - 1] = '\0';
- body = parseEmailFile(fd, rfc821, buffer, dir);
- UNLOCKFILE(fd);
- fclose(fd);
+ body = parseEmailFile(map, &at, rfc821, buffer, dir);
}
if(body) {
@@@ -1387,13 -587,6 +552,6 @@@
cli_dbgmsg("cli_mbox returning %d\n", retcode);
- #ifdef HAVE_BACKTRACE
- signal(SIGSEGV, segv);
- #endif
-
- #ifdef SAVE_TMP
- if (cli_unlink(tmpfilename)) return CL_EUNLINK;
- #endif
return retcode;
}
@@@ -1404,7 -597,7 +562,7 @@@
* handled ungracefully...
*/
static message *
- parseEmailFile(FILE *fin, const table_t *rfc821, const char *firstLine, const char *dir)
+ parseEmailFile(fmap_t *map, size_t *at, const table_t *rfc821, const char *firstLine, const char *dir)
{
bool inHeader = TRUE;
bool bodyIsEmpty = TRUE;
@@@ -1498,7 -691,7 +656,7 @@@
bodyIsEmpty = TRUE;
} else {
char *ptr;
- int lookahead;
+ char *lookahead;
if(fullline == NULL) {
char cmd[RFC2821LENGTH + 1], out[RFC2821LENGTH + 1];
@@@ -1551,10 -744,7 +709,7 @@@
assert(fullline != NULL);
- lookahead = GETC(fin);
- if(lookahead != EOF) {
- ungetc(lookahead, fin);
-
+ if((lookahead = fmap_need_off_once(map, *at, 1))) {
/*
* Section B.2 of RFC822 says TAB or
* SPACE means a continuation of the
@@@ -1562,7 -752,7 +717,7 @@@
*
* Add all the arguments on the line
*/
- if(isblank(lookahead))
+ if(isblank(*lookahead))
continue;
}
@@@ -1595,7 -785,7 +750,7 @@@
* TODO: binhex, yenc
*/
bodyIsEmpty = FALSE;
- if(uudecodeFile(ret, line, dir, fin) < 0)
+ if(uudecodeFile(ret, line, dir, map, at) < 0)
if(messageAddStr(ret, line) < 0)
break;
} else {
@@@ -1629,7 -819,7 +784,7 @@@
if(messageAddStr(ret, line) < 0)
break;
}
- } while(getline_from_mbox(buffer, sizeof(buffer) - 1, fin) != NULL);
+ } while(getline_from_mbox(buffer, sizeof(buffer) - 1, map, at) != NULL);
if(boundary)
free(boundary);
@@@ -3639,9 -2829,24 +2794,9 @@@ rfc1341(message *m, const char *dir
if(id == NULL)
return -1;
-/* do we need this for C_WINDOWS?
-#ifdef C_CYGWIN
- if((tmpdir = getenv("TEMP")) == (char *)NULL)
- if((tmpdir = getenv("TMP")) == (char *)NULL)
- if((tmpdir = getenv("TMPDIR")) == (char *)NULL)
- tmpdir = "C:\\";
-#else
-*/
- if((tmpdir = getenv("TMPDIR")) == (char *)NULL)
- if((tmpdir = getenv("TMP")) == (char *)NULL)
- if((tmpdir = getenv("TEMP")) == (char *)NULL)
-#ifdef P_tmpdir
- tmpdir = P_tmpdir;
-#else
- tmpdir = "/tmp";
-#endif
+ tmpdir = cli_gettmpdir();
- snprintf(pdir, sizeof(pdir) - 1, "%s/clamav-partial", tmpdir);
+ snprintf(pdir, sizeof(pdir) - 1, "%s"PATHSEP"clamav-partial", tmpdir);
if((mkdir(pdir, S_IRWXU) < 0) && (errno != EEXIST)) {
cli_errmsg("Can't create the directory '%s'\n", pdir);
@@@ -3725,7 -2930,7 +2880,7 @@@
sanitiseName(id);
- snprintf(outname, sizeof(outname) - 1, "%s/%s", dir, id);
+ snprintf(outname, sizeof(outname) - 1, "%s"PATHSEP"%s", dir, id);
cli_dbgmsg("outname: %s\n", outname);
@@@ -3764,15 -2969,16 +2919,15 @@@
int nblanks;
struct stat statb;
const char *dentry_idpart;
-#ifndef C_WINDOWS
+
if(dent->d_ino == 0)
continue;
-#endif
if(!strcmp(".",dent->d_name) ||
!strcmp("..", dent->d_name))
continue;
snprintf(fullname, sizeof(fullname) - 1,
- "%s/%s", pdir, dent->d_name);
+ "%s"PATHSEP"%s", pdir, dent->d_name);
dentry_idpart = strchr(dent->d_name, '_');
if(!dentry_idpart ||
@@@ -4055,63 -3261,65 +3210,65 @@@ usefulHeader(int commandNumber, const c
* Like fgets but cope with end of line by "\n", "\r\n", "\n\r", "\r"
*/
static char *
- getline_from_mbox(char *buffer, size_t len, FILE *fin)
+ getline_from_mbox(char *buffer, size_t buffer_len, fmap_t *map, size_t *at)
{
- char *ret;
+ char *src, *cursrc, *curbuf;
+ size_t i;
+ size_t input_len = MIN(map->len - *at, buffer_len + 1);
+ src = cursrc = fmap_need_off_once(map, *at, input_len);
/* we check for eof from the result of GETC()
* if(feof(fin))
return NULL;*/
+ if(!src) {
+ cli_dbgmsg("getline_from_mbox: fmap need failed\n");
+ return NULL;
+ }
+ if((buffer_len == 0) || (buffer == NULL)) {
+ cli_errmsg("Invalid call to getline_from_mbox(). Refer to http://www.clamav.net/bugs\n");
+ return NULL;
+ }
- if((len == 0) || (buffer == NULL)) {
- cli_errmsg("Invalid call to getline_from_mbox(). Refer to http://www.clamav.net/bugs\n");
- return NULL;
- }
-
- ret = buffer;
-
- do {
- int c = GETC(fin);
-
- switch(c) {
- default:
- *buffer = (char)c;
- buffer += (c != 0);
- continue;
- case '\n':
- *buffer++ = '\n';
- c = GETC(fin);
- if((c != '\r') && !feof(fin))
- ungetc(c, fin);
- break;
- case EOF:
- if(ret == buffer || ferror(fin)) {
- /* EOF on first char, or error */
- return NULL;
- }
- break;
- case '\r':
- *buffer++ = '\n';
- c = GETC(fin);
- if((c != '\n') && !feof(fin))
- ungetc(c, fin);
- break;
- }
- break;
- } while(--len > 1);
+ curbuf = buffer;
+
+ for(i=0; i<buffer_len-1; i++) {
+ char c;
- if(len == 0) {
- /* the email probably breaks RFC821 */
- cli_dbgmsg("getline_from_mbox: buffer overflow stopped, line lost\n");
+ if(!input_len--) {
+ if(curbuf == buffer) {
+ /* EOF on first char */
return NULL;
+ }
+ break;
}
- *buffer = '\0';
-
- if(len == 1)
- /* overflows will have appeared on separate lines */
- cli_dbgmsg("getline_from_mbox: buffer overflow stopped, line recovered\n");
- return ret;
+ switch((c = *cursrc++)) {
+ case '\0':
+ continue;
+ case '\n':
+ *curbuf++ = '\n';
+ if(input_len && *cursrc == '\r') {
+ i++;
+ cursrc++;
+ }
+ break;
+ case '\r':
+ *curbuf++ = '\r';
+ if(input_len && *cursrc == '\n') {
+ i++;
+ cursrc++;
+ }
+ break;
+ default:
+ *curbuf++ = c;
+ continue;
+ }
+ break;
+ }
+ *at += cursrc - src;
+ *curbuf = '\0';
+
+ return buffer;
}
/*
diff --combined libclamav/nsis/nulsft.c
index 5ca1441,704121d..96561b7
--- a/libclamav/nsis/nulsft.c
+++ b/libclamav/nsis/nulsft.c
@@@ -30,9 -30,6 +30,6 @@@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
#include "others.h"
#include "cltypes.h"
@@@ -43,7 -40,12 +40,8 @@@
#include "matcher.h"
#include "scanners.h"
#include "nulsft.h" /* SHUT UP GCC -Wextra */
+ #include "fmap.h"
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
#define EC32(x) le32_to_host(x)
enum {
@@@ -55,7 -57,7 +53,7 @@@
};
struct nsis_st {
- int ifd;
+ size_t curpos;
int ofd;
off_t off;
off_t fullsz;
@@@ -73,6 -75,7 +71,7 @@@
/* z_stream z; */
nsis_z_stream z;
unsigned char *freeme;
+ fmap_t *map;
char ofn[1024];
};
@@@ -198,9 -201,9 +197,9 @@@ static int nsis_unpack_next(struct nsis
return ret;
if (n->fno)
- snprintf(n->ofn, 1023, "%s/content.%.3u", n->dir, n->fno);
+ snprintf(n->ofn, 1023, "%s"PATHSEP"content.%.3u", n->dir, n->fno);
else
- snprintf(n->ofn, 1023, "%s/headers", n->dir);
+ snprintf(n->ofn, 1023, "%s"PATHSEP"headers", n->dir);
n->fno++;
@@@ -210,11 -213,12 +209,12 @@@
}
if (!n->solid) {
- if (cli_readn(n->ifd, &size, 4)!=4) {
+ if (fmap_readn(n->map, &size, n->curpos, 4)!=4) {
cli_dbgmsg("NSIS: reached EOF - extraction complete\n");
close(n->ofd);
return CL_BREAK;
}
+ n->curpos += 4;
if (n->asz==4) {
cli_dbgmsg("NSIS: reached CRC - extraction complete\n");
close(n->ofd);
@@@ -235,31 -239,24 +235,24 @@@
if ((ret=cli_checklimits("NSIS", ctx, size, 0, 0))!=CL_CLEAN) {
close(n->ofd);
- if (lseek(n->ifd, size, SEEK_CUR)==-1) return CL_ESEEK;
+ n->curpos += size;
return ret;
}
- if (!(ibuf= (unsigned char *) cli_malloc(size))) {
- cli_dbgmsg("NSIS: out of memory"__AT__"\n");
- close(n->ofd);
- return CL_EMEM;
- }
- if (cli_readn(n->ifd, ibuf, size) != (ssize_t) size) {
+ if (!(ibuf = fmap_need_off_once(n->map, n->curpos, size))) {
cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", size);
close(n->ofd);
return CL_EREAD;
}
+ n->curpos += size;
if (loops==size) {
if (cli_writen(n->ofd, ibuf, size) != (ssize_t) size) {
cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
- free(ibuf);
close(n->ofd);
return CL_EWRITE;
}
} else {
if ((ret=nsis_init(n))!=CL_SUCCESS) {
cli_dbgmsg("NSIS: decompressor init failed"__AT__"\n");
- free(ibuf);
close(n->ofd);
return ret;
}
@@@ -275,7 -272,6 +268,6 @@@
gotsome=1;
if (cli_writen(n->ofd, obuf, size) != (ssize_t) size) {
cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
- free(ibuf);
close(n->ofd);
nsis_shutdown(n);
return CL_EWRITE;
@@@ -284,7 -280,6 +276,6 @@@
n->nsis.avail_out = BUFSIZ;
loops=0;
if ((ret=cli_checklimits("NSIS", ctx, size, 0, 0))!=CL_CLEAN) {
- free(ibuf);
close(n->ofd);
nsis_shutdown(n);
return ret;
@@@ -302,7 -297,6 +293,6 @@@
gotsome=1;
if (cli_writen(n->ofd, obuf, n->nsis.next_out - obuf) != n->nsis.next_out - obuf) {
cli_dbgmsg("NSIS: cannot write output file"__AT__"\n");
- free(ibuf);
close(n->ofd);
return CL_EWRITE;
}
@@@ -316,13 -310,11 +306,11 @@@
ret = CL_EMAXSIZE;
close(n->ofd);
}
- free(ibuf);
return ret;
}
}
- free(ibuf);
return CL_SUCCESS;
} else {
@@@ -332,31 -324,12 +320,12 @@@
close(n->ofd);
return ret;
}
- #if HAVE_MMAP
- if((n->freeme= (unsigned char *)mmap(NULL, n->fullsz, PROT_READ, MAP_PRIVATE, n->ifd, 0))==MAP_FAILED) {
- cli_dbgmsg("NSIS: mmap() failed"__AT__"\n");
- close(n->ofd);
- return CL_EMAP;
- }
- n->nsis.next_in = n->freeme+n->off+0x1c;
- #else /* HAVE_MMAP */
- if(!size || size > CLI_MAX_ALLOCATION) {
- cli_dbgmsg("NSIS: mmap() support not compiled in and input file too big\n");
- close(n->ofd);
- return CL_EMEM;
- }
- if (!(n->freeme= (unsigned char *) cli_malloc(n->asz))) {
- cli_dbgmsg("NSIS: out of memory"__AT__"\n");
- close(n->ofd);
- return CL_EMEM;
- }
- if (cli_readn(n->ifd, n->freeme, n->asz) != (ssize_t) n->asz) {
+ if(!(n->freeme = fmap_need_off_once(n->map, n->curpos, n->asz))) {
cli_dbgmsg("NSIS: cannot read %u bytes"__AT__"\n", n->asz);
close(n->ofd);
return CL_EREAD;
}
n->nsis.next_in = n->freeme;
- #endif /* HAVE_MMAP */
n->nsis.avail_in = n->asz;
}
@@@ -450,52 -423,52 +419,52 @@@ static uint8_t nsis_detcomp(const char
}
static int nsis_headers(struct nsis_st *n, cli_ctx *ctx) {
- char buf[28];
- struct stat st;
+ const char *buf;
uint32_t pos;
int i;
uint8_t comps[] = {0, 0, 0, 0}, trunc = 0;
- if (fstat(n->ifd, &st)==-1 ||
- lseek(n->ifd, n->off, SEEK_SET)==-1 ||
- cli_readn(n->ifd, buf, 28) != 28)
+ if (!(buf = fmap_need_off_once(n->map, n->off, 0x1c)))
return CL_EREAD;
n->hsz = (uint32_t)cli_readint32(buf+0x14);
n->asz = (uint32_t)cli_readint32(buf+0x18);
- n->fullsz = st.st_size;
+ n->fullsz = n->map->len;
cli_dbgmsg("NSIS: Header info - Flags=%x, Header size=%x, Archive size=%x\n", cli_readint32(buf), n->hsz, n->asz);
- if (st.st_size - n->off < (off_t) n->asz) {
+ if (n->fullsz - n->off < (off_t) n->asz) {
cli_dbgmsg("NSIS: Possibly truncated file\n");
- n->asz = st.st_size - n->off;
+ n->asz = n->fullsz - n->off;
trunc++;
- } else if (st.st_size - n->off != (off_t) n->asz) {
+ } else if (n->fullsz - n->off != (off_t) n->asz) {
cli_dbgmsg("NSIS: Overlays found\n");
}
n->asz -= 0x1c;
+ buf += 0x1c;
/* Guess if solid */
for (i=0, pos=0;pos < n->asz-4;i++) {
int32_t nextsz;
- if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EREAD;
- nextsz=cli_readint32(buf+4);
- if (!i) n->comp = nsis_detcomp(buf+4);
+ if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD;
+ nextsz=cli_readint32(buf);
+ if (!i) n->comp = nsis_detcomp(buf);
+ buf += 4;
if (nextsz&0x80000000) {
nextsz&=~0x80000000;
- if (cli_readn(n->ifd, buf+4, 4)!=4) return CL_EREAD;
- comps[nsis_detcomp(buf+4)]++;
+ if (!(buf = fmap_need_ptr_once(n->map, (void *)buf, 4))) return CL_EREAD;
+ comps[nsis_detcomp(buf)]++;
nextsz-=4;
pos+=4;
+ buf+=4;
}
if ((pos+=4+nextsz) > n->asz) {
n->solid = 1;
break;
}
- if (lseek(n->ifd, nextsz, SEEK_CUR)==-1) return CL_ESEEK;
+ buf += nextsz;
}
if (trunc && i>=2) n->solid=0;
@@@ -508,8 -481,7 +477,7 @@@
n->comp = (comps[1]<comps[2]) ? (comps[2]<comps[3] ? COMP_ZLIB : COMP_LZMA) : (comps[1]<comps[3] ? COMP_ZLIB : COMP_BZIP2);
}
- if (lseek(n->ifd, n->off+0x1c, SEEK_SET)==-1) return CL_ESEEK;
-
+ n->curpos = n->off+0x1c;
return nsis_unpack_next(n, ctx);
}
@@@ -519,16 -491,6 +487,6 @@@ static int cli_nsis_unpack(struct nsis_
return (n->fno) ? nsis_unpack_next(n, ctx) : nsis_headers(n, ctx);
}
- static void cli_nsis_free(struct nsis_st *n) {
- nsis_shutdown(n);
- if (n->solid && n->freeme) {
- #if HAVE_MMAP
- munmap(n->freeme, n->fullsz);
- #else
- free(n->freeme);
- #endif
- }
- }
int cli_scannulsft(int desc, cli_ctx *ctx, off_t offset) {
int ret;
@@@ -538,7 -500,6 +496,6 @@@
memset(&nsist, 0, sizeof(struct nsis_st));
- nsist.ifd = desc;
nsist.off = offset;
if (!(nsist.dir = cli_gentemp(ctx->engine->tmpdir)))
return CL_ETMPDIR;
@@@ -547,6 -508,11 +504,11 @@@
free(nsist.dir);
return CL_ETMPDIR;
}
+
+ if(!(nsist.map = fmap(desc, 0, 0))) {
+ cli_errmsg("scannulsft: fmap failed\n");
+ return CL_EMEM;
+ }
if(ctx->engine->keeptmp) cli_dbgmsg("NSIS: Extracting files to %s\n", nsist.dir);
@@@ -570,7 -536,8 +532,8 @@@
if(ret == CL_BREAK || ret == CL_EMAXFILES)
ret = CL_CLEAN;
- cli_nsis_free(&nsist);
+ nsis_shutdown(&nsist);
+ funmap(nsist.map);
if(!ctx->engine->keeptmp)
cli_rmdirs(nsist.dir);
diff --combined libclamav/ole2_extract.c
index 0952504,71ce49d..f37589a
--- a/libclamav/ole2_extract.c
+++ b/libclamav/ole2_extract.c
@@@ -34,16 -34,13 +34,13 @@@
#endif
#include <ctype.h>
#include <stdlib.h>
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
#include "clamav.h"
#include "cltypes.h"
#include "others.h"
#include "ole2_extract.h"
#include "scanners.h"
- #include "mbox.h"
+ #include "fmap.h"
#define ole2_endian_convert_16(v) le16_to_host((uint16_t)(v))
#define ole2_endian_convert_32(v) le32_to_host((uint32_t)(v))
@@@ -60,6 -57,11 +57,6 @@@
#pragma pack 1
#endif
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-
typedef struct ole2_header_tag
{
unsigned char magic[8]; /* should be: 0xd0cf11e0a1b11ae1 */
@@@ -89,10 -91,10 +86,10 @@@
reading the header */
int32_t sbat_root_start __attribute__ ((packed));
uint32_t max_block_no;
off_t m_length;
bitset_t *bitset;
struct uniq *U;
+ fmap_t *map;
int has_vba;
} ole2_header_t;
@@@ -276,9 -278,10 +273,10 @@@ static void print_ole2_header(ole2_head
return;
}
- static int ole2_read_block(int fd, ole2_header_t *hdr, void *buff, unsigned int size, int32_t blockno)
+ static int ole2_read_block(ole2_header_t *hdr, void *buff, unsigned int size, int32_t blockno)
{
off_t offset, offend;
+ void *pblock;
if (blockno < 0) {
return FALSE;
@@@ -287,24 -290,18 +285,18 @@@
/* other methods: (blockno+1) * 512 or (blockno * block_size) + 512; */
offset = (blockno << hdr->log2_big_block_size) + MAX(512, 1 << hdr->log2_big_block_size); /* 512 is header size */
- if (hdr->m_area == NULL) {
- if (lseek(fd, offset, SEEK_SET) != offset) {
- return FALSE;
- }
- if (cli_readn(fd, buff, size) != size) {
- return FALSE;
- }
- } else {
- offend = offset + size;
- if ((offend <= 0) || (offend > hdr->m_length)) {
- return FALSE;
- }
- memcpy(buff, hdr->m_area+offset, size);
+ offend = offset + size;
+ if ((offend <= 0) || (offend > hdr->m_length)) {
+ return FALSE;
+ }
+ if(!(pblock = fmap_need_off_once(hdr->map, offset, size))) {
+ return FALSE;
}
+ memcpy(buff, pblock, size);
return TRUE;
}
- static int32_t ole2_get_next_bat_block(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_bat_block(ole2_header_t *hdr, int32_t current_block)
{
int32_t bat_array_index;
uint32_t bat[128];
@@@ -318,14 -315,14 +310,14 @@@
cli_dbgmsg("bat_array index error\n");
return -10;
}
- if (!ole2_read_block(fd, hdr, &bat, 512,
+ if (!ole2_read_block(hdr, &bat, 512,
ole2_endian_convert_32(hdr->bat_array[bat_array_index]))) {
return -1;
}
return ole2_endian_convert_32(bat[current_block-(bat_array_index * 128)]);
}
- static int32_t ole2_get_next_xbat_block(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_xbat_block(ole2_header_t *hdr, int32_t current_block)
{
int32_t xbat_index, xbat_block_index, bat_index, bat_blockno;
uint32_t xbat[128], bat[128];
@@@ -344,40 -341,40 +336,40 @@@
bat_index = current_block % 128;
- if (!ole2_read_block(fd, hdr, &xbat, 512, hdr->xbat_start)) {
+ if (!ole2_read_block(hdr, &xbat, 512, hdr->xbat_start)) {
return -1;
}
/* Follow the chain of XBAT blocks */
while (xbat_block_index > 0) {
- if (!ole2_read_block(fd, hdr, &xbat, 512,
+ if (!ole2_read_block(hdr, &xbat, 512,
ole2_endian_convert_32(xbat[127]))) {
return -1;
}
xbat_block_index--;
}
- if (!ole2_read_block(fd, hdr, &bat, 512, ole2_endian_convert_32(xbat[bat_blockno]))) {
+ if (!ole2_read_block(hdr, &bat, 512, ole2_endian_convert_32(xbat[bat_blockno]))) {
return -1;
}
return ole2_endian_convert_32(bat[bat_index]);
}
- static int32_t ole2_get_next_block_number(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_block_number(ole2_header_t *hdr, int32_t current_block)
{
if (current_block < 0) {
return -1;
}
if ((current_block / 128) > 108) {
- return ole2_get_next_xbat_block(fd, hdr, current_block);
+ return ole2_get_next_xbat_block(hdr, current_block);
} else {
- return ole2_get_next_bat_block(fd, hdr, current_block);
+ return ole2_get_next_bat_block(hdr, current_block);
}
}
- static int32_t ole2_get_next_sbat_block(int fd, ole2_header_t *hdr, int32_t current_block)
+ static int32_t ole2_get_next_sbat_block(ole2_header_t *hdr, int32_t current_block)
{
int32_t iter, current_bat_block;
uint32_t sbat[128];
@@@ -389,17 -386,17 +381,17 @@@
current_bat_block = hdr->sbat_start;
iter = current_block / 128;
while (iter > 0) {
- current_bat_block = ole2_get_next_block_number(fd, hdr, current_bat_block);
+ current_bat_block = ole2_get_next_block_number(hdr, current_bat_block);
iter--;
}
- if (!ole2_read_block(fd, hdr, &sbat, 512, current_bat_block)) {
+ if (!ole2_read_block(hdr, &sbat, 512, current_bat_block)) {
return -1;
}
return ole2_endian_convert_32(sbat[current_block % 128]);
}
/* Retrieve the block containing the data for the given sbat index */
- static int32_t ole2_get_sbat_data_block(int fd, ole2_header_t *hdr, void *buff, int32_t sbat_index)
+ static int32_t ole2_get_sbat_data_block(ole2_header_t *hdr, void *buff, int32_t sbat_index)
{
int32_t block_count, current_block;
@@@ -415,17 -412,17 +407,17 @@@
block_count = sbat_index / (1 << (hdr->log2_big_block_size - hdr->log2_small_block_size));
current_block = hdr->sbat_root_start;
while (block_count > 0) {
- current_block = ole2_get_next_block_number(fd, hdr, current_block);
+ current_block = ole2_get_next_block_number(hdr, current_block);
block_count--;
}
/* current_block now contains the block number of the sbat array
containing the entry for the required small block */
- return(ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block));
+ return(ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block));
}
- static int ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, int32_t prop_index,
- int (*handler)(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx),
+ static int ole2_walk_property_tree(ole2_header_t *hdr, const char *dir, int32_t prop_index,
+ int (*handler)(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx),
unsigned int rec_level, unsigned int *file_count, cli_ctx *ctx, unsigned long *scansize)
{
property_t prop_block[4];
@@@ -450,13 -447,13 +442,13 @@@
idx = prop_index / 4;
for (i=0 ; i < idx ; i++) {
- current_block = ole2_get_next_block_number(fd, hdr, current_block);
+ current_block = ole2_get_next_block_number(hdr, current_block);
if (current_block < 0) {
return CL_SUCCESS;
}
}
idx = prop_index % 4;
- if (!ole2_read_block(fd, hdr, prop_block, 512,
+ if (!ole2_read_block(hdr, prop_block, 512,
current_block)) {
return CL_SUCCESS;
}
@@@ -497,11 -494,11 +489,11 @@@
}
hdr->sbat_root_start = prop_block[idx].start_block;
if (
- (ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
||
- (ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
||
- (ret=ole2_walk_property_tree(fd, hdr, dir,prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir,prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
) return ret;
break;
case 2: /* File */
@@@ -512,24 -509,24 +504,24 @@@
if (!ctx || !ctx->engine->maxfilesize || prop_block[idx].size <= ctx->engine->maxfilesize || prop_block[idx].size <= *scansize) {
(*file_count)++;
*scansize-=prop_block[idx].size;
- if ((ret=handler(fd, hdr, &prop_block[idx], dir, ctx)) != CL_SUCCESS)
+ if ((ret=handler(hdr, &prop_block[idx], dir, ctx)) != CL_SUCCESS)
return ret;
} else {
cli_dbgmsg("OLE2: filesize exceeded\n");
}
if (
- (ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
||
- (ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].next, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].next, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
||
- (ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].child, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].child, handler, rec_level, file_count, ctx, scansize))!=CL_SUCCESS
) return ret;
break;
case 1: /* Directory */
if (dir) {
dirname = (char *) cli_malloc(strlen(dir)+8);
if (!dirname) return CL_BREAK;
- snprintf(dirname, strlen(dir)+8, "%s/%.6d", dir, prop_index);
+ snprintf(dirname, strlen(dir)+8, "%s"PATHSEP"%.6d", dir, prop_index);
if (mkdir(dirname, 0700) != 0) {
free(dirname);
return CL_BREAK;
@@@ -537,11 -534,11 +529,11 @@@
cli_dbgmsg("OLE2 dir entry: %s\n",dirname);
} else dirname = NULL;
if (
- (ret=ole2_walk_property_tree(fd, hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir, prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
||
- (ret=ole2_walk_property_tree(fd, hdr, dir,prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dir,prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
||
- (ret=ole2_walk_property_tree(fd, hdr, dirname, prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
+ (ret=ole2_walk_property_tree(hdr, dirname, prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize))!=CL_SUCCESS
) {}
if (dirname) free(dirname);
return ret;
@@@ -553,7 -550,7 +545,7 @@@
return CL_SUCCESS;
}
/* Write file Handler - write the contents of the entry to a file */
- static int handler_writefile(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
+ static int handler_writefile(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
{
unsigned char *buff;
int32_t current_block, ofd, len, offset;
@@@ -575,7 -572,7 +567,7 @@@
name = get_property_name2(prop->name, prop->name_size);
if (name) cnt = uniq_add(hdr->U, name, strlen(name), &hash);
else cnt = uniq_add(hdr->U, NULL, 0, &hash);
- snprintf(newname, sizeof(newname), "%s/%s_%u", dir, hash, cnt);
+ snprintf(newname, sizeof(newname), "%s"PATHSEP"%s_%u", dir, hash, cnt);
newname[sizeof(newname)-1]='\0';
cli_dbgmsg("OLE2 [handler_writefile]: Dumping '%s' to '%s'\n", name ? name : "<empty>", newname);
if (name) free(name);
@@@ -626,7 -623,7 +618,7 @@@
}
if (prop->size < (int64_t)hdr->sbat_cutoff) {
/* Small block file */
- if (!ole2_get_sbat_data_block(fd, hdr, buff, current_block)) {
+ if (!ole2_get_sbat_data_block(hdr, buff, current_block)) {
cli_dbgmsg("OLE2 [handler_writefile]: ole2_get_sbat_data_block failed\n");
close(ofd);
free(buff);
@@@ -644,10 -641,10 +636,10 @@@
}
len -= MIN(len,1 << hdr->log2_small_block_size);
- current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
+ current_block = ole2_get_next_sbat_block(hdr, current_block);
} else {
/* Big block file */
- if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
+ if (!ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
close(ofd);
free(buff);
cli_bitset_free(blk_bitset);
@@@ -661,7 -658,7 +653,7 @@@
return CL_BREAK;
}
- current_block = ole2_get_next_block_number(fd, hdr, current_block);
+ current_block = ole2_get_next_block_number(hdr, current_block);
len -= MIN(len,(1 << hdr->log2_big_block_size));
}
}
@@@ -672,7 -669,7 +664,7 @@@
}
/* enum file Handler - checks for VBA presence */
- static int handler_enum(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
+ static int handler_enum(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
{
char *name;
@@@ -688,7 -685,7 +680,7 @@@
}
- static int handler_otf(int fd, ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
+ static int handler_otf(ole2_header_t *hdr, property_t *prop, const char *dir, cli_ctx *ctx)
{
char *tempfile;
unsigned char *buff;
@@@ -753,7 -750,7 +745,7 @@@
}
if (prop->size < (int64_t)hdr->sbat_cutoff) {
/* Small block file */
- if (!ole2_get_sbat_data_block(fd, hdr, buff, current_block)) {
+ if (!ole2_get_sbat_data_block(hdr, buff, current_block)) {
cli_dbgmsg("ole2_get_sbat_data_block failed\n");
break;
}
@@@ -772,10 -769,10 +764,10 @@@
}
len -= MIN(len,1 << hdr->log2_small_block_size);
- current_block = ole2_get_next_sbat_block(fd, hdr, current_block);
+ current_block = ole2_get_next_sbat_block(hdr, current_block);
} else {
/* Big block file */
- if (!ole2_read_block(fd, hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
+ if (!ole2_read_block(hdr, buff, 1 << hdr->log2_big_block_size, current_block)) {
break;
}
if (cli_writen(ofd, buff, MIN(len,(1 << hdr->log2_big_block_size))) !=
@@@ -791,7 -788,7 +783,7 @@@
return CL_EWRITE;
}
- current_block = ole2_get_next_block_number(fd, hdr, current_block);
+ current_block = ole2_get_next_block_number(hdr, current_block);
len -= MIN(len,(1 << hdr->log2_big_block_size));
}
}
@@@ -874,13 -871,13 +866,13 @@@ static int ole2_read_header(int fd, ole
}
#endif
- int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx, struct uniq **vba)
+ int cli_ole2_extract(const char *dirname, cli_ctx *ctx, struct uniq **vba)
{
ole2_header_t hdr;
int hdr_size, ret=CL_CLEAN;
- struct stat statbuf;
unsigned int file_count=0;
unsigned long scansize, scansize2;
+ void *phdr;
cli_dbgmsg("in cli_ole2_extract()\n");
@@@ -895,40 -892,22 +887,22 @@@
/* size of header - size of other values in struct */
hdr_size = sizeof(struct ole2_header_tag) - sizeof(int32_t) - sizeof(uint32_t) -
- sizeof(unsigned char *) - sizeof(off_t) - sizeof(bitset_t *) -
- sizeof(struct uniq *) - sizeof(int);
+ sizeof(off_t) - sizeof(bitset_t *) -
+ sizeof(struct uniq *) - sizeof(int) - sizeof(fmap_t *);
- hdr.m_area = NULL;
-
- if (fstat(fd, &statbuf) == 0) {
- if (statbuf.st_size < hdr_size) {
- return CL_CLEAN;
- }
- #ifdef HAVE_MMAP
- hdr.m_length = statbuf.st_size;
- hdr.m_area = (unsigned char *) mmap(NULL, hdr.m_length, PROT_READ, MAP_PRIVATE, fd, 0);
- if (hdr.m_area == MAP_FAILED) {
- hdr.m_area = NULL;
- } else {
- cli_dbgmsg("mmap'ed file\n");
- memcpy(&hdr, hdr.m_area, hdr_size);
- }
- #endif
+ if((*ctx->fmap)->len < hdr_size) {
+ return CL_CLEAN;
}
-
- if (hdr.m_area == NULL) {
- hdr.bitset = NULL;
- #if defined(HAVE_ATTRIB_PACKED) || defined(HAVE_PRAGMA_PACK) || defined(HAVE_PRAGMA_PACK_HPPA)
- if (cli_readn(fd, &hdr, hdr_size) != hdr_size) {
- goto abort;
- }
- #else
- if (!ole2_read_header(fd, &hdr)) {
- goto abort;
- }
- #endif
+ hdr.map = *ctx->fmap;
+ hdr.m_length = hdr.map->len;
+ phdr = fmap_need_off_once(hdr.map, 0, hdr_size);
+ if(phdr) {
+ memcpy(&hdr, phdr, hdr_size);
+ } else {
+ cli_dbgmsg("cli_ole2_extract: failed to read header\n");
+ goto abort;
}
-
+
hdr.minor_version = ole2_endian_convert_16(hdr.minor_version);
hdr.dll_version = ole2_endian_convert_16(hdr.dll_version);
hdr.byte_order = ole2_endian_convert_16(hdr.byte_order);
@@@ -970,14 -949,14 +944,14 @@@
}
/* 8 SBAT blocks per file block */
- hdr.max_block_no = (statbuf.st_size - MAX(512, 1 << hdr.log2_big_block_size)) / (1 << hdr.log2_small_block_size);
+ hdr.max_block_no = (hdr.map->len - MAX(512, 1 << hdr.log2_big_block_size)) / (1 << hdr.log2_small_block_size);
print_ole2_header(&hdr);
cli_dbgmsg("Max block number: %lu\n", (unsigned long int) hdr.max_block_no);
/* PASS 1 : Count files and check for VBA */
hdr.has_vba = 0;
- ret = ole2_walk_property_tree(fd, &hdr, NULL, 0, handler_enum, 0, &file_count, ctx, &scansize);
+ ret = ole2_walk_property_tree(&hdr, NULL, 0, handler_enum, 0, &file_count, ctx, &scansize);
cli_bitset_free(hdr.bitset);
hdr.bitset = NULL;
if (!file_count || !(hdr.bitset = cli_bitset_init()))
@@@ -993,7 -972,7 +967,7 @@@
goto abort;
}
file_count = 0;
- ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize2);
+ ole2_walk_property_tree(&hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize2);
ret = CL_CLEAN;
*vba = hdr.U;
} else {
@@@ -1001,15 -980,10 +975,10 @@@
/* PASS 2/B : OTF scan */
file_count = 0;
if(ctx)
- ret = ole2_walk_property_tree(fd, &hdr, NULL, 0, handler_otf, 0, &file_count, ctx, &scansize2);
+ ret = ole2_walk_property_tree(&hdr, NULL, 0, handler_otf, 0, &file_count, ctx, &scansize2);
}
abort:
- #ifdef HAVE_MMAP
- if (hdr.m_area != NULL) {
- munmap(hdr.m_area, hdr.m_length);
- }
- #endif
if(hdr.bitset)
cli_bitset_free(hdr.bitset);
diff --combined libclamav/others.h
index 9cef29e,b33e104..fb0dfb2
--- a/libclamav/others.h
+++ b/libclamav/others.h
@@@ -38,6 -38,7 +38,7 @@@
#include "clamav.h"
#include "dconf.h"
#include "filetypes.h"
+ #include "fmap.h"
#include "libclamunrar_iface/unrar_iface.h"
#include "regex/regex.h"
@@@ -50,7 -51,7 +51,7 @@@
* in re-enabling affected modules.
*/
-#define CL_FLEVEL 47
+#define CL_FLEVEL 49
#define CL_FLEVEL_DCONF CL_FLEVEL
extern uint8_t cli_debug_flag;
@@@ -109,6 -110,7 +110,7 @@@ typedef struct
unsigned int found_possibly_unwanted;
cli_file_t container_type; /* FIXME: to be made into a stack or array - see bb#1579 & bb#1293 */
struct cli_dconf *dconf;
+ fmap_t **fmap;
} cli_ctx;
struct cl_engine {
@@@ -170,7 -172,7 +172,7 @@@
struct cli_ftype *ftypes;
/* Ignored signatures */
- struct cli_ignored *ignored;
+ struct cli_matcher *ignored;
/* PUA categories (to be included or excluded) */
char *pua_cats;
@@@ -316,6 -318,21 +318,6 @@@ static inline void cli_writeint32(char
#endif
#define CLI_SAR(n,s) n = CLI_SRS(n,s)
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-#ifndef MAX
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-#endif
-
typedef struct bitset_tag
{
unsigned char *bitset;
@@@ -382,7 -399,6 +384,7 @@@ char *cli_md5file(const char *filename)
int cli_unlink(const char *pathname);
int cli_readn(int fd, void *buff, unsigned int count);
int cli_writen(int fd, const void *buff, unsigned int count);
+const char *cli_gettmpdir(void);
char *cli_gentemp(const char *dir);
int cli_gentempfd(const char *dir, char **name, int *fd);
unsigned int cli_rndnum(unsigned int max);
diff --combined libclamav/pdf.c
index b79ec53,95e6a4e..9b2de23
--- a/libclamav/pdf.c
+++ b/libclamav/pdf.c
@@@ -26,7 -26,6 +26,6 @@@ static char const rcsid[] = "$Id: pdf.c
#include "clamav-config.h"
#endif
- #ifdef HAVE_MMAP
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@@ -41,18 -40,24 +40,16 @@@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
#include <zlib.h>
-#ifdef C_WINDOWS
-#include <io.h>
-#endif
-
#include "clamav.h"
#include "others.h"
#include "mbox.h"
#include "pdf.h"
#include "scanners.h"
+ #include "fmap.h"
#include "str.h"
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
#ifdef CL_DEBUG
/*#define SAVE_TMP
*Save the file being worked on in tmp */
@@@ -65,7 -70,7 +62,7 @@@ static const char *pdf_nextlinestart(co
static const char *pdf_nextobject(const char *ptr, size_t len);
int
- cli_pdf(const char *dir, int desc, cli_ctx *ctx, off_t offset)
+ cli_pdf(const char *dir, cli_ctx *ctx, off_t offset)
{
off_t size; /* total number of bytes in the file */
off_t bytesleft, trailerlength;
@@@ -76,23 -81,18 +73,18 @@@
table_t *md5table;
int printed_predictor_message, printed_embedded_font_message, rc;
unsigned int files;
- struct stat statb;
+ fmap_t *map = *ctx->fmap;
int opt_failed = 0;
cli_dbgmsg("in cli_pdf(%s)\n", dir);
- if(fstat(desc, &statb) < 0) {
- cli_errmsg("cli_pdf: fstat() failed\n");
- return CL_EOPEN;
- }
-
- size = statb.st_size - offset;
+ size = map->len - offset;
if(size <= 7) /* doesn't even include the file header */
return CL_CLEAN;
- p = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, offset);
- if(buf == MAP_FAILED) {
+ p = buf = fmap_need_off_once(map, 0, size); /* FIXME: really port to fmap */
+ if(!buf) {
cli_errmsg("cli_pdf: mmap() failed\n");
return CL_EMAP;
}
@@@ -112,7 -112,6 +104,6 @@@
}
if(!bytesleft) {
- munmap(buf, size);
cli_dbgmsg("cli_pdf: file header not found\n");
return CL_CLEAN;
}
@@@ -123,7 -122,6 +114,6 @@@
break;
if(q <= p) {
- munmap(buf, size);
cli_dbgmsg("cli_pdf: trailer not found\n");
return CL_CLEAN;
}
@@@ -142,7 -140,6 +132,6 @@@
* http://www.cs.cmu.edu/~dst/Adobe/Gallery/anon21jul01-pdf-encryption.txt
* http://www.adobe.com/devnet/pdf/
*/
- munmap(buf, size);
cli_dbgmsg("cli_pdf: Encrypted PDF files not yet supported\n");
return CL_CLEAN;
}
@@@ -165,7 -162,6 +154,6 @@@
break;
if(xrefstart == p) {
- munmap(buf, size);
cli_dbgmsg("cli_pdf: xref not found\n");
return CL_CLEAN;
}
@@@ -386,7 -382,7 +374,7 @@@
has_cr = 1;
} else
has_cr = 0;
- snprintf(fullname, sizeof(fullname), "%s/pdf%02u", dir, files);
+ snprintf(fullname, sizeof(fullname), "%s"PATHSEP"pdf%02u", dir, files);
fout = open(fullname, O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
if(fout < 0) {
char err[128];
@@@ -544,7 -540,6 +532,6 @@@
if(rc != CL_CLEAN) break;
}
- munmap(buf, size);
tableDestroy(md5table);
@@@ -840,17 -835,3 +827,3 @@@ pdf_nextobject(const char *ptr, size_t
}
return NULL;
}
-
- #else /*!HAVE_MMAP*/
-
- #include "clamav.h"
- #include "others.h"
- #include "pdf.h"
-
- int
- cli_pdf(const char *dir, int desc, cli_ctx *ctx, off_t offset)
- {
- cli_dbgmsg("File not decoded - PDF decoding needs mmap() (for now)\n");
- return CL_CLEAN;
- }
- #endif
diff --combined libclamav/pe.c
index 7aaa26b,870f3fd..d706ca8
--- a/libclamav/pe.c
+++ b/libclamav/pe.c
@@@ -59,6 -59,10 +59,6 @@@
#include "special.h"
#include "ishield.h"
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
#define DCONF ctx->dconf->pe
#define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */
@@@ -286,7 -290,7 +286,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(fmap_t *map, struct cli_exe_section *s, unsigned char *digest) {
void *hashme;
cli_md5_ctx md5;
@@@ -295,28 -299,21 +295,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, fmap_t *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);
@@@ -324,7 -321,7 +317,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);
@@@ -332,18 -329,13 +325,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);
@@@ -385,13 -377,13 +373,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",
@@@ -400,22 -392,15 +388,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;
@@@ -429,10 -414,9 +410,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;
@@@ -444,6 -428,7 +424,7 @@@
struct cli_matcher *md5_sect;
char timestr[32];
struct pe_image_data_dir *dirs;
+ fmap_t *map;
if(!ctx) {
@@@ -451,7 -436,8 +432,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;
}
@@@ -461,15 -447,13 +443,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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN;
}
@@@ -481,13 -465,7 +461,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;
@@@ -605,7 -583,7 +579,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
if(nsections)
cli_warnmsg("PE file contains %d sections\n", nsections);
@@@ -625,20 -603,22 +599,22 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return 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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return 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) {
@@@ -648,7 -628,7 +624,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN;
}
@@@ -664,7 -644,7 +640,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
cli_dbgmsg("9x compatibility mode\n");
}
@@@ -673,7 -653,7 +649,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)
@@@ -701,16 -681,16 +677,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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return 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");
@@@ -787,22 -767,17 +763,17 @@@
cli_dbgmsg("Bad virtual alignemnt\n");
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return 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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
- if(fstat(desc, &sb) == -1) {
- cli_dbgmsg("fstat failed\n");
- return CL_ESTAT;
- }
-
- fsize = sb.st_size;
+ fsize = map->len;
section_hdr = (struct pe_image_section_hdr *) cli_calloc(nsections, sizeof(struct pe_image_section_hdr));
@@@ -822,7 -797,7 +793,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);
@@@ -830,11 -805,12 +801,12 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return 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)) {
@@@ -899,7 -875,7 +871,7 @@@
*ctx->virname = "Broken.Executable";
free(section_hdr);
free(exe_sections);
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */
@@@ -910,7 -886,7 +882,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN; /* no ninjas to see here! move along! */
}
@@@ -924,13 -900,11 +896,12 @@@
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, NULL) == CL_VIRUS) {
- if(cli_bm_scanbuff(md5_dig, 16, NULL, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS) {
+ const struct cli_bm_patt *patt;
- if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, &patt, ctx->engine->md5_mdb, 0, -1, NULL) == CL_VIRUS && patt->filesize == exe_sections[i].rsz) {
- if(cli_bm_scanbuff(md5_dig, 16, NULL, &patt, ctx->engine->md5_fp, 0, -1, NULL) != CL_VIRUS || patt->filesize != fsize) {
-
++ if(cli_md5sect(map, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, &patt, ctx->engine->md5_mdb, 0, NULL, NULL) == CL_VIRUS && patt->filesize == exe_sections[i].rsz) {
++ if(cli_bm_scanbuff(md5_dig, 16, NULL, &patt, ctx->engine->md5_fp, 0, NULL, NULL) != CL_VIRUS || patt->filesize != fsize) {
free(section_hdr);
free(exe_sections);
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
}
break;
@@@ -946,7 -920,7 +917,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN;
}
@@@ -958,7 -932,7 +929,7 @@@
*ctx->virname = "Broken.Executable";
free(section_hdr);
free(exe_sections);
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
min = exe_sections[i].rva;
max = exe_sections[i].rva + exe_sections[i].rsz;
@@@ -969,7 -943,7 +940,7 @@@
*ctx->virname = "Broken.Executable";
free(section_hdr);
free(exe_sections);
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
if(exe_sections[i].rva < min)
min = exe_sections[i].rva;
@@@ -989,7 -963,7 +960,7 @@@
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN;
}
@@@ -1001,13 -975,11 +972,11 @@@
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);
+ if(disasmbuf((unsigned char*)epbuff, epsize, ndesc))
+ ret = cli_scandesc(ndesc, ctx, CL_TYPE_PE_DISASM, 1, NULL, AC_SCAN_VIR);
close(ndesc);
CLI_TMPUNLK();
free(tempfile);
@@@ -1019,7 -991,7 +988,7 @@@
if(overlays) {
int overlays_sz = fsize - overlays;
if(overlays_sz > 0) {
- ret = cli_scanishield(desc, ctx, overlays, overlays_sz);
+ ret = cli_scanishield(ctx, overlays, overlays_sz);
if(ret != CL_CLEAN) {
free(exe_sections);
return ret;
@@@ -1037,7 -1009,7 +1006,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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
}
}
@@@ -1120,7 -1092,7 +1089,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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n");
kzstate++;
@@@ -1141,25 -1113,25 +1110,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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return 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(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
}
}
@@@ -1172,15 -1144,9 +1141,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);
@@@ -1188,7 -1154,6 +1151,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;
}
@@@ -1207,17 -1172,15 +1169,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]==0x0ec && ((jump==0x83ec8b55 && code[6]==0x60) || (jump==0x81ec8b55 && !code[7] && !code[8])))) {
*ctx->virname = "W32.Polipos.A";
free(jumps);
free(exe_sections);
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
}
free(jumps);
@@@ -1234,7 -1197,7 +1194,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";
}
@@@ -1242,8 -1205,8 +1202,6 @@@
}
if (ret != CL_CLEAN) {
free(exe_sections);
-- if(ret == CL_VIRUS)
- return CL_VIRUS;
- return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS;
return ret;
}
}
@@@ -1266,6 -1229,7 +1224,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) {
@@@ -1274,29 -1238,20 +1233,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;
@@@ -1306,20 -1261,19 +1256,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;
@@@ -1327,13 -1281,13 +1276,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;
}
@@@ -1430,8 -1384,7 +1379,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;
@@@ -1439,9 -1392,7 +1387,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;
@@@ -1477,36 -1428,27 +1423,27 @@@
break;
}
- if((src = (char *) cli_malloc(ssize)) == NULL) {
- free(exe_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 + 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;
}
@@@ -1517,19 -1459,16 +1454,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;
}
@@@ -1542,8 -1481,8 +1476,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;
}
@@@ -1568,25 -1507,18 +1502,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;
+ gp = exe_sections[i + 1].raw - t;
- CLI_UNPSIZELIMITS("FSG", gp)
-
- 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;
}
@@@ -1596,13 -1528,11 +1523,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;
}
@@@ -1625,13 -1555,11 +1550,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;
}
@@@ -1639,25 -1567,15 +1562,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;
}
@@@ -1665,8 -1583,8 +1578,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 */
}
@@@ -1676,8 -1594,7 +1589,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);
@@@ -1687,7 -1604,6 +1599,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;
@@@ -1711,20 -1627,13 +1622,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;
}
@@@ -1745,13 -1654,11 +1649,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;
}
@@@ -1760,25 -1667,15 +1662,15 @@@
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;
}
@@@ -1787,8 -1684,8 +1679,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 */
}
@@@ -1809,25 -1706,17 +1701,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");
@@@ -1901,13 -1790,11 +1785,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));
@@@ -1975,7 -1862,7 +1857,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;
@@@ -2004,8 -1891,7 +1886,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);
@@@ -2069,8 -1955,7 +1950,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);
@@@ -2107,8 -1992,7 +1987,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);
@@@ -2116,9 -2000,8 +1995,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");
@@@ -2130,7 -2013,7 +2008,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);
@@@ -2162,9 -2045,8 +2040,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");
@@@ -2183,14 -2065,13 +2060,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;
}
@@@ -2199,11 -2080,9 +2075,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 */
@@@ -2215,39 -2094,31 +2089,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;
}
@@@ -2257,7 -2128,7 +2123,7 @@@
return CL_CLEAN;
}
- int cli_peheader(int desc, struct cli_exe_info *peinfo)
+ int cli_peheader(fmap_t *map, struct cli_exe_info *peinfo)
{
uint16_t e_magic; /* DOS signature ("MZ") */
uint32_t e_lfanew; /* address of new exe header */
@@@ -2270,24 -2141,18 +2136,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) {
@@@ -2295,10 -2160,7 +2155,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;
}
@@@ -2309,13 -2171,7 +2166,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;
@@@ -2333,26 -2189,29 +2184,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);
}
@@@ -2378,7 -2237,7 +2232,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);
@@@ -2386,6 -2245,7 +2240,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 0b5bc80,5bb0ddb..74bda9d
--- a/libclamav/phishcheck.c
+++ b/libclamav/phishcheck.c
@@@ -322,6 -322,9 +322,6 @@@ static int build_regex(regex_t* preg,co
rc = cli_regcomp(preg,regex,REG_EXTENDED|REG_ICASE|(nosub ? REG_NOSUB :0));
if(rc) {
-#ifdef C_WINDOWS
- cli_errmsg("Phishcheck: Error in compiling regex, disabling phishing checks\n");
-#else
size_t buflen = cli_regerror(rc,preg,NULL,0);
char *errbuf = cli_malloc(buflen);
@@@ -331,6 -334,7 +331,6 @@@
free(errbuf);
} else
cli_errmsg("Phishcheck: Error in compiling regex, disabling phishing checks. Additionally an Out-of-memory error was encountered while generating a detailed error message\n");
-#endif
return 1;
}
return CL_SUCCESS;
@@@ -1194,13 -1198,13 +1194,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, NULL, &rlist->hostkey_prefix,0,-1,NULL) == CL_VIRUS) {
- if (cli_bm_scanbuff(sha256_dig, 4, &virname, &rlist->hostkey_prefix,0,NULL,NULL) == CL_VIRUS) {
++ if (cli_bm_scanbuff(sha256_dig, 4, &virname, NULL, &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, NULL, &rlist->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
- if (cli_bm_scanbuff(sha256_dig, 32, &virname, &rlist->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
++ if (cli_bm_scanbuff(sha256_dig, 32, &virname, NULL, &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 a90cc89,df19a53..6771ece
--- 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, NULL, &matcher->sha256_hashes,0,-1,NULL) == CL_VIRUS) {
- cli_bm_scanbuff(pat->pattern, 32, &vname, &matcher->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
++ cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
if (*vname == 'W') {
/* hash is whitelisted in local.gdb */
cli_dbgmsg("Skipping hash %s\n", pattern);
diff --combined libclamav/scanners.c
index 50ba696,e2b44dd..e8d890b
--- a/libclamav/scanners.c
+++ b/libclamav/scanners.c
@@@ -22,6 -22,7 +22,7 @@@
#include "clamav-config.h"
#endif
+ #include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@@ -35,7 -36,14 +36,7 @@@
#include <sys/param.h>
#endif
#include <fcntl.h>
-#ifndef C_WINDOWS
#include <dirent.h>
-#include <netinet/in.h>
-#endif
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
#define DCONF_ARCH ctx->dconf->archive
#define DCONF_DOC ctx->dconf->doc
@@@ -81,6 -89,7 +82,7 @@@
#include "macho.h"
#include "ishield.h"
#include "7z.h"
+ #include "fmap.h"
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
@@@ -115,7 -124,9 +117,7 @@@ static int cli_scandir(const char *dirn
#else
while((dent = readdir(dd))) {
#endif
-#if (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
if(dent->d_ino)
-#endif
{
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
/* build the full name */
@@@ -125,7 -136,7 +127,7 @@@
return CL_EMEM;
}
- sprintf(fname, "%s/%s", dirname, dent->d_name);
+ sprintf(fname, "%s"PATHSEP"%s", dirname, dent->d_name);
/* stat the file */
if(lstat(fname, &statbuf) != -1) {
@@@ -209,7 -220,7 +211,7 @@@ static int cli_unrar_scanmetadata(int d
if(mdata) {
*ctx->virname = mdata->virname;
- return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
if(DETECT_ENCRYPTED && metadata->encrypted) {
@@@ -421,77 -432,72 +423,72 @@@ static int cli_scanarj(int desc, cli_ct
return ret;
}
- static int cli_scangzip(int desc, cli_ctx *ctx)
+ static int cli_scangzip(cli_ctx *ctx)
{
- int fd, bytes, ret = CL_CLEAN;
- unsigned long int size = 0;
- char *buff;
+ int fd, ret = CL_CLEAN;
+ unsigned char buff[FILEBUFF];
char *tmpname;
- gzFile gd;
-
-
+ z_stream z;
+ size_t at = 0;
+ fmap_t *map = *ctx->fmap;
+
cli_dbgmsg("in cli_scangzip()\n");
- if((gd = gzdopen(dup(desc), "rb")) == NULL) {
- cli_dbgmsg("GZip: Can't open descriptor %d\n", desc);
- return CL_EOPEN;
+ memset(&z, 0, sizeof(z));
+ if(inflateInit2(&z, MAX_WBITS + 16) != Z_OK) {
+ cli_dbgmsg("GZip: InflateInit failed\n");
+ return CL_CLEAN;
}
- if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd))) {
+ if((ret = cli_gentempfd(ctx->engine->tmpdir, &tmpname, &fd)) != CL_SUCCESS) {
cli_dbgmsg("GZip: Can't generate temporary file.\n");
- gzclose(gd);
+ inflateEnd(&z);
return ret;
}
- if(!(buff = (char *) cli_malloc(FILEBUFF))) {
- cli_dbgmsg("GZip: Unable to malloc %u bytes.\n", FILEBUFF);
- gzclose(gd);
- close(fd);
- if(!ctx->engine->keeptmp) {
- if(cli_unlink(tmpname)) {
- free(tmpname);
+ while (at < map->len) {
+ unsigned int bytes = MIN(map->len - at, map->pgsz);
+ if(!(z.next_in = fmap_need_off_once(map, at, bytes))) {
+ cli_dbgmsg("GZip: Can't read %u bytes @ %lu.\n", bytes, (long unsigned)at);
+ inflateEnd(&z);
+ close(fd);
+ if (cli_unlink(tmpname)) {
+ free(tmpname);
return CL_EUNLINK;
}
+ free(tmpname);
+ return CL_EREAD;
}
- return CL_EMEM;
- }
-
- while((bytes = gzread(gd, buff, FILEBUFF)) > 0) {
- size += bytes;
-
- if(cli_checklimits("GZip", ctx, size + FILEBUFF, 0, 0)!=CL_CLEAN)
- break;
-
- if(cli_writen(fd, buff, bytes) != bytes) {
- cli_dbgmsg("GZip: Can't write to file.\n");
- close(fd);
- if(!ctx->engine->keeptmp) {
- if (cli_unlink(tmpname)) {
+ at += bytes;
+ z.avail_in = bytes;
+ do {
+ int inf;
+ z.avail_out = sizeof(buff);
+ z.next_out = buff;
+ inf = inflate(&z, Z_NO_FLUSH);
+ if(inf != Z_OK && inf != Z_STREAM_END && inf != Z_BUF_ERROR) {
+ cli_dbgmsg("GZip: Bad stream.\n");
+ at = map->len;
+ break;
+ }
+ if(cli_writen(fd, buff, sizeof(buff) - z.avail_out) < 0) {
+ inflateEnd(&z);
+ close(fd);
+ if (cli_unlink(tmpname)) {
free(tmpname);
return CL_EUNLINK;
}
}
- free(tmpname);
- gzclose(gd);
- free(buff);
- return CL_EWRITE;
- }
+ if(inf == Z_STREAM_END) {
+ at -= z.avail_in;
+ inflateReset(&z);
+ break;
+ }
+ } while (z.avail_out == 0);
}
- free(buff);
- gzclose(gd);
+ inflateEnd(&z);
- if(ret == CL_VIRUS) {
- close(fd);
- if(!ctx->engine->keeptmp)
- if (cli_unlink(tmpname)) ret = CL_EUNLINK;
- free(tmpname);
- return ret;
- }
-
- lseek(fd, 0, SEEK_SET);
if((ret = cli_magic_scandesc(fd, ctx)) == CL_VIRUS ) {
cli_dbgmsg("GZip: Infected with %s\n", *ctx->virname);
close(fd);
@@@ -501,14 -507,13 +498,13 @@@
return CL_EUNLINK;
}
}
- free(tmpname);
+ free(tmpname);
return CL_VIRUS;
}
close(fd);
if(!ctx->engine->keeptmp)
if (cli_unlink(tmpname)) ret = CL_EUNLINK;
- free(tmpname);
-
+ free(tmpname);
return ret;
}
@@@ -741,7 -746,7 +737,7 @@@ static int cli_vba_scandir(const char *
for(i = 0; i < vba_project->count; i++) {
for(j = 0; (unsigned int)j < vba_project->colls[i]; j++) {
- snprintf(vbaname, 1024, "%s/%s_%u", vba_project->dir, vba_project->name[i], j);
+ snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", vba_project->dir, vba_project->name[i], j);
vbaname[sizeof(vbaname)-1] = '\0';
fd = open(vbaname, O_RDONLY|O_BINARY);
if(fd == -1) continue;
@@@ -775,7 -780,7 +771,7 @@@
if(ret == CL_CLEAN && (hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
while(hashcnt--) {
- snprintf(vbaname, 1024, "%s/%s_%u", dirname, hash, hashcnt);
+ snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
vbaname[sizeof(vbaname)-1] = '\0';
fd = open(vbaname, O_RDONLY|O_BINARY);
if (fd == -1) continue;
@@@ -793,7 -798,7 +789,7 @@@
if (ret == CL_CLEAN && (hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
while(hashcnt--) {
- snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
+ snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
vbaname[sizeof(vbaname)-1] = '\0';
fd = open(vbaname, O_RDONLY|O_BINARY);
if (fd == -1) continue;
@@@ -840,7 -845,7 +836,7 @@@
/* Check directory for embedded OLE objects */
hashcnt = uniq_get(U, "_1_ole10native", 14, &hash);
while(hashcnt--) {
- snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
+ snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
vbaname[sizeof(vbaname)-1] = '\0';
fd = open(vbaname, O_RDONLY|O_BINARY);
@@@ -865,7 -870,9 +861,7 @@@
#else
while((dent = readdir(dd))) {
#endif
-#if (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
if(dent->d_ino)
-#endif
{
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) {
/* build the full name */
@@@ -874,7 -881,7 +870,7 @@@
ret = CL_EMEM;
break;
}
- sprintf(fullname, "%s/%s", dirname, dent->d_name);
+ sprintf(fullname, "%s"PATHSEP"%s", dirname, dent->d_name);
/* stat the file */
if(lstat(fullname, &statbuf) != -1) {
@@@ -898,24 -905,19 +894,19 @@@
return ret;
}
- static int cli_scanhtml(int desc, cli_ctx *ctx)
+ static int cli_scanhtml(cli_ctx *ctx)
{
char *tempname, fullname[1024];
int ret=CL_CLEAN, fd;
- struct stat sb;
+ fmap_t *map = *ctx->fmap;
cli_dbgmsg("in cli_scanhtml()\n");
- if(fstat(desc, &sb) == -1) {
- cli_errmsg("cli_scanhtml: fstat() failed for descriptor %d\n", desc);
- return CL_ESTAT;
- }
-
/* Because HTML detection is FP-prone and html_normalise_fd() needs to
* mmap the file don't normalise files larger than 10 MB.
*/
- if(sb.st_size > 10485760) {
+ if(map->len > 10485760) {
cli_dbgmsg("cli_scanhtml: exiting (file larger than 10 MB)\n");
return CL_CLEAN;
}
@@@ -931,18 -933,18 +922,18 @@@
cli_dbgmsg("cli_scanhtml: using tempdir %s\n", tempname);
- html_normalise_fd(desc, tempname, NULL, ctx->dconf);
+ html_normalise_map(map, tempname, NULL, ctx->dconf);
- snprintf(fullname, 1024, "%s/nocomment.html", tempname);
+ snprintf(fullname, 1024, "%s"PATHSEP"nocomment.html", tempname);
fd = open(fullname, O_RDONLY|O_BINARY);
if (fd >= 0) {
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
close(fd);
}
- if(ret == CL_CLEAN && sb.st_size < 2097152) {
+ if(ret == CL_CLEAN && map->len < 2097152) {
/* limit to 2 MB, we're not interesting in scanning large files in notags form */
/* TODO: don't even create notags if file is over 2 MB */
- snprintf(fullname, 1024, "%s/notags.html", tempname);
+ snprintf(fullname, 1024, "%s"PATHSEP"notags.html", tempname);
fd = open(fullname, O_RDONLY|O_BINARY);
if(fd >= 0) {
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
@@@ -951,7 -953,7 +942,7 @@@
}
if(ret == CL_CLEAN) {
- snprintf(fullname, 1024, "%s/javascript", tempname);
+ snprintf(fullname, 1024, "%s"PATHSEP"javascript", tempname);
fd = open(fullname, O_RDONLY|O_BINARY);
if(fd >= 0) {
ret = cli_scandesc(fd, ctx, CL_TYPE_HTML, 0, NULL, AC_SCAN_VIR);
@@@ -964,7 -966,7 +955,7 @@@
}
if (ret == CL_CLEAN) {
- snprintf(fullname, 1024, "%s/rfc2397", tempname);
+ snprintf(fullname, 1024, "%s"PATHSEP"rfc2397", tempname);
ret = cli_scandir(fullname, ctx);
}
@@@ -975,30 -977,25 +966,25 @@@
return ret;
}
- static int cli_scanscript(int desc, cli_ctx *ctx)
+ static int cli_scanscript(cli_ctx *ctx)
{
- unsigned char buff[FILEBUFF];
+ unsigned char *buff;
unsigned char* normalized;
struct text_norm_state state;
struct stat sb;
char *tmpname = NULL;
int ofd = -1, ret;
- ssize_t nread;
const struct cli_matcher *troot = ctx->engine->root[7];
uint32_t maxpatlen = troot ? troot->maxpatlen : 0, offset = 0;
struct cli_matcher *groot = ctx->engine->root[0];
struct cli_ac_data gmdata, tmdata;
struct cli_ac_data *mdata[2];
+ fmap_t *map = *ctx->fmap;
+ size_t at = 0;
cli_dbgmsg("in cli_scanscript()\n");
- if(fstat(desc, &sb) == -1) {
- cli_errmsg("cli_scanscript: fstat() failed for descriptor %d\n", desc);
- return CL_ESTAT;
- }
-
- /* don't normalize files that are too large */
- if(sb.st_size > 5242880) {
+ if(map->len > 5242880) {
cli_dbgmsg("cli_scanscript: exiting (file larger than 5 MB)\n");
return CL_CLEAN;
}
@@@ -1030,39 -1027,37 +1016,37 @@@
mdata[0] = &tmdata;
mdata[1] = &gmdata;
- do {
- nread = cli_readn(desc, buff, sizeof(buff));
- if(nread <= 0 || state.out_pos + nread > state.out_len) {
- /* flush if error/EOF, or too little buffer space left */
- if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
- cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
- close(ofd);
- ofd = -1;
- /* we can continue to scan in memory */
- }
- /* when we flush the buffer also scan */
- if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
- ret = CL_VIRUS;
- if(ofd != -1)
- ret = cli_checkfp(ofd, ctx) ? CL_CLEAN : CL_VIRUS;
- break;
- }
- if(ctx->scanned)
- *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
- offset += state.out_pos;
- /* carry over maxpatlen from previous buffer */
- if (state.out_pos > maxpatlen)
- memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);
- text_normalize_reset(&state);
- state.out_pos = maxpatlen;
+ while(1) {
+ size_t len = MIN(map->pgsz, map->len - at);
+ buff = fmap_need_off_once(map, at, len);
+ at += len;
+ if(!buff || !len || state.out_pos + len > state.out_len) {
+ /* flush if error/EOF, or too little buffer space left */
+ if((ofd != -1) && (write(ofd, state.out, state.out_pos) == -1)) {
+ cli_errmsg("cli_scanscript: can't write to file %s\n",tmpname);
+ close(ofd);
+ ofd = -1;
+ /* we can continue to scan in memory */
}
- if(nread > 0 && (text_normalize_buffer(&state, buff, nread) != nread)) {
- cli_dbgmsg("cli_scanscript: short read during normalizing\n");
+ /* when we flush the buffer also scan */
+ if(cli_scanbuff(state.out, state.out_pos, offset, ctx, CL_TYPE_TEXT_ASCII, mdata) == CL_VIRUS) {
+ ret = CL_VIRUS;
+ break;
}
- /* used a do {}while() here, since we need to flush our buffers at the end,
- * and using while(){} loop would mean code duplication */
- } while (nread > 0);
-
+ if(ctx->scanned)
+ *ctx->scanned += state.out_pos / CL_COUNT_PRECISION;
+ offset += state.out_pos;
+ /* carry over maxpatlen from previous buffer */
+ if (state.out_pos > maxpatlen)
+ memmove(state.out, state.out + state.out_pos - maxpatlen, maxpatlen);
+ text_normalize_reset(&state);
+ state.out_pos = maxpatlen;
+ }
+ if(!len) break;
+ if(text_normalize_buffer(&state, buff, len) != len) {
+ cli_dbgmsg("cli_scanscript: short read during normalizing\n");
+ }
+ }
cli_ac_freedata(&tmdata);
cli_ac_freedata(&gmdata);
if(ctx->engine->keeptmp) {
@@@ -1074,11 -1069,12 +1058,12 @@@
return ret;
}
- static int cli_scanhtml_utf16(int desc, cli_ctx *ctx)
+ static int cli_scanhtml_utf16(cli_ctx *ctx)
{
- char *tempname, buff[512], *decoded;
+ char *tempname, *decoded, *buff;
int ret = CL_CLEAN, fd, bytes;
-
+ size_t at = 0;
+ fmap_t *map = *ctx->fmap;
cli_dbgmsg("in cli_scanhtml_utf16()\n");
@@@ -1093,7 -1089,15 +1078,15 @@@
cli_dbgmsg("cli_scanhtml_utf16: using tempfile %s\n", tempname);
- while((bytes = read(desc, buff, sizeof(buff))) > 0) {
+ while(at < map->len) {
+ bytes = MIN(map->len - at, map->pgsz * 16);
+ if(!(buff = fmap_need_off_once(map, at, bytes))) {
+ close(fd);
+ cli_unlink(tempname);
+ free(tempname);
+ return CL_EREAD;
+ }
+ at += bytes;
decoded = cli_utf16toascii(buff, bytes);
if(decoded) {
if(write(fd, decoded, strlen(decoded)) == -1) {
@@@ -1108,8 -1112,14 +1101,14 @@@
}
}
- lseek(fd, 0, SEEK_SET);
- ret = cli_scanhtml(fd, ctx);
+ *ctx->fmap = fmap(fd, 0, 0);
+ if(*ctx->fmap) {
+ ret = cli_scanhtml(ctx);
+ funmap(*ctx->fmap);
+ } else
+ cli_errmsg("cli_scanhtml_utf16: fmap of %s failed\n", tempname);
+
+ *ctx->fmap = map;
close(fd);
if(!ctx->engine->keeptmp) {
@@@ -1121,7 -1131,7 +1120,7 @@@
return ret;
}
- static int cli_scanole2(int desc, cli_ctx *ctx)
+ static int cli_scanole2(cli_ctx *ctx)
{
char *dir;
int ret = CL_CLEAN;
@@@ -1142,7 -1152,7 +1141,7 @@@
return CL_ETMPDIR;
}
- ret = cli_ole2_extract(desc, dir, ctx, &vba);
+ ret = cli_ole2_extract(dir, ctx, &vba);
if(ret!=CL_CLEAN && ret!=CL_VIRUS) {
cli_dbgmsg("OLE2: %s\n", cl_strerror(ret));
if(!ctx->engine->keeptmp)
@@@ -1195,7 -1205,7 +1194,7 @@@ static int cli_scantar(int desc, cli_ct
return ret;
}
- static int cli_scanbinhex(int desc, cli_ctx *ctx)
+ static int cli_scanbinhex(cli_ctx *ctx)
{
char *dir;
int ret = CL_CLEAN;
@@@ -1213,7 -1223,7 +1212,7 @@@
return CL_ETMPDIR;
}
- if((ret = cli_binhex(dir, desc)))
+ if((ret = cli_binhex(dir, *ctx->fmap)))
cli_dbgmsg("Binhex: %s\n", cl_strerror(ret));
else
ret = cli_scandir(dir, ctx);
@@@ -1253,11 -1263,11 +1252,11 @@@ static int cli_scanmschm(int desc, cli_
}
do {
- ret = cli_chm_prepare_file(desc, dir, &metadata);
+ ret = cli_chm_prepare_file(&metadata);
if (ret != CL_SUCCESS) {
break;
}
- ret = cli_chm_extract_file(desc, dir, &metadata, ctx);
+ ret = cli_chm_extract_file(dir, &metadata, ctx);
if (ret == CL_SUCCESS) {
lseek(metadata.ofd, 0, SEEK_SET);
rc = cli_magic_scandesc(metadata.ofd, ctx);
@@@ -1316,8 -1326,10 +1315,8 @@@ static int cli_scanriff(int desc, cli_c
int ret = CL_CLEAN;
if(cli_check_riff_exploit(desc) == 2) {
- if(!cli_checkfp(desc, ctx)) {
- ret = CL_VIRUS;
- *ctx->virname = "Exploit.W32.MS05-002";
- }
+ ret = CL_VIRUS;
+ *ctx->virname = "Exploit.W32.MS05-002";
}
return ret;
@@@ -1328,8 -1340,10 +1327,8 @@@ static int cli_scanjpeg(int desc, cli_c
int ret = CL_CLEAN;
if(cli_check_jpeg_exploit(desc, ctx) == 1) {
- if(!cli_checkfp(desc, ctx)) {
- ret = CL_VIRUS;
- *ctx->virname = "Exploit.W32.MS04-028";
- }
+ ret = CL_VIRUS;
+ *ctx->virname = "Exploit.W32.MS04-028";
}
return ret;
@@@ -1420,7 -1434,7 +1419,7 @@@ static int cli_scancryptff(int desc, cl
return ret;
}
- static int cli_scanpdf(int desc, cli_ctx *ctx, off_t offset)
+ static int cli_scanpdf(cli_ctx *ctx, off_t offset)
{
int ret;
char *dir = cli_gentemp(ctx->engine->tmpdir);
@@@ -1434,7 -1448,7 +1433,7 @@@
return CL_ETMPDIR;
}
- ret = cli_pdf(dir, desc, ctx, offset);
+ ret = cli_pdf(dir, ctx, offset);
if(!ctx->engine->keeptmp)
cli_rmdirs(dir);
@@@ -1469,7 -1483,7 +1468,7 @@@ static int cli_scantnef(int desc, cli_c
return ret;
}
- static int cli_scanuuencoded(int desc, cli_ctx *ctx)
+ static int cli_scanuuencoded(cli_ctx *ctx)
{
int ret;
char *dir = cli_gentemp(ctx->engine->tmpdir);
@@@ -1483,7 -1497,7 +1482,7 @@@
return CL_ETMPDIR;
}
- ret = cli_uuencode(dir, desc);
+ ret = cli_uuencode(dir, *ctx->fmap);
if(ret == CL_CLEAN)
ret = cli_scandir(dir, ctx);
@@@ -1591,13 -1605,13 +1590,13 @@@ static int cli_scan_structured(int desc
if(cc_count != 0 && cc_count >= ctx->engine->min_cc_count) {
cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
*ctx->virname = "Structured.CreditCardNumber";
- return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
if(ssn_count != 0 && ssn_count >= ctx->engine->min_ssn_count) {
cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
*ctx->virname = "Structured.SSN";
- return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ return CL_VIRUS;
}
return CL_CLEAN;
@@@ -1669,14 -1683,14 +1668,14 @@@ static int cli_scanembpe(int desc, cli_
return CL_CLEAN;
}
- static int cli_scanraw(int desc, cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype)
+ static int cli_scanraw(cli_ctx *ctx, cli_file_t type, uint8_t typercg, cli_file_t *dettype)
{
int ret = CL_CLEAN, nret = CL_CLEAN;
struct cli_matched_type *ftoffset = NULL, *fpt;
uint32_t lastzip, lastrar;
struct cli_exe_info peinfo;
unsigned int acmode = AC_SCAN_VIR, break_loop = 0;
- struct stat sb;
+ fmap_t *map = *ctx->fmap;
if(ctx->engine->maxreclevel && ctx->recursion >= ctx->engine->maxreclevel)
@@@ -1685,12 -1699,7 +1684,7 @@@
if(typercg)
acmode |= AC_SCAN_FT;
- if(lseek(desc, 0, SEEK_SET) < 0) {
- cli_errmsg("cli_scanraw: lseek() failed\n");
- return CL_ESEEK;
- }
-
- ret = cli_scandesc(desc, ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
+ ret = cli_fmap_scandesc(ctx, type == CL_TYPE_TEXT_ASCII ? 0 : type, 0, &ftoffset, acmode);
if(ret >= CL_TYPENO) {
ctx->recursion++;
@@@ -1714,73 -1723,72 +1708,72 @@@
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
if(type != CL_TYPE_RAR && have_rar && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_RAR)) {
cli_dbgmsg("RAR/RAR-SFX signature found at %u\n", (unsigned int) fpt->offset);
- nret = cli_scanrar(desc, ctx, fpt->offset, &lastrar);
+ nret = cli_scanrar(map->fd, ctx, fpt->offset, &lastrar);
}
break;
case CL_TYPE_ZIPSFX:
if(type != CL_TYPE_ZIP && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_ZIP)) {
cli_dbgmsg("ZIP/ZIP-SFX signature found at %u\n", (unsigned int) fpt->offset);
- nret = cli_unzip_single(desc, ctx, fpt->offset);
+ nret = cli_unzip_single(ctx, fpt->offset);
}
break;
case CL_TYPE_CABSFX:
if(type != CL_TYPE_MSCAB && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_CAB)) {
cli_dbgmsg("CAB/CAB-SFX signature found at %u\n", (unsigned int) fpt->offset);
- nret = cli_scanmscab(desc, ctx, fpt->offset);
+ nret = cli_scanmscab(map->fd, ctx, fpt->offset);
}
break;
case CL_TYPE_ARJSFX:
if(type != CL_TYPE_ARJ && SCAN_ARCHIVE && fpt->offset < 102400 && (DCONF_ARCH & ARCH_CONF_ARJ)) {
cli_dbgmsg("ARJ-SFX signature found at %u\n", (unsigned int) fpt->offset);
- nret = cli_scanarj(desc, ctx, fpt->offset, &lastrar);
+ nret = cli_scanarj(map->fd, ctx, fpt->offset, &lastrar);
}
break;
case CL_TYPE_NULSFT:
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_NSIS) && fpt->offset > 4) {
cli_dbgmsg("NSIS signature found at %u\n", (unsigned int) fpt->offset-4);
- nret = cli_scannulsft(desc, ctx, fpt->offset - 4);
+ nret = cli_scannulsft(map->fd, ctx, fpt->offset - 4);
}
break;
case CL_TYPE_AUTOIT:
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_AUTOIT)) {
cli_dbgmsg("AUTOIT signature found at %u\n", (unsigned int) fpt->offset);
- nret = cli_scanautoit(desc, ctx, fpt->offset + 23);
+ nret = cli_scanautoit(map->fd, ctx, fpt->offset + 23);
}
break;
case CL_TYPE_ISHIELD_MSI:
if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE && (DCONF_ARCH & ARCH_CONF_ISHIELD)) {
cli_dbgmsg("ISHIELD-MSI signature found at %u\n", (unsigned int) fpt->offset);
- nret = cli_scanishield_msi(desc, ctx, fpt->offset + 14);
+ nret = cli_scanishield_msi(ctx, fpt->offset + 14);
}
break;
case CL_TYPE_PDF:
if(type != CL_TYPE_PDF && SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF)) {
cli_dbgmsg("PDF signature found at %u\n", (unsigned int) fpt->offset);
- nret = cli_scanpdf(desc, ctx, fpt->offset);
+ nret = cli_scanpdf(ctx, fpt->offset);
}
break;
case CL_TYPE_MSEXE:
if(SCAN_PE && (type == CL_TYPE_MSEXE || type == CL_TYPE_ZIP || type == CL_TYPE_MSOLE2) && ctx->dconf->pe) {
- fstat(desc, &sb);
- if(sb.st_size > 10485760)
+ if(map->len > 10485760)
break;
memset(&peinfo, 0, sizeof(struct cli_exe_info));
peinfo.offset = fpt->offset;
- lseek(desc, fpt->offset, SEEK_SET);
- if(cli_peheader(desc, &peinfo) == 0) {
+ lseek(map->fd, fpt->offset, SEEK_SET);
+ if(cli_peheader(map, &peinfo) == 0) {
cli_dbgmsg("*** Detected embedded PE file at %u ***\n", (unsigned int) fpt->offset);
if(peinfo.section)
free(peinfo.section);
- lseek(desc, fpt->offset, SEEK_SET);
- nret = cli_scanembpe(desc, ctx);
+ lseek(map->fd, fpt->offset, SEEK_SET);
+ nret = cli_scanembpe(map->fd, ctx);
break_loop = 1; /* we can stop here and other
* embedded executables will
* be found recursively
@@@ -1805,13 -1813,13 +1798,13 @@@
case CL_TYPE_HTML:
if(SCAN_HTML && type == CL_TYPE_TEXT_ASCII && (DCONF_DOC & DOC_CONF_HTML)) {
*dettype = CL_TYPE_HTML;
- nret = cli_scanhtml(desc, ctx);
+ nret = cli_scanhtml(ctx);
}
break;
case CL_TYPE_MAIL:
if(SCAN_MAIL && type == CL_TYPE_TEXT_ASCII && (DCONF_MAIL & MAIL_CONF_MBOX))
- nret = cli_scanmail(desc, ctx);
+ nret = cli_scanmail(map->fd, ctx);
break;
default:
@@@ -1828,7 -1836,7 +1821,7 @@@
}
if(ret == CL_VIRUS)
- cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
+ cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, map->fd);
return ret;
}
@@@ -1869,30 -1877,40 +1862,41 @@@ int cli_magic_scandesc(int desc, cli_ct
if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
return CL_CLEAN;
+ ctx->fmap++;
+ if(!(*ctx->fmap = fmap(desc, 0, sb.st_size))) {
+ cli_errmsg("CRITICAL: fmap() failed\n");
+ return CL_EMEM;
+ }
+
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_fmap_scandesc(ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
- return CL_VIRUS;
- }
+ funmap(*ctx->fmap);
+ ctx->fmap--;
return ret;
}
- lseek(desc, 0, SEEK_SET);
- type = cli_filetype2(desc, ctx->engine);
+ type = cli_filetype2(*ctx->fmap, ctx->engine); /* FIXMEFMAP: port to fmap */
if(type == CL_TYPE_ERROR) {
cli_dbgmsg("cli_magic_scandesc: cli_filetype2 returned CL_TYPE_ERROR\n");
+ funmap(*ctx->fmap);
+ ctx->fmap--;
return CL_EREAD;
}
- lseek(desc, 0, SEEK_SET);
+ lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
if(type != CL_TYPE_IGNORED && ctx->engine->sdb) {
- if((ret = cli_scanraw(desc, ctx, type, 0, &dettype)) == CL_VIRUS)
- return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
- lseek(desc, 0, SEEK_SET);
+ if((ret = cli_scanraw(ctx, type, 0, &dettype)) == CL_VIRUS) {
++ ret = cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ funmap(*ctx->fmap);
+ ctx->fmap--;
- return CL_VIRUS;
++ return ret;
+ }
+ lseek(desc, 0, SEEK_SET); /* FIXMEFMAP: remove ? */
}
ctx->container_type = 0;
@@@ -1908,12 -1926,12 +1912,12 @@@
case CL_TYPE_ZIP:
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP))
- ret = cli_unzip(desc, ctx);
+ ret = cli_unzip(ctx);
break;
case CL_TYPE_GZ:
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GZ))
- ret = cli_scangzip(desc, ctx);
+ ret = cli_scangzip(ctx);
break;
case CL_TYPE_BZ:
@@@ -1947,17 -1965,17 +1951,17 @@@
case CL_TYPE_HTML:
if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
- ret = cli_scanhtml(desc, ctx);
+ ret = cli_scanhtml(ctx);
break;
case CL_TYPE_HTML_UTF16:
if(SCAN_HTML && (DCONF_DOC & DOC_CONF_HTML))
- ret = cli_scanhtml_utf16(desc, ctx);
+ ret = cli_scanhtml_utf16(ctx);
break;
case CL_TYPE_SCRIPT:
if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
- ret = cli_scanscript(desc, ctx);
+ ret = cli_scanscript(ctx);
break;
case CL_TYPE_RTF:
@@@ -1977,7 -1995,7 +1981,7 @@@
case CL_TYPE_UUENCODED:
if(DCONF_OTHER & OTHER_CONF_UUENC)
- ret = cli_scanuuencoded(desc, ctx);
+ ret = cli_scanuuencoded(ctx);
break;
case CL_TYPE_MSCHM:
@@@ -1987,7 -2005,7 +1991,7 @@@
case CL_TYPE_MSOLE2:
if(SCAN_OLE2 && (DCONF_ARCH & ARCH_CONF_OLE2))
- ret = cli_scanole2(desc, ctx);
+ ret = cli_scanole2(ctx);
break;
case CL_TYPE_7Z:
@@@ -2027,7 -2045,7 +2031,7 @@@
case CL_TYPE_BINHEX:
if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BINHEX))
- ret = cli_scanbinhex(desc, ctx);
+ ret = cli_scanbinhex(ctx);
break;
case CL_TYPE_SCRENC:
@@@ -2047,7 -2065,7 +2051,7 @@@
case CL_TYPE_PDF: /* FIXMELIMITS: pdf should be an archive! */
if(SCAN_PDF && (DCONF_DOC & DOC_CONF_PDF))
- ret = cli_scanpdf(desc, ctx, 0);
+ ret = cli_scanpdf(ctx, 0);
break;
case CL_TYPE_CRYPTFF:
@@@ -2057,17 -2075,17 +2061,17 @@@
case CL_TYPE_ELF:
if(SCAN_ELF && ctx->dconf->elf)
- ret = cli_scanelf(desc, ctx);
+ ret = cli_scanelf(ctx);
break;
case CL_TYPE_MACHO:
if(ctx->dconf->macho)
- ret = cli_scanmacho(desc, ctx, NULL);
+ ret = cli_scanmacho(ctx, NULL);
break;
case CL_TYPE_MACHO_UNIBIN:
if(ctx->dconf->macho)
- ret = cli_scanmacho_unibin(desc, ctx);
+ ret = cli_scanmacho_unibin(ctx);
break;
case CL_TYPE_SIS:
@@@ -2094,8 -2112,11 +2098,12 @@@
ctx->recursion--;
ctx->container_type = current_container;
- if(ret == CL_VIRUS)
- return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ if(ret == CL_VIRUS) {
++ ret = cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ funmap(*ctx->fmap);
+ ctx->fmap--;
- return CL_VIRUS;
++ return ret;
+ }
if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
if(sb.st_size > 1048576) {
@@@ -2106,8 -2127,11 +2114,12 @@@
/* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && !ctx->engine->sdb) {
- if(cli_scanraw(desc, ctx, type, typercg, &dettype) == CL_VIRUS)
- return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ if(cli_scanraw(ctx, type, typercg, &dettype) == CL_VIRUS) {
++ ret = cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+ funmap(*ctx->fmap);
+ ctx->fmap--;
- return CL_VIRUS;
++ return ret;
+ }
}
ctx->recursion++;
@@@ -2118,7 -2142,7 +2130,7 @@@
case CL_TYPE_TEXT_UTF16LE:
case CL_TYPE_TEXT_UTF8:
if((DCONF_DOC & DOC_CONF_SCRIPT) && dettype != CL_TYPE_HTML)
- ret = cli_scanscript(desc, ctx);
+ ret = cli_scanscript(ctx);
if(ret != CL_VIRUS && ctx->container_type == CL_TYPE_MAIL) {
lseek(desc, 0, SEEK_SET);
ret = cli_scandesc(desc, ctx, CL_TYPE_MAIL, 0, NULL, AC_SCAN_VIR);
@@@ -2129,17 -2153,16 +2141,19 @@@
*/
case CL_TYPE_MSEXE:
if(SCAN_PE && ctx->dconf->pe)
- ret = cli_scanpe(desc, ctx);
+ ret = cli_scanpe(ctx);
break;
default:
break;
}
ctx->recursion--;
+ funmap(*ctx->fmap);
+ ctx->fmap--;
+ if(ret == CL_VIRUS)
+ return cli_checkfp(desc, ctx) ? CL_CLEAN : CL_VIRUS;
+
switch(ret) {
case CL_EFORMAT:
case CL_EMAXREC:
@@@ -2165,8 -2188,15 +2179,15 @@@ int cl_scandesc(int desc, const char **
ctx.found_possibly_unwanted = 0;
ctx.container_type = 0;
ctx.dconf = (struct cli_dconf *) engine->dconf;
+ ctx.fmap = cli_calloc(sizeof(fmap_t *), ctx.engine->maxreclevel + 1);
+ if(!ctx.fmap)
+ return CL_EMEM;
+ ctx.fmap--;
rc = cli_magic_scandesc(desc, &ctx);
+
+ ctx.fmap++;
+ free(ctx.fmap);
if(rc == CL_CLEAN && ctx.found_possibly_unwanted)
rc = CL_VIRUS;
return rc;
@@@ -2211,7 -2241,6 +2232,6 @@@ int cl_scanfile(const char *filename, c
{
int fd, ret;
-
if((fd = open(filename, O_RDONLY|O_BINARY)) == -1)
return CL_EOPEN;
diff --combined libclamav/unzip.c
index 47c8cf7,1376996..bcc8e32
--- a/libclamav/unzip.c
+++ b/libclamav/unzip.c
@@@ -34,10 -34,8 +34,7 @@@
#include <string.h>
#endif
#include <stdlib.h>
-
#include <stdio.h>
- #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
- #include <sys/mman.h>
- #endif
#include <zlib.h>
#include "inflate64.h"
@@@ -50,23 -48,20 +47,15 @@@
#include "clamav.h"
#include "scanners.h"
#include "matcher.h"
+ #include "fmap.h"
#define UNZIP_PRIVATE
#include "unzip.h"
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-
static int wrap_inflateinit2(void *a, int b) {
return inflateInit2(a, b);
}
- static inline void destroy_map(void *map, size_t fsize) {
- #if HAVE_MMAP
- munmap(map, fsize);
- #else
- free(map);
- #endif
- }
-
-
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) {
char name[1024], obuf[BUFSIZ];
char *tempfile = name;
@@@ -74,7 -69,7 +63,7 @@@
unsigned int res=1, written=0;
if(tmpd) {
- snprintf(name, sizeof(name), "%s/zip.%03u", tmpd, *fu);
+ snprintf(name, sizeof(name), "%s"PATHSEP"zip.%03u", tmpd, *fu);
name[sizeof(name)-1]='\0';
} else {
if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM;
@@@ -308,33 -303,39 +297,39 @@@
return ret;
}
- static unsigned int lhdr(uint8_t *zip, uint32_t zsize, unsigned int *fu, unsigned int fc, uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int fd) {
- uint8_t *lh = zip;
+ static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int *fu, unsigned int fc, uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd) {
+ uint8_t *lh, *zip;
char name[256];
uint32_t csize, usize;
struct cli_meta_node *meta = ctx->engine->zip_mlist;
- if(zsize<=SIZEOF_LH) {
- cli_dbgmsg("cli_unzip: lh - out of file\n");
- return 0;
+ if(!(lh = fmap_need_off(map, loff, SIZEOF_LH))) {
+ cli_dbgmsg("cli_unzip: lh - out of file\n");
+ return 0;
}
if(LH_magic != 0x04034b50) {
if (!ch) cli_dbgmsg("cli_unzip: lh - wrkcomplete\n");
else cli_dbgmsg("cli_unzip: lh - bad magic\n");
+ fmap_unneed_off(map, loff, SIZEOF_LH);
return 0;
}
- zip+=SIZEOF_LH;
+ zip = lh + SIZEOF_LH;
zsize-=SIZEOF_LH;
if(zsize<=LH_flen) {
cli_dbgmsg("cli_unzip: lh - fname out of file\n");
+ fmap_unneed_off(map, loff, SIZEOF_LH);
return 0;
}
if(meta || cli_debug_flag) {
- uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen;
- memcpy(name, zip, nsize);
- name[nsize]='\0';
+ uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen;
+ char *src;
+ if(nsize && (src = fmap_need_ptr_once(map, zip, nsize))) {
+ memcpy(name, zip, nsize);
+ name[nsize]='\0';
+ } else
+ name[0] = '\0';
}
zip+=LH_flen;
zsize-=LH_flen;
@@@ -355,14 -356,20 +350,15 @@@
)
) meta = meta->next;
if(meta) {
- if(!cli_checkfp(map->fd, ctx)) {
- *ctx->virname = meta->virname;
- *ret = CL_VIRUS;
- } else
- *ret = CL_CLEAN;
-
- fmap_unneed_off(map, loff, SIZEOF_LH);
+ *ctx->virname = meta->virname;
+ *ret = CL_VIRUS;
return 0;
}
if(LH_flags & F_MSKED) {
cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n");
/* FIXME: need to find/craft a sample */
+ fmap_unneed_off(map, loff, SIZEOF_LH);
return 0;
}
@@@ -370,63 -377,76 +366,76 @@@
cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n");
*ctx->virname = "Encrypted.Zip";
*ret = CL_VIRUS;
+ fmap_unneed_off(map, loff, SIZEOF_LH);
return 0;
}
if(LH_flags & F_USEDD) {
cli_dbgmsg("cli_unzip: lh - has data desc\n");
- if(!ch) return 0;
+ if(!ch) {
+ fmap_unneed_off(map, loff, SIZEOF_LH);
+ return 0;
+ }
else { usize = CH_usize; csize = CH_csize; }
} else { usize = LH_usize; csize = LH_csize; }
if(zsize<=LH_elen) {
cli_dbgmsg("cli_unzip: lh - extra out of file\n");
+ fmap_unneed_off(map, loff, SIZEOF_LH);
return 0;
}
zip+=LH_elen;
zsize-=LH_elen;
if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
- cli_dbgmsg("cli_unzip: lh - skipping empty file\n");
+ cli_dbgmsg("cli_unzip: lh - skipping empty file\n");
} else {
- if(zsize<csize) {
- cli_dbgmsg("cli_unzip: lh - stream out of file\n");
- return 0;
- }
- if(LH_flags & F_ENCR) {
- cli_dbgmsg("cli_unzip: lh - skipping encrypted file\n");
- } else *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd);
- zip+=csize;
- zsize-=csize;
+ if(zsize<csize) {
+ cli_dbgmsg("cli_unzip: lh - stream out of file\n");
+ fmap_unneed_off(map, loff, SIZEOF_LH);
+ return 0;
+ }
+ 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);
+ }
+ zip+=csize;
+ zsize-=csize;
}
+ fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */
if(LH_flags & F_USEDD) {
- if(zsize<12) {
- cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
- return 0;
- }
- zsize-=12;
- if(cli_readint32(zip)==0x08074b50) {
- if(zsize<4) {
- cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
- return 0;
+ if(zsize<12) {
+ cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
+ return 0;
}
- zip+=4;
- }
- zip+=12;
+ zsize-=12;
+ if(fmap_need_ptr_once(map, zip, 4)) {
+ if(cli_readint32(zip)==0x08074b50) {
+ if(zsize<4) {
+ cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
+ return 0;
+ }
+ zip+=4;
+ }
+ }
+ zip+=12;
}
return zip-lh;
}
- static unsigned int chdr(uint8_t *zip, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd, int fd) {
- uint8_t *ch = &zip[coff];
+ static unsigned int chdr(fmap_t *map, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd) {
char name[256];
int last = 0;
+ int8_t *ch;
- if(zsize-coff<=SIZEOF_CH || CH_magic != 0x02014b50) {
- cli_dbgmsg("cli_unzip: ch - wrkcomplete\n");
- return 0;
+ if(!(ch = fmap_need_off(map, coff, SIZEOF_CH)) || CH_magic != 0x02014b50) {
+ if(ch) fmap_unneed_ptr(map, ch, SIZEOF_CH);
+ cli_dbgmsg("cli_unzip: ch - wrkcomplete\n");
+ return 0;
}
coff+=SIZEOF_CH;
@@@ -437,10 -457,13 +446,13 @@@
last=1;
}
if(cli_debug_flag && !last) {
- unsigned int size = (CH_flen>=sizeof(name))?sizeof(name)-1:CH_flen;
- memcpy(name, &zip[coff], size);
- name[size]='\0';
- cli_dbgmsg("cli_unzip: ch - fname: %s\n", name);
+ unsigned int size = (CH_flen>=sizeof(name))?sizeof(name)-1:CH_flen;
+ char *src = fmap_need_off_once(map, coff, size);
+ if(src) {
+ memcpy(name, src, size);
+ name[size]='\0';
+ cli_dbgmsg("cli_unzip: ch - fname: %s\n", name);
+ }
}
coff+=CH_flen;
@@@ -457,27 -480,23 +469,23 @@@
coff+=CH_clen;
if(CH_off<zsize-SIZEOF_LH) {
- lhdr(&zip[CH_off], zsize-CH_off, fu, fc, ch, ret, ctx, tmpd, fd);
+ lhdr(map, CH_off, zsize-CH_off, fu, fc, ch, ret, ctx, tmpd);
} else cli_dbgmsg("cli_unzip: ch - local hdr out of file\n");
+ fmap_unneed_ptr(map, ch, SIZEOF_CH);
return last?0:coff;
}
- int cli_unzip(int f, cli_ctx *ctx) {
+ int cli_unzip(cli_ctx *ctx) {
unsigned int fc=0, fu=0;
int ret=CL_CLEAN;
uint32_t fsize, lhoff = 0, coff = 0;
- struct stat st;
- uint8_t *map;
- char *tmpd;
+ fmap_t *map = *ctx->fmap;
+ char *tmpd, *ptr;
cli_dbgmsg("in cli_unzip\n");
- if (fstat(f, &st)==-1) {
- cli_warnmsg("cli_unzip: fstat() failed\n");
- return CL_ESTAT;
- }
- fsize = (uint32_t)st.st_size;
- if(sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=st.st_size) {
+ fsize = (uint32_t)map->len;
+ if(sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=map->len) {
cli_dbgmsg("cli_unzip: file too big\n");
return CL_CLEAN;
}
@@@ -485,59 -504,39 +493,39 @@@
cli_dbgmsg("cli_unzip: file too short\n");
return CL_CLEAN;
}
-
- #if HAVE_MMAP
- if ((map = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, f, 0))==MAP_FAILED) {
- cli_dbgmsg("cli_unzip: mmap failed\n");
- return CL_EMAP;
- }
- #else
- if(fsize > CLI_MAX_ALLOCATION) {
- cli_warnmsg("cli_unzip: mmap not available and file is too big\n");
- return CL_CLEAN;
- }
- lseek(f, 0, SEEK_SET);
- if(!(map = cli_malloc(fsize)))
- return CL_EMEM;
- if(cli_readn(f, map, fsize)!=fsize) {
- free(map);
- return CL_EREAD;
- }
- #endif
-
if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) {
- destroy_map(map, fsize);
return CL_ETMPDIR;
}
if (mkdir(tmpd, 0700)) {
cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd);
- destroy_map(map, fsize);
free(tmpd);
return CL_ETMPDIR;
}
for(coff=fsize-22 ; coff>0 ; coff--) { /* sizeof(EOC)==22 */
- if(cli_readint32(&map[coff])==0x06054b50) {
- uint32_t chptr = cli_readint32(&map[coff+16]);
- if(!CLI_ISCONTAINED(map, fsize, map+chptr, SIZEOF_CH)) continue;
- coff=chptr;
- break;
- }
+ if(!(ptr = fmap_need_off_once(map, coff, 20)))
+ continue;
+ if(cli_readint32(ptr)==0x06054b50) {
+ uint32_t chptr = cli_readint32(&ptr[16]);
+ if(!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue;
+ coff=chptr;
+ break;
+ }
}
if(coff) {
- cli_dbgmsg("cli_unzip: central @%x\n", coff);
- while(ret==CL_CLEAN && (coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd, f))) {
- fc++;
- if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
- cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
- ret=CL_EMAXFILES;
+ cli_dbgmsg("cli_unzip: central @%x\n", coff);
+ while(ret==CL_CLEAN && (coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd))) {
+ fc++;
+ if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
+ cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
+ ret=CL_EMAXFILES;
+ }
}
} else cli_dbgmsg("cli_unzip: central not found, using localhdrs\n");
if(fu<=(fc/4)) { /* FIXME: make up a sane ratio or remove the whole logic */
fc = 0;
- while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(&map[lhoff], fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd, f))) {
+ while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(map, lhoff, fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd))) {
fc++;
lhoff+=coff;
if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
@@@ -547,27 -546,21 +535,21 @@@
}
}
- destroy_map(map, fsize);
if (!ctx->engine->keeptmp) cli_rmdirs(tmpd);
free(tmpd);
return ret;
}
- int cli_unzip_single(int f, cli_ctx *ctx, off_t lhoffl) {
+ int cli_unzip_single(cli_ctx *ctx, off_t lhoffl) {
int ret=CL_CLEAN;
unsigned int fu=0;
- struct stat st;
uint32_t fsize;
- uint8_t *map;
+ fmap_t *map = *ctx->fmap;
cli_dbgmsg("in cli_unzip_single\n");
- if (fstat(f, &st)==-1) {
- cli_warnmsg("cli_unzip: fstat() failed\n");
- return CL_ESTAT;
- }
- fsize = (uint32_t)(st.st_size - lhoffl);
- if (lhoffl<0 || lhoffl>st.st_size || (sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=st.st_size - lhoffl)) {
+ fsize = (uint32_t)(map->len - lhoffl);
+ if (lhoffl<0 || lhoffl>map->len || (sizeof(off_t)!=sizeof(uint32_t) && (off_t)fsize!=map->len - lhoffl)) {
cli_dbgmsg("cli_unzip: bad offset\n");
return CL_CLEAN;
}
@@@ -576,26 -569,7 +558,7 @@@
return CL_CLEAN;
}
- #if HAVE_MMAP
- if ((map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0))==MAP_FAILED) {
- cli_dbgmsg("cli_unzip: mmap() failed\n");
- return CL_EMAP;
- }
- #else
- if(st.st_size > CLI_MAX_ALLOCATION) {
- cli_warnmsg("cli_unzip: mmap not available and file is too big\n");
- return CL_CLEAN;
- }
- lseek(f, 0, SEEK_SET);
- if(!(map = cli_malloc(st.st_size)))
- return CL_EMEM;
- if(cli_readn(f, map, st.st_size)!=st.st_size) {
- free(map);
- return CL_EREAD;
- }
- #endif
- lhdr(&map[lhoffl], fsize, &fu, 0, NULL, &ret, ctx, NULL, f);
+ lhdr(map, lhoffl, fsize, &fu, 0, NULL, &ret, ctx, NULL);
- destroy_map(map, st.st_size);
return ret;
}
diff --combined libclamav/uuencode.c
index 71fa0ba,6619c94..517f48d
--- a/libclamav/uuencode.c
+++ b/libclamav/uuencode.c
@@@ -39,6 -39,10 +39,6 @@@ static char const rcsid[] = "$Id: uuenc
#include "others.h"
#include "str.h"
-#ifdef C_WINDOWS
-#include <io.h>
-#endif
-
#include "mbox.h"
#include "uuencode.h"
@@@ -46,48 -50,35 +46,35 @@@
#define RFC2821LENGTH 1000
int
- cli_uuencode(const char *dir, int desc)
+ cli_uuencode(const char *dir, fmap_t *map)
{
- FILE *fin;
- int i;
message *m;
char buffer[RFC2821LENGTH + 1];
+ size_t at = 0;
- i = dup(desc);
- if((fin = fdopen(i, "rb")) == NULL) {
- cli_errmsg("Can't open descriptor %d\n", desc);
- close(i);
- return CL_EOPEN;
- }
- if(fgets(buffer, sizeof(buffer) - 1, fin) == NULL) {
+ if(!fmap_gets(map, buffer, &at, sizeof(buffer) - 1)) {
/* empty message */
return CL_CLEAN;
}
if(!isuuencodebegin(buffer)) {
- fclose(fin);
cli_dbgmsg("Message is not in uuencoded format\n");
return CL_EFORMAT;
}
m = messageCreate();
if(m == NULL) {
- fclose(fin);
return CL_EMEM;
}
cli_dbgmsg("found uuencode file\n");
- if(uudecodeFile(m, buffer, dir, fin) < 0) {
+ if(uudecodeFile(m, buffer, dir, map, &at) < 0) {
messageDestroy(m);
- fclose(fin);
cli_dbgmsg("Message is not in uuencoded format\n");
return CL_EFORMAT;
}
messageDestroy(m);
- fclose(fin);
-
return CL_CLEAN; /* a lie - but it gets things going */
}
@@@ -97,7 -88,7 +84,7 @@@
* Return < 0 for failure
*/
int
- uudecodeFile(message *m, const char *firstline, const char *dir, FILE *fin)
+ uudecodeFile(message *m, const char *firstline, const char *dir, fmap_t *map, size_t *at)
{
fileblob *fb;
char buffer[RFC2821LENGTH + 1];
@@@ -116,7 -107,7 +103,7 @@@
cli_dbgmsg("uudecode %s\n", filename);
free(filename);
- while(fgets(buffer, sizeof(buffer) - 1, fin) != NULL) {
+ while(fmap_gets(map, buffer, at, sizeof(buffer) - 1)) {
unsigned char data[1024];
const unsigned char *uptr;
size_t len;
diff --combined sigtool/sigtool.c
index 66b4d3b,e3e5ce5..be290a2
--- a/sigtool/sigtool.c
+++ b/sigtool/sigtool.c
@@@ -34,13 -34,11 +34,13 @@@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#ifndef _WIN32
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
+#endif
#include <dirent.h>
#ifdef HAVE_TERMIOS_H
@@@ -63,6 -61,7 +63,7 @@@
#include "libclamav/ole2_extract.h"
#include "libclamav/htmlnorm.h"
#include "libclamav/default.h"
+ #include "libclamav/fmap.h"
#define MAX_DEL_LOOKAHEAD 200
@@@ -184,14 -183,19 +185,19 @@@ static int md5sig(const struct optstruc
static int htmlnorm(const struct optstruct *opts)
{
int fd;
-
+ fmap_t *map;
if((fd = open(optget(opts, "html-normalise")->strarg, O_RDONLY)) == -1) {
mprintf("!htmlnorm: Can't open file %s\n", optget(opts, "html-normalise")->strarg);
return -1;
}
- html_normalise_fd(fd, ".", NULL, NULL);
+ if((map = fmap(fd, 0, 0))) {
+ html_normalise_map(map, ".", NULL, NULL);
+ funmap(map);
+ } else
+ mprintf("!fmap failed\n");
+
close(fd);
return 0;
@@@ -327,7 -331,7 +333,7 @@@ static char *getdsig(const char *host,
server.sin_port = htons(33101);
if(connect(sockd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) {
- close(sockd);
+ closesocket(sockd);
perror("connect()");
mprintf("!getdsig: Can't connect to ClamAV Signing Service at %s\n", host);
memset(pass, 0, sizeof(pass));
@@@ -345,9 -349,9 +351,9 @@@
memcpy(pt, data, datalen);
len += datalen;
- if(write(sockd, cmd, len) < 0) {
+ if(send(sockd, cmd, len, 0) < 0) {
mprintf("!getdsig: Can't write to socket\n");
- close(sockd);
+ closesocket(sockd);
memset(cmd, 0, sizeof(cmd));
memset(pass, 0, sizeof(pass));
return NULL;
@@@ -357,22 -361,22 +363,22 @@@
memset(pass, 0, sizeof(pass));
memset(buff, 0, sizeof(buff));
- if((bread = cli_readn(sockd, buff, sizeof(buff))) > 0) {
+ if((bread = recv(sockd, buff, sizeof(buff), 0)) > 0) {
if(!strstr(buff, "Signature:")) {
mprintf("!getdsig: Error generating digital signature\n");
mprintf("!getdsig: Answer from remote server: %s\n", buff);
- close(sockd);
+ closesocket(sockd);
return NULL;
} else {
mprintf("Signature received (length = %lu)\n", strlen(buff) - 10);
}
} else {
mprintf("!getdsig: Communication error with remote server\n");
- close(sockd);
+ closesocket(sockd);
return NULL;
}
- close(sockd);
+ closesocket(sockd);
pt = buff;
pt += 10;
@@@ -617,9 -621,9 +623,9 @@@ static int build(const struct optstruc
} else {
pt = freshdbdir();
- snprintf(olddb, sizeof(olddb), "%s/%s.cvd", pt, dbname);
+ snprintf(olddb, sizeof(olddb), "%s"PATHSEP"%s.cvd", pt, dbname);
if(access(olddb, R_OK))
- snprintf(olddb, sizeof(olddb), "%s/%s.cld", pt, dbname);
+ snprintf(olddb, sizeof(olddb), "%s"PATHSEP"%s.cld", pt, dbname);
free(pt);
}
@@@ -910,9 -914,9 +916,9 @@@ static int unpack(const struct optstruc
if(optget(opts, "unpack-current")->enabled) {
dbdir = freshdbdir();
- snprintf(name, sizeof(name), "%s/%s.cvd", dbdir, optget(opts, "unpack-current")->strarg);
+ snprintf(name, sizeof(name), "%s"PATHSEP"%s.cvd", dbdir, optget(opts, "unpack-current")->strarg);
if(access(name, R_OK)) {
- snprintf(name, sizeof(name), "%s/%s.cld", dbdir, optget(opts, "unpack-current")->strarg);
+ snprintf(name, sizeof(name), "%s"PATHSEP"%s.cld", dbdir, optget(opts, "unpack-current")->strarg);
if(access(name, R_OK)) {
mprintf("!unpack: Couldn't find %s CLD/CVD database\n", optget(opts, "unpack-current")->strarg);
free(dbdir);
@@@ -989,7 -993,9 +995,7 @@@ static int listdir(const char *dirname
}
while((dent = readdir(dd))) {
-#ifndef C_INTERIX
if(dent->d_ino)
-#endif
{
if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
(cli_strbcasestr(dent->d_name, ".db") ||
@@@ -1013,7 -1019,7 +1019,7 @@@
closedir(dd);
return -1;
}
- sprintf(dbfile, "%s/%s", dirname, dent->d_name);
+ sprintf(dbfile, "%s"PATHSEP"%s", dirname, dent->d_name);
if(listdb(dbfile) == -1) {
mprintf("!listdb: Error listing database %s\n", dbfile);
@@@ -1061,7 -1067,15 +1067,7 @@@ static int listdb(const char *filename
free(buffer);
fclose(fh);
- tmpdir = getenv("TMPDIR");
- if(tmpdir == NULL)
-#ifdef P_tmpdir
- tmpdir = P_tmpdir;
-#else
- tmpdir = "/tmp";
-#endif
-
- if(!(dir = cli_gentemp(tmpdir))) {
+ if(!(dir = cli_gentemp(NULL))) {
mprintf("!listdb: Can't generate temporary name\n");
return -1;
}
@@@ -1201,6 -1215,7 +1207,7 @@@ static int vbadump(const struct optstru
char *dir;
const char *pt;
struct uniq *vba = NULL;
+ cli_ctx ctx;
if(optget(opts, "vba-hex")->enabled) {
@@@ -1211,7 -1226,7 +1218,7 @@@
pt = optget(opts, "vba")->strarg;
}
- if((fd = open(pt, O_RDONLY)) == -1) {
+ if((fd = open(pt, O_RDONLY|O_BINARY)) == -1) {
mprintf("!vbadump: Can't open file %s\n", pt);
return -1;
}
@@@ -1230,7 -1245,18 +1237,18 @@@
return -1;
}
- if(cli_ole2_extract(fd, dir, NULL, &vba)) {
+ ctx.fmap = cli_malloc(sizeof(struct F_MAP *));
+ if(!ctx.fmap) {
+ printf("malloc failed\n");
+ return 1;
+ }
+ *ctx.fmap = fmap(fd, 0, 0);
+ if(*ctx.fmap) {
+ printf("fmap failed\n");
+ return 1;
+ }
+
+ if(cli_ole2_extract(dir, NULL, &vba)) {
cli_rmdirs(dir);
free(dir);
close(fd);
@@@ -1461,13 -1487,15 +1479,13 @@@ static int dircopy(const char *src, con
}
while((dent = readdir(dd))) {
-#if (!defined(C_INTERIX)) && (!defined(C_WINDOWS))
if(dent->d_ino)
-#endif
{
if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
continue;
- snprintf(spath, sizeof(spath), "%s/%s", src, dent->d_name);
- snprintf(dpath, sizeof(dpath), "%s/%s", dest, dent->d_name);
+ snprintf(spath, sizeof(spath), "%s"PATHSEP"%s", src, dent->d_name);
+ snprintf(dpath, sizeof(dpath), "%s"PATHSEP"%s", dest, dent->d_name);
if(filecopy(spath, dpath) == -1) {
/* mprintf("!dircopy: Can't copy %s to %s\n", spath, dpath); */
@@@ -1607,12 -1635,14 +1625,12 @@@ static int diffdirs(const char *old, co
}
while((dent = readdir(dd))) {
-#ifndef C_INTERIX
if(dent->d_ino)
-#endif
{
if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
continue;
- snprintf(path, sizeof(path), "%s/%s", old, dent->d_name);
+ snprintf(path, sizeof(path), "%s"PATHSEP"%s", old, dent->d_name);
if(compare(path, dent->d_name, diff) == -1) {
if(chdir(cwd) == -1)
mprintf("^diffdirs: Can't chdir to %s\n", cwd);
@@@ -1633,12 -1663,14 +1651,12 @@@
}
while((dent = readdir(dd))) {
-#ifndef C_INTERIX
if(dent->d_ino)
-#endif
{
if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
continue;
- snprintf(path, sizeof(path), "%s/%s", new, dent->d_name);
+ snprintf(path, sizeof(path), "%s"PATHSEP"%s", new, dent->d_name);
if(access(path, R_OK))
fprintf(diff, "UNLINK %s\n", dent->d_name);
}
diff --combined sigtool/vba.c
index f0edeb2,1b6a5da..d3e6219
--- a/sigtool/vba.c
+++ b/sigtool/vba.c
@@@ -17,10 -17,6 +17,10 @@@
* MA 02110-1301, USA.
*/
+#if HAVE_CONFIG_H
+#include "clamav-config.h"
+#endif
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@@ -36,7 -32,10 +36,7 @@@
#include "libclamav/others.h"
#include "libclamav/cltypes.h"
#include "libclamav/ole2_extract.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
+#include "shared/output.h"
typedef struct mac_token_tag
{
@@@ -967,6 -966,7 +967,7 @@@ static int sigtool_scandir (const char
const char *tmpdir;
char *dir;
int ret = CL_CLEAN, desc;
+ cli_ctx ctx;
if ((dd = opendir (dirname)) != NULL) {
@@@ -975,7 -975,7 +976,7 @@@
if (strcmp (dent->d_name, ".") && strcmp (dent->d_name, "..")) {
/* build the full name */
fname = (char *) cli_calloc (strlen (dirname) + strlen (dent->d_name) + 2, sizeof (char));
- sprintf (fname, "%s/%s", dirname, dent->d_name);
+ sprintf (fname, "%s"PATHSEP"%s", dirname, dent->d_name);
/* stat the file */
if (lstat (fname, &statbuf) != -1) {
@@@ -988,7 -988,14 +989,7 @@@
} else {
if (S_ISREG (statbuf.st_mode)) {
struct uniq *vba = NULL;
- tmpdir = getenv ("TMPDIR");
-
- if (tmpdir == NULL)
-#ifdef P_tmpdir
- tmpdir = P_tmpdir;
-#else
- tmpdir = "/tmp";
-#endif
+ tmpdir = cli_gettmpdir();
/* generate the temporary directory */
dir = cli_gentemp (tmpdir);
@@@ -997,12 -1004,22 +998,22 @@@
return CL_ETMPDIR;
}
- if ((desc = open (fname, O_RDONLY)) == -1) {
+ if ((desc = open (fname, O_RDONLY|O_BINARY)) == -1) {
printf ("Can't open file %s\n", fname);
return 1;
}
- if ((ret = cli_ole2_extract (desc, dir, NULL, &vba))) {
+ ctx.fmap = cli_malloc(sizeof(struct F_MAP *));
+ if(!ctx.fmap) {
+ printf("malloc failed\n");
+ return 1;
+ }
+ *ctx.fmap = fmap(desc, 0, 0);
+ if(*ctx.fmap) {
+ printf("fmap failed\n");
+ return 1;
+ }
+ if ((ret = cli_ole2_extract (dir, &ctx, &vba))) {
printf ("ERROR %s\n", cl_strerror (ret));
cli_rmdirs (dir);
free (dir);
@@@ -1011,9 -1028,11 +1022,11 @@@
if(vba)
sigtool_vba_scandir (dir, hex_output, vba);
-
cli_rmdirs (dir);
free (dir);
+ funmap(*ctx.fmap);
+ free(ctx.fmap);
+ close(desc);
}
}
@@@ -1023,7 -1042,7 +1036,7 @@@
}
}
} else {
- cli_errmsg ("Can't open directory %s.\n", dirname);
+ logg("!Can't open directory %s.\n", dirname);
return CL_EOPEN;
}
@@@ -1048,7 -1067,7 +1061,7 @@@ int sigtool_vba_scandir (const char *di
for(i = 0; i < vba_project->count; i++) {
for(j = 0; j < vba_project->colls[i]; j++) {
- snprintf(vbaname, 1024, "%s/%s_%u", vba_project->dir, vba_project->name[i], j);
+ snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", vba_project->dir, vba_project->name[i], j);
vbaname[sizeof(vbaname)-1] = '\0';
fd = open(vbaname, O_RDONLY|O_BINARY);
if(fd == -1) continue;
@@@ -1074,7 -1093,7 +1087,7 @@@
if((hashcnt = uniq_get(U, "powerpoint document", 19, &hash))) {
while(hashcnt--) {
- snprintf(vbaname, 1024, "%s/%s_%u", dirname, hash, hashcnt);
+ snprintf(vbaname, 1024, "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
vbaname[sizeof(vbaname)-1] = '\0';
fd = open(vbaname, O_RDONLY|O_BINARY);
if (fd == -1) continue;
@@@ -1090,7 -1109,7 +1103,7 @@@
if ((hashcnt = uniq_get(U, "worddocument", 12, &hash))) {
while(hashcnt--) {
- snprintf(vbaname, sizeof(vbaname), "%s/%s_%u", dirname, hash, hashcnt);
+ snprintf(vbaname, sizeof(vbaname), "%s"PATHSEP"%s_%u", dirname, hash, hashcnt);
vbaname[sizeof(vbaname)-1] = '\0';
fd = open(vbaname, O_RDONLY|O_BINARY);
if (fd == -1) continue;
@@@ -1128,7 -1147,7 +1141,7 @@@
if (strcmp (dent->d_name, ".") && strcmp (dent->d_name, "..")) {
/* build the full name */
fullname = calloc (strlen (dirname) + strlen (dent->d_name) + 2, sizeof (char));
- sprintf (fullname, "%s/%s", dirname, dent->d_name);
+ sprintf (fullname, "%s"PATHSEP"%s", dirname, dent->d_name);
/* stat the file */
if (lstat (fullname, &statbuf) != -1) {
@@@ -1140,7 -1159,7 +1153,7 @@@
}
}
} else {
- cli_errmsg ("ScanDir -> Can't open directory %s.\n", dirname);
+ logg("!ScanDir -> Can't open directory %s.\n", dirname);
return CL_EOPEN;
}
--
Debian repository for ClamAV
More information about the Pkg-clamav-commits
mailing list