Browse code

Fixed an infinite loop on binhex

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@234 77e5149b-7576-45b1-b177-96237e5ba77b

Nigel Horne authored on 2004/02/03 23:38:03
Showing 2 changed files
... ...
@@ -1,3 +1,9 @@
1
+Tue Feb  3 14:38:04 GMT 2004 (njh)
2
+----------------------------------
3
+  * libclamav:	Speeded up binhex decoding using table look up
4
+  		Fixed possible infinite loop when decoding compressed binhex
5
+		Both fixes thanks to Thomas Lamy <Thomas.Lamy@in-online.net>
6
+
1 7
 Tue Feb  3 02:31:55 CET 2004 (tk)
2 8
 ---------------------------------
3 9
   * libclamav: + don't report errors when archive limits are reached
... ...
@@ -17,6 +17,9 @@
17 17
  *
18 18
  * Change History:
19 19
  * $Log: message.c,v $
20
+ * Revision 1.21  2004/02/03 14:35:37  nigelhorne
21
+ * Fixed an infinite loop on binhex
22
+ *
20 23
  * Revision 1.20  2004/02/02 17:10:04  nigelhorne
21 24
  * Scan a rare form of bounce message
22 25
  *
... ...
@@ -57,7 +60,7 @@
57 57
  * uuencodebegin() no longer static
58 58
  *
59 59
  */
60
-static	char	const	rcsid[] = "$Id: message.c,v 1.20 2004/02/02 17:10:04 nigelhorne Exp $";
60
+static	char	const	rcsid[] = "$Id: message.c,v 1.21 2004/02/03 14:35:37 nigelhorne Exp $";
61 61
 
62 62
 #ifndef	CL_DEBUG
63 63
 /*#define	NDEBUG	/* map CLAMAV debug onto standard */
... ...
@@ -661,39 +664,41 @@ messageToBlob(const message *m)
661 661
 		 */
662 662
 		if(data[0] == ':') {
663 663
 			char *ptr;
664
-			unsigned long newlen = 0L;
665 664
 			int bytenumber = 0;
665
+			unsigned long newlen = 0L;
666
+			const unsigned char hqxtbl[] = {
667
+				     /*   00   01   02   03   04   05   06   07   08   09   0a   0b   0c   0d   0e   0f */
668
+			/* 00-0f */	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
669
+			/* 10-1f */	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
670
+			/* 20-2f */	0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0xff,0xff,
671
+			/* 30-3f */	0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0xff,0x14,0x15,0xff,0xff,0xff,0xff,0xff,0xff,
672
+			/* 40-4f */	0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0xff,
673
+			/* 50-5f */	0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0xff,0x2c,0x2d,0x2e,0x2f,0xff,0xff,0xff,0xff,
674
+			/* 60-6f */	0x30,0x31,0x32,0x33,0x34,0x35,0x36,0xff,0x37,0x38,0x39,0x3a,0x3b,0x3c,0xff,0xff,
675
+			/* 70-7f */	0x3d,0x3e,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
676
+			};
666 677
 
667 678
 			/*
668 679
 			 * Convert 7 bit data into 8 bit
669 680
 			 */
670
-			cli_dbgmsg("decode HQX7 message");
681
+			cli_dbgmsg("decode HQX7 message (%d bytes)\n", len);
671 682
 
672 683
 			ptr = cli_malloc(len);
673 684
 			memcpy(ptr, data, len);
674 685
 
675 686
 			for(l = 1; l < len; l++) {
676 687
 				unsigned char c = ptr[l];
677
-				const unsigned char *tptr;
678
-
679
-				/* TODO: table look up would be quicker */
680
-				const unsigned char table[] =
681
-					"!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
682 688
 
683 689
 				if((c == '\n') || (c == '\r'))
684 690
 					continue;
685 691
 				if(c == ':')
686 692
 					break;
687
-				/*
688
-				 * TODO: at least post a sentinal!
689
-				 */
690
-				for(tptr = table; (*tptr != c) && (*tptr != '\0'); tptr++)
691
-					;
692
-				if(*tptr == '\0') {
693
-					cli_warnmsg("Invalid HQX7 character '%c'\n", c);
693
+
694
+				if((c < 0x20) || (c > 0x7f) || (hqxtbl[c] == 0xff)) {
695
+					cli_warnmsg("Invalid HQX7 character '%c' (0x%02x)\n", c, c);
694 696
 					break;
695 697
 				}
696
-				c = (unsigned char)(tptr - table);
698
+				c = hqxtbl[c];
697 699
 				assert(c <= 63);
698 700
 
699 701
 				/*
... ...
@@ -721,6 +726,7 @@ messageToBlob(const message *m)
721 721
 						break;
722 722
 				}
723 723
 			}
724
+			cli_dbgmsg("decoded HQX7 message (now %d bytes)\n", newlen);
724 725
 			free(ptr);
725 726
 		} else {
726 727
 			/*
... ...
@@ -747,6 +753,10 @@ messageToBlob(const message *m)
747 747
 		 * skip over length, filename, version, type, creator and flags
748 748
 		 */
749 749
 		byte = 1 + byte + 1 + 4 + 4 + 2;
750
+
751
+		/*
752
+		 * Set len to be the data fork length
753
+		 */
750 754
 		len = (data[byte] << 24) + (data[byte + 1] << 16) + (data[byte + 2] << 8) + data[byte + 3];
751 755
 
752 756
 		/*
... ...
@@ -756,11 +766,14 @@ messageToBlob(const message *m)
756 756
 		data = &data[byte];
757 757
 
758 758
 		/*
759
-		 * Check for compression of repetitive characters
759
+		 * Check for compression of repetitive characters in
760
+		 * the data fork
760 761
 		 */
761 762
 		if(memchr(data, 0x90, len))
762 763
 			/*
763 764
 			 * Includes compression
765
+			 * TODO: sections of data that are not compressed
766
+			 *	can be added to the blob all at once
764 767
 			 */
765 768
 			for(l = 0; l < len; l++) {
766 769
 				unsigned char c = data[l];
... ...
@@ -773,19 +786,22 @@ messageToBlob(const message *m)
773 773
 
774 774
 						l += 2;
775 775
 						count = data[l];
776
+						cli_dbgmsg("uncompress HQX7 at 0x%06x: %d repetitive bytes\n", l, count);
776 777
 
777 778
 						if(count == 0) {
778 779
 							c = 0x90;
779 780
 							blobAddData(b, &c, 1);
780
-						} else while(--l > 0)
781
+						} else while(--count > 0)
781 782
 							blobAddData(b, &c, 1);
782 783
 					}
783 784
 			}
784
-		else
785
+		else {
785 786
 			/*
786 787
 			 * No compression - quickly copy all across
787 788
 			 */
789
+			cli_dbgmsg("HQX7 message is not compressed...\n");
788 790
 			blobAddData(b, data, len);
791
+		}
789 792
 
790 793
 		blobDestroy(tmp);
791 794