--- clamav/clamav-devel/libclamav/others.c 2005/10/03 13:19:09 1.67 +++ clamav/clamav-devel/libclamav/others.c 2005/10/25 22:38:45 1.69 @@ -681,3 +681,88 @@ return close(d); } + +/* Implement a generic bitset, trog@clamav.net */ + +#define BITS_PER_CHAR (8) +#define BITSET_DEFAULT_SIZE (1024) +#define FALSE (0) +#define TRUE (1) + +static unsigned long nearest_power(unsigned long num) +{ + unsigned long n = BITSET_DEFAULT_SIZE; + + while (n < num) { + n <<= 1; + if (n == 0) { + return num; + } + } + return n; +} + +bitset_t *cli_bitset_init() +{ + bitset_t *bs; + + bs = cli_malloc(sizeof(bitset_t)); + if (!bs) { + return NULL; + } + bs->length = BITSET_DEFAULT_SIZE; + bs->bitset = cli_calloc(BITSET_DEFAULT_SIZE, 1); + return bs; +} + +void cli_bitset_free(bitset_t *bs) +{ + if (!bs) { + return; + } + if (bs->bitset) { + free(bs->bitset); + } + free(bs); +} + +static bitset_t *bitset_realloc(bitset_t *bs, unsigned long min_size) +{ + unsigned long new_length; + + new_length = nearest_power(min_size); + bs->bitset = (unsigned char *) cli_realloc(bs->bitset, new_length); + if (!bs->bitset) { + return NULL; + } + memset(bs->bitset+bs->length, 0, new_length-bs->length); + bs->length = new_length; + return bs; +} + +int cli_bitset_set(bitset_t *bs, unsigned long bit_offset) +{ + unsigned long char_offset; + + char_offset = bit_offset / BITS_PER_CHAR; + bit_offset = bit_offset % BITS_PER_CHAR; + + if (char_offset >= bs->length) { + bs = bitset_realloc(bs, char_offset+1); + if (!bs) { + return FALSE; + } + } + bs->bitset[char_offset] |= ((unsigned char)1 << bit_offset); + return TRUE; +} + +int cli_bitset_test(bitset_t *bs, unsigned long bit_offset) +{ + unsigned long char_offset; + + char_offset = bit_offset / BITS_PER_CHAR; + bit_offset = bit_offset % BITS_PER_CHAR; + + return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset)); +} --- clamav/clamav-devel/libclamav/ole2_extract.c 2005/03/18 13:52:06 1.35 +++ clamav/clamav-devel/libclamav/ole2_extract.c 2005/10/18 10:32:06 1.36 @@ -111,6 +111,7 @@ int32_t sbat_root_start __attribute__ ((packed)); unsigned char *m_area; off_t m_length; + bitset_t *bitset; } ole2_header_t; typedef struct property_tag @@ -468,7 +469,7 @@ if ((prop_index < 0) || (rec_level > 100) || (*file_count > 100000)) { return; } - + if (limits && limits->maxfiles && (*file_count > limits->maxfiles)) { cli_dbgmsg("OLE2: File limit reached (max: %d)\n", limits->maxfiles); return; @@ -507,6 +508,17 @@ prop_block[index].size = ole2_endian_convert_32(prop_block[index].size); print_ole2_property(&prop_block[index]); + + /* Check we aren't in a loop */ + if (cli_bitset_test(hdr->bitset, (unsigned long) prop_index)) { + /* Loop in property tree detected */ + cli_dbgmsg("OLE2: Property tree loop detected at index %d\n", prop_index); + return; + } + if (!cli_bitset_set(hdr->bitset, (unsigned long) prop_index)) { + return; + } + switch (prop_block[index].type) { case 5: /* Root Entry */ if ((prop_index != 0) || (rec_level !=0) || @@ -745,7 +757,7 @@ /* size of header - size of other values in struct */ hdr_size = sizeof(struct ole2_header_tag) - sizeof(int32_t) - - sizeof(unsigned char *) - sizeof(off_t); + sizeof(unsigned char *) - sizeof(off_t) - sizeof(bitset_t *); hdr.m_area = NULL; @@ -791,7 +803,12 @@ hdr.xbat_count = ole2_endian_convert_32(hdr.xbat_count); hdr.sbat_root_start = -1; - + + hdr.bitset = cli_bitset_init(); + if (!hdr.bitset) { + return CL_EOLE2; + } + if (strncmp(hdr.magic, magic_id, 8) != 0) { cli_dbgmsg("OLE2 magic failed!\n"); #ifdef HAVE_MMAP @@ -799,6 +816,7 @@ munmap(hdr.m_area, hdr.m_length); } #endif + cli_bitset_free(hdr.bitset); return CL_EOLE2; } @@ -831,5 +849,6 @@ munmap(hdr.m_area, hdr.m_length); } #endif + cli_bitset_free(hdr.bitset); return 0; }