Browse code

* libclamav/others.c,h: Add generic bitset implementation * libclamav/ole2_extract.c: Make sure the property tree doesn't loop

git-svn: trunk@1732

Trog authored on 2005/10/18 19:32:06
Showing 4 changed files
... ...
@@ -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