From: Melvin H. <mha...@us...> - 2003-05-30 19:42:41
|
Update of /cvsroot/libetpan/xetpan/src In directory sc8-pr-cvs1:/tmp/cvs-serv18204/src Modified Files: utils.c utils.h Log Message: * src/utils.c: * src/utils.h: - Utils_data_has_yencoded(): changed interface - Worked around libmagic buffer overflow bug - a_Utils_data_has_uuencoded(): changed interface and use a_Utils_memmem() instead of strstr to search for a string and fixed a buffer overflow bug. - a_Utils_data_has_yencoded(): changed interface - a_Utils_data_has_yencoded2(): changed interface - Utils_data_has_yencoded(): changed interface and use a_Utils_memmem() instead of strstr to search for a string and fixed a buffer overflow bug. - a_Utils_memmem(): new function as a replacement of GNU libc memmem. Index: utils.c =================================================================== RCS file: /cvsroot/libetpan/xetpan/src/utils.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- utils.c 28 May 2003 20:57:04 -0000 1.4 +++ utils.c 30 May 2003 19:42:37 -0000 1.5 @@ -29,6 +29,10 @@ #ifdef HAVE_MAGIC_H #include <magic.h> +/* This is a bug in magic_buffer: it has an internal buffer size of + * 65k but it does not check for buffer overflow. Limit it to 10000. + */ +#define MAGIC_MAX_BUF_LEN 10000 #endif #include "intl.h" @@ -51,7 +55,7 @@ Utils_data_has_yencoded(const char *data, size_t size, const char **uu_start, - const char **uu_end, + size_t *uu_size, const char *begin_tag); /* Function definitions */ @@ -215,7 +219,10 @@ magic = magic_open(MAGIC_MIME); magic_load(magic, NULL); - magic_type = magic_buffer(magic, data, size); + magic_type = magic_buffer(magic, data, + ((size < MAGIC_MAX_BUF_LEN) ? + size : + MAGIC_MAX_BUF_LEN)); if (magic_type) mime_type = strdup(magic_type); @@ -475,12 +482,13 @@ a_Utils_data_has_uuencoded(const char *data, size_t size, const char **uu_start, - const char **uu_end) + size_t *uu_size) { const char *begin; const char *begin_tag = "begin "; const char *end_tag = "end"; const char *begin_eol; + const char *data_end = data + size; const char *mode; const char *end; const char *filename; @@ -492,7 +500,7 @@ if (data == NULL || size == 0) return NULL; - begin = strstr(data, begin_tag); + begin = a_Utils_memmem(data, size, begin_tag, strlen(begin_tag)); if (!begin) return NULL; @@ -506,24 +514,24 @@ mode = begin + strlen(begin_tag); begin_eol = mode; - while (*begin_eol && (*begin_eol != '\n' && *begin_eol != '\r')) + while (begin_eol < data_end && (*begin_eol != '\n' && *begin_eol != '\r')) { begin_eol++; } /* Fail if "begin " is on the last line of data */ - if (*begin_eol == 0x00) + if (begin_eol == data_end) { return NULL; } /* Check for correct mode syntax */ - for (i = 0; i < 4 && mode[i] && ok; i++) + for (i = 0; i < 4 && mode[i] && mode + i < data_end && ok; i++) { if ((mode[i] < '0' || mode[i] > '7') && !(i == 3 && mode[i] == ' ')) ok = 0; } - if (!ok) + if (!ok || mode + i == data_end) { return NULL; } @@ -552,7 +560,8 @@ /* Find "end" tag */ end = begin_eol; - while((end = strstr(end, end_tag)) && + while((end = a_Utils_memmem(end, data + size - end, + end_tag, strlen(end_tag))) && (*(end - 1) != '\n' && *(end - 1) != '\r')) { end++; @@ -560,11 +569,13 @@ if (end) { - *uu_end = end + strlen(end_tag); + /* Size of data from "begin" to "end" */ + *uu_size = end + strlen(end_tag) - begin; } else { - *uu_end = data + size; + /* Size is the remaining size from "begin" */ + *uu_size = size - (begin - data);; } return result; @@ -574,27 +585,27 @@ a_Utils_data_has_yencoded(const char *data, size_t size, const char **uu_start, - const char **uu_end) + size_t *uu_size) { const char *begin_tag = "=ybegin "; - return Utils_data_has_yencoded(data, size, uu_start, uu_end, begin_tag); + return Utils_data_has_yencoded(data, size, uu_start, uu_size, begin_tag); } char * a_Utils_data_has_yencoded2(const char *data, size_t size, const char **uu_start, - const char **uu_end) + size_t *uu_size) { const char *begin_tag = "=ybegin2 "; - return Utils_data_has_yencoded(data, size, uu_start, uu_end, begin_tag); + return Utils_data_has_yencoded(data, size, uu_start, uu_size, begin_tag); } static char * Utils_data_has_yencoded(const char *data, size_t size, const char **uu_start, - const char **uu_end, + size_t *uu_size, const char *begin_tag) { const char *begin; @@ -602,6 +613,7 @@ const char *begin_eol; const char *end; const char *end_eol; + const char *data_end = data + size; const char *filename; char buffer[MAX_ALLOWED_BEGIN_LINE_LEN + 1]; const char *size_tag; @@ -612,8 +624,9 @@ if (data == NULL || size == 0) return NULL; - - begin = strstr(data, begin_tag); + + /* We should loop until no begin is found */ + begin = a_Utils_memmem(data, size, begin_tag, strlen(begin_tag)); if (!begin) return NULL; @@ -626,12 +639,12 @@ begin_eol = begin + strlen(begin_tag); - while (*begin_eol && (*begin_eol != '\n' && *begin_eol != '\r')) + while (begin_eol < data_end && (*begin_eol != '\n' && *begin_eol != '\r')) { begin_eol++; } /* Fail if "begin " is on the last line of data */ - if (*begin_eol == 0x00) + if (begin_eol == data_end) { return NULL; } @@ -684,7 +697,8 @@ /* Find "=yend " tag */ end = begin_eol; - while((end = strstr(end, end_tag)) && + while((end = a_Utils_memmem(end, data + size - end, + end_tag, strlen(end_tag))) && (*(end - 1) != '\n' && *(end - 1) != '\r')) { end++; @@ -697,14 +711,14 @@ } end_eol = end + strlen(end_tag); - while (*end_eol && (*end_eol != '\n' && *end_eol != '\r')) + while (end_eol < data_end && (*end_eol != '\n' && *end_eol != '\r')) { end_eol++; } /* Fail if "=yend " does not have a trailing CR/LF */ #ifdef STRICT_YENC - if (*end_eol == 0x00) + if (end_eol == data_end) { return NULL; } @@ -740,7 +754,7 @@ /* We have apparently a yEncoded file at position 'begin' */ *uu_start = begin; - *uu_end = end_eol; + *uu_size = end_eol - begin; return result; } @@ -810,4 +824,39 @@ return 0; } - + +void * +a_Utils_memmem(const void *haystack, + size_t haystack_len, + const void *needle, + size_t needle_len) +{ +#ifdef HAVE_MEMMEM_DISABLED + return memmem(haystack, haystack_len, needle, needle_len); +#else + const unsigned char *hs_p; + const unsigned char *hs_oldp = (const unsigned char *) haystack; + const unsigned char *n_p = (const unsigned char *) needle; + const unsigned char *e_p = haystack + haystack_len; + size_t rem_len = haystack_len; + size_t i; + + while ((hs_oldp < e_p) && (hs_p = memchr(hs_oldp, *n_p, rem_len))) + { + rem_len -= hs_p - hs_oldp; + if (rem_len < needle_len) + return NULL; + i = 1; + for (i = 1; hs_p[i] == n_p[i] && i < needle_len; i++) + { + /* Empty on purpose: the search is done in the for loop */ + } + + if (i == needle_len) + return (void *) hs_p; + hs_oldp = hs_p + 1; + rem_len--; + } + return NULL; +#endif +} Index: utils.h =================================================================== RCS file: /cvsroot/libetpan/xetpan/src/utils.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- utils.h 28 May 2003 20:57:04 -0000 1.3 +++ utils.h 30 May 2003 19:42:37 -0000 1.4 @@ -192,7 +192,7 @@ a_Utils_data_has_uuencoded(const char *data, size_t size, const char **uu_start, - const char **uu_end); + size_t *uu_size); /*! Check if in-memory data contains a yEncoded data * \param data the in-memory data to be checked @@ -209,7 +209,7 @@ a_Utils_data_has_yencoded(const char *data, size_t size, const char **uu_start, - const char **uu_end); + size_t *uu_size); /*! Check if in-memory data contains a yEnc2 encoded data * Scan the data for a valid "=ybegin2 " line @@ -227,7 +227,7 @@ a_Utils_data_has_yencoded2(const char *data, size_t size, const char **uu_start, - const char **uu_end); + size_t *uu_size); /*! Convert a message original date to a local time @@ -239,5 +239,15 @@ int a_Utils_orig_date_to_localtime(struct mailimf_date_time *date_time, struct tm *local_tm); + +/*! Find an array of chars in a block of memory. This is equivalent in + * function to GNU's memmem and will use it if available at compile + * time + */ +void * +a_Utils_memmem(const void *haystack, + size_t haystack_len, + const void *needle, + size_t needle_len); #endif |