Browse code

Prevent buffer overflow in broken uuencoded files

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

Nigel Horne authored on 2003/11/17 16:58:42
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Mon Nov 17 13:28:16 IST 2003 (njh)
2
+----------------------------------
3
+  * libclamav: Prevent buffer overflow in broken uuencoded files
4
+
1 5
 Mon Nov 17 10:20:05 IST 2003 (njh)
2 6
 ----------------------------------
3 7
   * clamav-milter: changed version from 0.60 to 0.65
... ...
@@ -17,6 +17,9 @@
17 17
  *
18 18
  * Change History:
19 19
  * $Log: message.c,v $
20
+ * Revision 1.11  2003/11/17 07:57:12  nigelhorne
21
+ * Prevent buffer overflow in broken uuencoded files
22
+ *
20 23
  * Revision 1.10  2003/11/05 07:03:51  nigelhorne
21 24
  * Handle broken content-disposition
22 25
  *
... ...
@@ -27,7 +30,7 @@
27 27
  * uuencodebegin() no longer static
28 28
  *
29 29
  */
30
-static	char	const	rcsid[] = "$Id: message.c,v 1.10 2003/11/05 07:03:51 nigelhorne Exp $";
30
+static	char	const	rcsid[] = "$Id: message.c,v 1.11 2003/11/17 07:57:12 nigelhorne Exp $";
31 31
 
32 32
 #ifndef	CL_DEBUG
33 33
 /*#define	NDEBUG	/* map CLAMAV debug onto standard */
... ...
@@ -74,7 +77,7 @@ static	char	const	rcsid[] = "$Id: message.c,v 1.10 2003/11/05 07:03:51 nigelhorn
74 74
 
75 75
 typedef enum { FALSE = 0, TRUE = 1 } bool;
76 76
 
77
-static	unsigned char	*decodeLine(const message *m, const char *line, unsigned char *ptr);
77
+static	unsigned char	*decodeLine(const message *m, const char *line, unsigned char *buf, size_t buflen);
78 78
 static unsigned char *decode(const char *in, unsigned char *out, unsigned char (*decoder)(char), bool isFast);
79 79
 static	unsigned	char	hex(char c);
80 80
 static	unsigned	char	base64(char c);
... ...
@@ -658,7 +661,7 @@ messageToBlob(const message *m)
658 658
 				if(strcasecmp(line, "end") == 0)
659 659
 					break;
660 660
 
661
-			uptr = decodeLine(m, line, data);
661
+			uptr = decodeLine(m, line, data, sizeof(data));
662 662
 
663 663
 			if(uptr == NULL)
664 664
 				break;
... ...
@@ -737,7 +740,7 @@ messageToText(const message *m)
737 737
 				if(strcasecmp(line, "end") == 0)
738 738
 					break;
739 739
 
740
-			uptr = decodeLine(m, line, data);
740
+			uptr = decodeLine(m, line, data, sizeof(data));
741 741
 
742 742
 			if(uptr == NULL)
743 743
 				break;
... ...
@@ -796,9 +799,11 @@ uuencodeBegin(const message *m)
796 796
 /*
797 797
  * Decode a line and add it to a buffer, return the end of the buffer
798 798
  * to help appending callers. There is no new line at the end of "line"
799
+ *
800
+ * len is sizeof(ptr)
799 801
  */
800 802
 static unsigned char *
801
-decodeLine(const message *m, const char *line, unsigned char *ptr)
803
+decodeLine(const message *m, const char *line, unsigned char *buf, size_t buflen)
802 804
 {
803 805
 	int len;
804 806
 	bool softbreak;
... ...
@@ -807,15 +812,15 @@ decodeLine(const message *m, const char *line, unsigned char *ptr)
807 807
 
808 808
 	assert(m != NULL);
809 809
 	assert(line != NULL);
810
-	assert(ptr != NULL);
810
+	assert(buf != NULL);
811 811
 
812 812
 	switch(messageGetEncoding(m)) {
813 813
 		case NOENCODING:
814 814
 		case EIGHTBIT:
815 815
 		default:	/* unknown encoding type - try our best */
816
-			ptr = (unsigned char *)strrcpy((char *)ptr, line);
816
+			buf = (unsigned char *)strrcpy((char *)buf, line);
817 817
 			/* Put the new line back in */
818
-			return (unsigned char *)strrcpy((char *)ptr, "\n");
818
+			return (unsigned char *)strrcpy((char *)buf, "\n");
819 819
 
820 820
 		case QUOTEDPRINTABLE:
821 821
 			softbreak = FALSE;
... ...
@@ -836,20 +841,20 @@ decodeLine(const message *m, const char *line, unsigned char *ptr)
836 836
 						 * broken e-mail, not
837 837
 						 * adhering to RFC1522
838 838
 						 */
839
-						*ptr++ = byte;
839
+						*buf++ = byte;
840 840
 						break;
841 841
 					}
842 842
 
843 843
 					byte <<= 4;
844 844
 					byte += hex(*line);
845
-					*ptr++ = byte;
845
+					*buf++ = byte;
846 846
 				} else
847
-					*ptr++ = *line;
847
+					*buf++ = *line;
848 848
 				line++;
849 849
 			}
850 850
 			if(!softbreak)
851 851
 				/* Put the new line back in */
852
-				*ptr++ = '\n';
852
+				*buf++ = '\n';
853 853
 			break;
854 854
 
855 855
 		case BASE64:
... ...
@@ -864,8 +869,8 @@ decodeLine(const message *m, const char *line, unsigned char *ptr)
864 864
 			/*
865 865
 			 * Klez doesn't always put "=" on the last line
866 866
 			 */
867
-			/*ptr = decode(line, ptr, base64, p2 == NULL);*/
868
-			ptr = decode(copy, ptr, base64, 0);
867
+			/*buf = decode(line, buf, base64, p2 == NULL);*/
868
+			buf = decode(copy, buf, base64, 0);
869 869
 
870 870
 			free(copy);
871 871
 			break;
... ...
@@ -878,15 +883,20 @@ decodeLine(const message *m, const char *line, unsigned char *ptr)
878 878
 			if(strcasecmp(line, "end") == 0)
879 879
 				break;
880 880
 
881
-			assert(strlen(line) <= 62);
882 881
 			if((line[0] & 0x3F) == ' ')
883 882
 				break;
884 883
 
885 884
 			len = *line++ - ' ';
886 885
 
887
-			assert((len >= 0) && (len <= 63));
888
-
889
-			ptr = decode(line, ptr, uudecode, (len & 3) == 0);
886
+			if(len > buflen)
887
+				/*
888
+				 * In practice this should never occur since
889
+				 * the maximum length of a uuencoded line is
890
+				 * 62 characters
891
+				 */
892
+				cli_warnmsg("uudecode: buffer overflow stopped, attempting to ignore but decoding may fail");
893
+			else
894
+				buf = decode(line, buf, uudecode, (len & 3) == 0);
890 895
 			break;
891 896
 
892 897
 		case BINARY:
... ...
@@ -896,8 +906,8 @@ decodeLine(const message *m, const char *line, unsigned char *ptr)
896 896
 			break;
897 897
 	}
898 898
 
899
-	*ptr = '\0';
900
-	return ptr;
899
+	*buf = '\0';
900
+	return buf;
901 901
 }
902 902
 
903 903
 static unsigned char *