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... | ... |
@@ -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 * |