Blob Blame History Raw
--- clamav-0.88.7/libclamav/ole2_extract.c.cve-2007-2650	2006-01-05 16:04:38.000000000 +0100
+++ clamav-0.88.7/libclamav/ole2_extract.c	2007-05-31 20:33:14.000000000 +0200
@@ -1,7 +1,7 @@
 /*
  *  Extract component parts of OLE2 files (e.g. MS Office Documents)
  *
- *  Copyright (C) 2004 trog@uncon.org
+ *  Copyright (C) 2004-2007 trog@uncon.org
  *
  *  This code is based on the OpenOffice and libgsf sources.
  *                  
@@ -583,6 +583,7 @@
 	unsigned char *buff;
 	int32_t current_block, ofd, len, offset;
 	char *name, *newname;
+	bitset_t *blk_bitset;
 
 	if (prop->type != 2) {
 		/* Not a file */
@@ -643,14 +644,33 @@
 		close(ofd);
 		return FALSE;
 	}
-
+	
+	blk_bitset = cli_bitset_init();
+	if (!blk_bitset) {
+		cli_errmsg("ERROR [handler_writefile]: init bitset failed\n");
+		close(ofd);
+		return FALSE;
+	}
 	while((current_block >= 0) && (len > 0)) {
+		/* Check we aren't in a loop */
+		if (cli_bitset_test(blk_bitset, (unsigned long) current_block)) {
+			/* Loop in block list */
+			cli_dbgmsg("OLE2: Block list loop detected\n");
+			close(ofd);
+			free(buff);
+			cli_bitset_free(blk_bitset);
+			return FALSE;
+		}
+		if (!cli_bitset_set(blk_bitset, (unsigned long) current_block)) {
+			return FALSE;
+		}			
 		if (prop->size < (int64_t)hdr->sbat_cutoff) {
 			/* Small block file */
 			if (!ole2_get_sbat_data_block(fd, hdr, buff, current_block)) {
 				cli_dbgmsg("ole2_get_sbat_data_block failed\n");
 				close(ofd);
 				free(buff);
+				cli_bitset_free(blk_bitset);
 				return FALSE;
 			}
 			/* buff now contains the block with 8 small blocks in it */
@@ -658,6 +678,7 @@
 			if (cli_writen(ofd, &buff[offset], MIN(len,64)) != MIN(len,64)) {
 				close(ofd);
 				free(buff);
+				cli_bitset_free(blk_bitset);
 				return FALSE;
 			}
 
@@ -668,12 +689,14 @@
 			if (!ole2_read_block(fd, hdr, buff, current_block)) {
 				close(ofd);
 				free(buff);
+				cli_bitset_free(blk_bitset);
 				return FALSE;
 			}
 			if (cli_writen(ofd, buff, MIN(len,(1 << hdr->log2_big_block_size))) !=
 							MIN(len,(1 << hdr->log2_big_block_size))) {
 				close(ofd);
 				free(buff);
+				cli_bitset_free(blk_bitset);
 				return FALSE;
 			}
 
@@ -683,6 +706,7 @@
 	}
 	close(ofd);
 	free(buff);
+	cli_bitset_free(blk_bitset);
 	return TRUE;
 }