git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@1732 77e5149b-7576-45b1-b177-96237e5ba77b
Trog authored on 2005/10/18 19:32:06... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Tue Oct 18 11:29:04 BST 2005 (trog) |
|
2 |
+----------------------------------- |
|
3 |
+ * libclamav/others.c,h: Add generic bitset implementation |
|
4 |
+ |
|
5 |
+ * libclamav/ole2_extract.c: Make sure the property tree doesn't loop |
|
6 |
+ |
|
1 | 7 |
Fri Sep 30 17:00:49 BST 2005 (njh) |
2 | 8 |
---------------------------------- |
3 | 9 |
* clamav-milter: Added --freshclam-monitor |
... | ... |
@@ -111,6 +111,7 @@ typedef struct ole2_header_tag |
111 | 111 |
int32_t sbat_root_start __attribute__ ((packed)); |
112 | 112 |
unsigned char *m_area; |
113 | 113 |
off_t m_length; |
114 |
+ bitset_t *bitset; |
|
114 | 115 |
} ole2_header_t; |
115 | 116 |
|
116 | 117 |
typedef struct property_tag |
... | ... |
@@ -468,7 +469,7 @@ static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, |
468 | 468 |
if ((prop_index < 0) || (rec_level > 100) || (*file_count > 100000)) { |
469 | 469 |
return; |
470 | 470 |
} |
471 |
- |
|
471 |
+ |
|
472 | 472 |
if (limits && limits->maxfiles && (*file_count > limits->maxfiles)) { |
473 | 473 |
cli_dbgmsg("OLE2: File limit reached (max: %d)\n", limits->maxfiles); |
474 | 474 |
return; |
... | ... |
@@ -507,6 +508,17 @@ static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, |
507 | 507 |
prop_block[index].size = ole2_endian_convert_32(prop_block[index].size); |
508 | 508 |
|
509 | 509 |
print_ole2_property(&prop_block[index]); |
510 |
+ |
|
511 |
+ /* Check we aren't in a loop */ |
|
512 |
+ if (cli_bitset_test(hdr->bitset, (unsigned long) prop_index)) { |
|
513 |
+ /* Loop in property tree detected */ |
|
514 |
+ cli_dbgmsg("OLE2: Property tree loop detected at index %d\n", prop_index); |
|
515 |
+ return; |
|
516 |
+ } |
|
517 |
+ if (!cli_bitset_set(hdr->bitset, (unsigned long) prop_index)) { |
|
518 |
+ return; |
|
519 |
+ } |
|
520 |
+ |
|
510 | 521 |
switch (prop_block[index].type) { |
511 | 522 |
case 5: /* Root Entry */ |
512 | 523 |
if ((prop_index != 0) || (rec_level !=0) || |
... | ... |
@@ -745,7 +757,7 @@ int cli_ole2_extract(int fd, const char *dirname, const struct cl_limits *limits |
745 | 745 |
|
746 | 746 |
/* size of header - size of other values in struct */ |
747 | 747 |
hdr_size = sizeof(struct ole2_header_tag) - sizeof(int32_t) - |
748 |
- sizeof(unsigned char *) - sizeof(off_t); |
|
748 |
+ sizeof(unsigned char *) - sizeof(off_t) - sizeof(bitset_t *); |
|
749 | 749 |
|
750 | 750 |
hdr.m_area = NULL; |
751 | 751 |
|
... | ... |
@@ -791,7 +803,12 @@ int cli_ole2_extract(int fd, const char *dirname, const struct cl_limits *limits |
791 | 791 |
hdr.xbat_count = ole2_endian_convert_32(hdr.xbat_count); |
792 | 792 |
|
793 | 793 |
hdr.sbat_root_start = -1; |
794 |
- |
|
794 |
+ |
|
795 |
+ hdr.bitset = cli_bitset_init(); |
|
796 |
+ if (!hdr.bitset) { |
|
797 |
+ return CL_EOLE2; |
|
798 |
+ } |
|
799 |
+ |
|
795 | 800 |
if (strncmp(hdr.magic, magic_id, 8) != 0) { |
796 | 801 |
cli_dbgmsg("OLE2 magic failed!\n"); |
797 | 802 |
#ifdef HAVE_MMAP |
... | ... |
@@ -799,6 +816,7 @@ int cli_ole2_extract(int fd, const char *dirname, const struct cl_limits *limits |
799 | 799 |
munmap(hdr.m_area, hdr.m_length); |
800 | 800 |
} |
801 | 801 |
#endif |
802 |
+ cli_bitset_free(hdr.bitset); |
|
802 | 803 |
return CL_EOLE2; |
803 | 804 |
} |
804 | 805 |
|
... | ... |
@@ -831,5 +849,6 @@ abort: |
831 | 831 |
munmap(hdr.m_area, hdr.m_length); |
832 | 832 |
} |
833 | 833 |
#endif |
834 |
+ cli_bitset_free(hdr.bitset); |
|
834 | 835 |
return 0; |
835 | 836 |
} |
... | ... |
@@ -681,3 +681,89 @@ int cli_filecopy(const char *src, const char *dest) |
681 | 681 |
|
682 | 682 |
return close(d); |
683 | 683 |
} |
684 |
+ |
|
685 |
+/* Implement a generic bitset */ |
|
686 |
+ |
|
687 |
+#define BITS_PER_CHAR (8) |
|
688 |
+#define BITSET_DEFAULT_SIZE (1024) |
|
689 |
+#define FALSE (0) |
|
690 |
+#define TRUE (1) |
|
691 |
+ |
|
692 |
+static unsigned long nearest_power(unsigned long num) |
|
693 |
+{ |
|
694 |
+ unsigned long n = BITSET_DEFAULT_SIZE; |
|
695 |
+ |
|
696 |
+ while (n < num) { |
|
697 |
+ n <<= 1; |
|
698 |
+ if (n == 0) { |
|
699 |
+ return num; |
|
700 |
+ } |
|
701 |
+ } |
|
702 |
+ return n; |
|
703 |
+} |
|
704 |
+ |
|
705 |
+bitset_t *cli_bitset_init() |
|
706 |
+{ |
|
707 |
+ bitset_t *bs; |
|
708 |
+ |
|
709 |
+ bs = malloc(sizeof(bitset_t)); |
|
710 |
+ if (!bs) { |
|
711 |
+ return NULL; |
|
712 |
+ } |
|
713 |
+ bs->length = BITSET_DEFAULT_SIZE; |
|
714 |
+ bs->bitset = calloc(BITSET_DEFAULT_SIZE, 1); |
|
715 |
+ return bs; |
|
716 |
+} |
|
717 |
+ |
|
718 |
+void cli_bitset_free(bitset_t *bs) |
|
719 |
+{ |
|
720 |
+ if (!bs) { |
|
721 |
+ return; |
|
722 |
+ } |
|
723 |
+ if (bs->bitset) { |
|
724 |
+ free(bs->bitset); |
|
725 |
+ } |
|
726 |
+ free(bs); |
|
727 |
+} |
|
728 |
+ |
|
729 |
+static bitset_t *bitset_realloc(bitset_t *bs, unsigned long min_size) |
|
730 |
+{ |
|
731 |
+ unsigned long new_length; |
|
732 |
+ |
|
733 |
+ new_length = nearest_power(min_size); |
|
734 |
+ bs->bitset = (unsigned char *) realloc(bs->bitset, new_length); |
|
735 |
+ if (!bs->bitset) { |
|
736 |
+ return NULL; |
|
737 |
+ } |
|
738 |
+ memset(bs->bitset+bs->length, 0, new_length-bs->length); |
|
739 |
+ bs->length = new_length; |
|
740 |
+ return bs; |
|
741 |
+} |
|
742 |
+ |
|
743 |
+int cli_bitset_set(bitset_t *bs, unsigned long bit_offset) |
|
744 |
+{ |
|
745 |
+ unsigned long char_offset; |
|
746 |
+ |
|
747 |
+ char_offset = bit_offset / BITS_PER_CHAR; |
|
748 |
+ bit_offset = bit_offset % BITS_PER_CHAR; |
|
749 |
+ |
|
750 |
+ if (char_offset >= bs->length) { |
|
751 |
+ bs = bitset_realloc(bs, char_offset+1); |
|
752 |
+ if (!bs) { |
|
753 |
+ return FALSE; |
|
754 |
+ } |
|
755 |
+ } |
|
756 |
+ bs->bitset[char_offset] |= ((unsigned char)1 << bit_offset); |
|
757 |
+ return TRUE; |
|
758 |
+} |
|
759 |
+ |
|
760 |
+int cli_bitset_test(bitset_t *bs, unsigned long bit_offset) |
|
761 |
+{ |
|
762 |
+ unsigned long char_offset; |
|
763 |
+ |
|
764 |
+ char_offset = bit_offset / BITS_PER_CHAR; |
|
765 |
+ bit_offset = bit_offset % BITS_PER_CHAR; |
|
766 |
+ |
|
767 |
+ return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset)); |
|
768 |
+} |
|
769 |
+ |
... | ... |
@@ -23,6 +23,12 @@ |
23 | 23 |
#include <stdlib.h> |
24 | 24 |
#include "cltypes.h" |
25 | 25 |
|
26 |
+typedef struct bitset_tag |
|
27 |
+{ |
|
28 |
+ unsigned char *bitset; |
|
29 |
+ unsigned long length; |
|
30 |
+} bitset_t; |
|
31 |
+ |
|
26 | 32 |
void cli_warnmsg(const char *str, ...); |
27 | 33 |
void cli_errmsg(const char *str, ...); |
28 | 34 |
void cli_dbgmsg(const char *str, ...); |
... | ... |
@@ -43,5 +49,8 @@ char *cli_gentempdesc(const char *dir, int *fd); |
43 | 43 |
char *cli_gentempstream(const char *dir, FILE **fs); |
44 | 44 |
unsigned int cli_rndnum(unsigned int max); |
45 | 45 |
int cli_filecopy(const char *src, const char *dest); |
46 |
- |
|
46 |
+bitset_t *cli_bitset_init(); |
|
47 |
+void cli_bitset_free(bitset_t *bs); |
|
48 |
+int cli_bitset_set(bitset_t *bs, unsigned long bit_offset); |
|
49 |
+int cli_bitset_test(bitset_t *bs, unsigned long bit_offset); |
|
47 | 50 |
#endif |