--- 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; }