[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:19:51 UTC 2010


The following commit has been merged in the debian/unstable branch:
commit 124ba12d7b7a5b65e1856947d9d6aa047d8a3237
Author: aCaB <acab at clamav.net>
Date:   Fri Feb 12 12:46:57 2010 +0100

    one pass binhex

diff --git a/libclamav/binhex.c b/libclamav/binhex.c
index 30d0108..0c7498a 100644
--- a/libclamav/binhex.c
+++ b/libclamav/binhex.c
@@ -1,7 +1,7 @@
 /*
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
+ *  Copyright (C) 2010 Sourcefire, Inc.
  *
- *  Authors: Nigel Horne
+ *  Authors: aCaB <acab at clamav.net>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -17,197 +17,214 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
  *
- * Change History:
- * $Log: binhex.c,v $
- * Revision 1.23  2007/02/12 20:46:08  njh
- * Various tidy
- *
- * Revision 1.22  2006/07/31 09:19:52  njh
- * Use MAP_PRIVATE
- *
- * Revision 1.21  2006/07/01 16:17:35  njh
- * Added destroy flag
- *
- * Revision 1.20  2006/07/01 03:47:50  njh
- * Don't loop if binhex runs out of memory
- *
- * Revision 1.19  2006/05/19 11:02:12  njh
- * Just include mbox.h
- *
- * Revision 1.18  2006/04/09 19:59:27  kojm
- * update GPL headers with new address for FSF
- *
- * Revision 1.17  2005/11/06 14:03:26  nigelhorne
- * Ensure NAME_MAX isn't redefined on BeOS
- *
- * Revision 1.16  2005/05/14 16:13:25  nigelhorne
- * Ensure munmap is the right size
- *
- * Revision 1.15  2005/05/13 19:30:34  nigelhorne
- * Clean cli_realloc call
- *
- * Revision 1.14  2005/03/10 08:51:30  nigelhorne
- * Tidy
- *
- * Revision 1.13  2005/01/19 05:29:41  nigelhorne
- * tidy
- *
- * Revision 1.12  2004/12/27 14:17:14  nigelhorne
- * Fix segfault if write to temporary file fails
- *
- * Revision 1.11  2004/12/17 12:03:38  nigelhorne
- * Tidy up for machines without MMAP
- *
- * Revision 1.10  2004/12/16 15:29:51  nigelhorne
- * Tidy
- *
- * Revision 1.9  2004/11/28 22:06:39  nigelhorne
- * Tidy space only headers code
- *
- * Revision 1.8  2004/11/28 21:05:50  nigelhorne
- * Handle headers with only spaces
- *
- * Revision 1.7  2004/11/23 09:05:26  nigelhorne
- * Fix crash in base64 encoded binhex files
- *
- * Revision 1.6  2004/11/22 15:16:53  nigelhorne
- * Use cli_realloc instead of many cli_mallocs
- *
- * Revision 1.5  2004/11/18 20:11:34  nigelhorne
- * Fix segfault
- *
- * Revision 1.4  2004/11/18 19:30:29  kojm
- * add support for Mac's HQX file format
- *
- * Revision 1.3  2004/11/18 18:24:45  nigelhorne
- * Added binhex.h
- *
- * Revision 1.2  2004/11/18 18:09:06  nigelhorne
- * First draft of binhex.c
- *
  */
-static	char	const	rcsid[] = "$Id: binhex.c,v 1.23 2007/02/12 20:46:08 njh Exp $";
-
-#include "clamav.h"
 
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
-#ifdef CL_THREAD_SAFE
-#ifndef	_REENTRANT
-#define	_REENTRANT	/* for Solaris 2.8 */
-#endif
-#endif
-
-#include <stdio.h>
-#include <memory.h>
-#include <sys/stat.h>
-#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H)
-#include <sys/mman.h>
-#endif
+#include <string.h>
 
+#include "scanners.h"
+#include "cltypes.h"
 #include "others.h"
-#include "mbox.h"
-#include "binhex.h"
+#include "clamav.h"
 #include "fmap.h"
 
-int
-cli_binhex(const char *dir, fmap_t *map)
-{
-	char *buf, *start, *line;
-	size_t size;
-	long bytesleft;
-	message *m;
-	fileblob *fb;
-	text *t_line;
-
-	size = (size_t)map->len;
-
-	if(size == 0)
-		return CL_CLEAN;
-
-	m = messageCreate();
-	if(m == NULL)
-		return CL_EMEM;
-
-	start = buf = fmap_need_off_once(map, 0, size);
-	if(!buf) {
-		messageDestroy(m);
-		return CL_EMAP;
-	}
-
-	cli_dbgmsg("mmap'ed binhex file\n");
-
-	bytesleft = (long)size;
-	line = NULL;
-
-	while(bytesleft > 0) {
-		int length = bytesleft;
-		char *ptr, *newline;
 
-		/*printf("%d: ", bytesleft);*/
-
-		for(ptr = buf; bytesleft && (*ptr != '\n') && (*ptr != '\r'); ptr++) {
-			--bytesleft;
+static const uint8_t hqxtbl[] = {
+    /*           00   01   02   03   04   05   06   07   08   09   0a   0b   0c   0d   0e   0f */
+    /* 00-0f */	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    /* 10-1f */	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+    /* 20-2f */	0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0xff,0xff,
+    /* 30-3f */	0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0xff,0x14,0x15,0xff,0xff,0xff,0xff,0xff,0xff,
+    /* 40-4f */	0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0xff,
+    /* 50-5f */	0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0xff,0x2c,0x2d,0x2e,0x2f,0xff,0xff,0xff,0xff,
+    /* 60-6f */	0x30,0x31,0x32,0x33,0x34,0x35,0x36,0xff,0x37,0x38,0x39,0x3a,0x3b,0x3c,0xff,0xff,
+    /* 70-7f */	0x3d,0x3e,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
+};
+
+#define BH_FLUSH_SZ (BUFSIZ - 256)
+
+int cli_binhex(cli_ctx *ctx) {
+    fmap_t *map = *ctx->fmap;
+    uint8_t *encoded, decoded[BUFSIZ], spare_bits, last_byte=0, this_byte, offset=0;
+    size_t enc_done=0, enc_todo=map->len;
+    unsigned int dec_done=0, chunksz = 0, chunkoff=0;
+    uint32_t datalen, reslen;
+    int in_data = 0, in_run = 0, _6bit=-1, datafd, resfd, ret = CL_CLEAN;
+    enum binhex_phase { IN_HEADER, IN_DATA, IN_LIMBO1, IN_LIMBO2, IN_RES } write_phase = IN_HEADER;
+    char *dname, *rname;
+
+    cli_dbgmsg("in cli_binhex\n");
+    if(!map->len) return CL_CLEAN;
+
+    if((ret = cli_gentempfd(ctx->engine->tmpdir, &dname, &datafd)) != CL_SUCCESS)
+	return ret;
+
+    if((ret = cli_gentempfd(ctx->engine->tmpdir, &rname, &resfd)) != CL_SUCCESS) {
+	close(datafd);
+	if(cli_unlink(dname)) ret = CL_EUNLINK;
+	free(dname);
+	return ret;
+    }
+
+    while(1) {
+	uint8_t b;
+	if(!enc_todo || dec_done >= BH_FLUSH_SZ) {
+	    if(!enc_todo && !dec_done) {
+		cli_dbgmsg("cli_binhex: possibly truncated file\n");
+		break;
+	    }
+	    if(write_phase == IN_HEADER) {
+		uint32_t namelen = (uint32_t)decoded[0], hdrlen = 1 + namelen + 1 + 4 + 4 + 2;
+		datalen = (decoded[hdrlen]<<24) | (decoded[hdrlen+1]<<16) | (decoded[hdrlen+2]<<8) | decoded[hdrlen+3];
+		hdrlen += 4;
+		reslen = (decoded[hdrlen]<<24) | (decoded[hdrlen+1]<<16) | (decoded[hdrlen+2]<<8) | decoded[hdrlen+3];
+		hdrlen += 4 + 2;
+		decoded[namelen+1] = 0;
+		if(dec_done <= hdrlen) {
+		    cli_dbgmsg("cli_binhex: possibly truncated file\n");
+		    break;
 		}
-
-		length -= bytesleft;
-		/*printf("%d: ", length);*/
-
-		newline = cli_realloc(line, (size_t)(length + 1));
-		if(newline == NULL)
-			break;
-
-		line = newline;
-
-		memcpy(line, buf, length);
-		line[length] = '\0';
-
-		/*puts(line);*/
-
-		if(messageAddStr(m, line) < 0)
+		cli_dbgmsg("cli_binhex: decoding '%s' - %u bytes of data to %s - %u bytes or resources to %s\n", decoded+1, datalen, dname, reslen, rname);
+		memmove(decoded, &decoded[hdrlen], dec_done - hdrlen);
+		dec_done -= hdrlen;
+		write_phase++;
+	    }
+	    if(dec_done && write_phase == IN_DATA) {
+		unsigned int todo = MIN(dec_done, datalen);
+		datalen -= todo;
+		dec_done -= todo;
+		if(cli_writen(datafd, decoded, todo)!=(int)todo) {
+		    ret = CL_EWRITE;
+		    break;
+		}
+		if(!datalen) {
+		    write_phase++;
+		    lseek(datafd, 0, SEEK_SET);
+		    ret = cli_magic_scandesc(datafd, ctx);
+		    if(ret == CL_VIRUS) break;
+		}
+		if(dec_done)
+		    memmove(decoded, &decoded[todo], dec_done);
+	    }
+	    if(dec_done && write_phase == IN_LIMBO1) {
+		if(dec_done > 1) {
+		    if(reslen<5) {
+			cli_dbgmsg("cli_binhex: skipping resources (too small)\n");
 			break;
-
-		if((bytesleft > 0) && (*ptr == '\r')) {
-			ptr++;
-			bytesleft--;
+		    }
+		    dec_done-=2;
+		    write_phase+=2;
+		    if(dec_done)
+			memmove(decoded, &decoded[2], dec_done);
+		} else {
+		    dec_done--;
+		    write_phase++;
+		    if(dec_done)
+			memmove(decoded, &decoded[1], dec_done);
+		}
+	    }
+	    if(dec_done && write_phase == IN_LIMBO2) {
+		if(reslen<5) {
+		    cli_dbgmsg("cli_binhex: skipping resources (too small)\n");
+		    break;
 		}
-		buf = ++ptr;
-		bytesleft--;
+		write_phase++;
+		if(--dec_done)
+		    memmove(decoded, &decoded[1], dec_done);
+	    }
+	    if(dec_done && write_phase == IN_RES) {
+		unsigned int todo = MIN(dec_done, reslen);
+		reslen -= todo;
+		dec_done -= todo;
+		if(cli_writen(resfd, decoded, todo)!=(int)todo) {
+		    ret = CL_EWRITE;
+		    break;
+		}
+		if(!reslen) {
+		    lseek(resfd, 0, SEEK_SET);
+		    ret = cli_magic_scandesc(resfd, ctx);
+		    break;
+		}
+	    }
 	}
 
-	if(line)
-		free(line);
-
-	if((t_line = binhexBegin(m)) == NULL) {
-		messageDestroy(m);
-		cli_dbgmsg("No binhex line found\n");
-		return CL_EFORMAT;
+	if(!chunksz) {
+	    chunksz = MIN(enc_todo, map->pgsz);
+	    encoded = fmap_need_off_once(map, enc_done, chunksz);
+	    if(!encoded) {
+		ret = CL_EREAD;
+		break;
+	    }
+	    chunkoff = 0;
 	}
+	chunksz--;
 
-	while(((t_line = t_line->t_next) != NULL) && (t_line->t_line == NULL));
+	b = encoded[chunkoff++];
+	enc_done++;
+	enc_todo--;
 
-	if(!t_line) {
-		messageDestroy(m);
-		cli_dbgmsg("No binhex data to parse\n");
-		return CL_EFORMAT;
+	if((char)b == '\r' || (char)b == '\n') { /* FIXME: skip eol on 8bit encoding ? */
+	    in_data = 1;
+	    continue;
+	}
+	if(!in_data) continue;
+	if(_6bit < 0) {
+	    _6bit = ((char)b == ':');
+	    continue;
+	}
+	if(_6bit) {
+	    if((char)b == ':')
+		continue;
+	    if(b > 0x7f || (b = hqxtbl[b]) == 0xff) {
+		cli_dbgmsg("cli_binhex: Invalid character (%02x)\n", encoded[chunkoff-1]);
+		break;
+	    }
+	    switch((offset++) & 3) { /* 6 bits per char */
+	    case 0: /* left-6h */
+		spare_bits = b<<2;
+		continue;
+	    case 1: /* left-2l + middle-4h */
+		this_byte = spare_bits | (b>>4);
+		spare_bits = b<<4;
+		break;
+	    case 2: /* middle-4l + right-2h */
+		this_byte = spare_bits | (b>>2);
+		spare_bits = b<<6;
+		break;
+	    case 3: /* right-6l */
+		this_byte = spare_bits | b;
+	    }
+	} else {
+	    this_byte = b;
 	}
 
-	/* similar to binhexMessage */
-	messageSetEncoding(m, "x-binhex");
-
-	fb = messageToFileblob(m, dir, 1);
-	if(fb) {
-		cli_dbgmsg("Binhex file decoded to %s\n", fileblobGetFilename(fb));
-		fileblobDestroy(fb);
-	} else
-		cli_errmsg("Couldn't decode binhex file to %s\n", dir);
-	messageDestroy(m);
-
-	if(fb)
-		return CL_CLEAN;	/* a lie - but it gets things going */
-	/* return CL_EIO; */	/* probably CL_EMEM, but we can't tell at this layer */
-	/* TK: CL_EMEM is too generic here and should not be reported for parsing errors */
-	return CL_EFORMAT;
+	if(in_run) {
+	    in_run = 0;
+	    if(!this_byte)
+		this_byte = 0x90;
+	    else {
+		while(--this_byte) 
+		    decoded[dec_done++] = last_byte;
+		continue;
+	    }
+	} else if(this_byte == 0x90) {
+	    in_run = 1;
+	    continue;
+	}
+	decoded[dec_done++] = this_byte;
+	last_byte = this_byte;
+    }
+
+    close(datafd);
+    close(resfd);
+    if(!ctx->engine->keeptmp) {
+	if(cli_unlink(dname) && ret != CL_VIRUS) ret = CL_EUNLINK;
+	if(cli_unlink(rname) && ret != CL_VIRUS) ret = CL_EUNLINK;
+    }
+    free(dname);
+    free(rname);
+    return ret;
 }
diff --git a/libclamav/binhex.h b/libclamav/binhex.h
index 2eafc8a..0732a5b 100644
--- a/libclamav/binhex.h
+++ b/libclamav/binhex.h
@@ -33,6 +33,7 @@
 #ifndef __BINHEX_H
 #define __BINHEX_H
 
-int cli_binhex(const char *dir, fmap_t *map);
+#include "others.h"
+int cli_binhex(cli_ctx *ctx);
 
 #endif
diff --git a/libclamav/scanners.c b/libclamav/scanners.c
index 038c683..9268a2a 100644
--- a/libclamav/scanners.c
+++ b/libclamav/scanners.c
@@ -1243,36 +1243,6 @@ static int cli_scantar(int desc, cli_ctx *ctx, unsigned int posix)
     return ret;
 }
 
-static int cli_scanbinhex(cli_ctx *ctx)
-{
-	char *dir;
-	int ret = CL_CLEAN;
-
-
-    cli_dbgmsg("in cli_scanbinhex()\n");
-
-    /* generate temporary directory */
-    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
-	return CL_EMEM;
-
-    if(mkdir(dir, 0700)) {
-	cli_errmsg("Binhex: Can't create temporary directory %s\n", dir);
-	free(dir);
-	return CL_ETMPDIR;
-    }
-
-    if((ret = cli_binhex(dir, *ctx->fmap)))
-	cli_dbgmsg("Binhex: %s\n", cl_strerror(ret));
-    else
-	ret = cli_scandir(dir, ctx);
-
-    if(!ctx->engine->keeptmp)
-	cli_rmdirs(dir);
-
-    free(dir);
-    return ret;
-}
-
 static int cli_scanmschm(int desc, cli_ctx *ctx)
 {
 	int ret = CL_CLEAN, rc;
@@ -2135,7 +2105,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
 
 	case CL_TYPE_BINHEX:
 	    if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_BINHEX))
-		ret = cli_scanbinhex(ctx);
+		ret = cli_binhex(ctx);
 	    break;
 
 	case CL_TYPE_SCRENC:

-- 
Debian repository for ClamAV



More information about the Pkg-clamav-commits mailing list