[svn] Don't tolerate non-base64 non-whitespace characters in base64 stream.

This commit is contained in:
hniksic 2005-07-04 06:28:19 -07:00
parent b6037a182f
commit e0aa2eef43
2 changed files with 38 additions and 19 deletions

View File

@ -1,3 +1,8 @@
2005-07-04 Hrvoje Niksic <hniksic@xemacs.org>
* utils.c (base64_decode): Don't silently tolerate non-base64
non-white-space characters in the base64 stream.
2005-07-04 Hrvoje Niksic <hniksic@xemacs.org> 2005-07-04 Hrvoje Niksic <hniksic@xemacs.org>
* connect.c (LAZY_RETRIEVE_INFO): Make last_tick unsigned to match * connect.c (LAZY_RETRIEVE_INFO): Make last_tick unsigned to match

View File

@ -1899,16 +1899,24 @@ base64_encode (const char *str, int length, char *b64store)
#define IS_ASCII(c) (((c) & 0x80) == 0) #define IS_ASCII(c) (((c) & 0x80) == 0)
#define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=') #define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=')
/* Get next character from the string, except that non-base64 /* Get next character from the string, ignoring whitespace. C should
characters are ignored, as mandated by rfc2045. */ be int, and will contain the next character, \0 if end is reached,
#define NEXT_BASE64_CHAR(c, p) do { \ or -1 if a non-ws non-base64 character is read. */
c = *p++; \ #define NEXT_BASE64_CHAR(c, p) for (;;) { \
} while (c != '\0' && !IS_BASE64 (c)) c = (unsigned char) *p++; \
if (IS_BASE64 (c) || c == '\0') \
break; \
else if (!ISSPACE (c)) \
{ \
c = -1; \
break; \
} \
/* c is whitespace, keep looping */ \
}
/* Decode data from BASE64 (assumed to be encoded as base64) into /* Decode data from BASE64 (pointer to \0-terminated text) into memory
memory pointed to by TO. TO should be large enough to accomodate pointed to by TO. TO should be large enough to accomodate the
the decoded data, which is guaranteed to be less than decoded data, which is guaranteed to be less than strlen(base64).
strlen(base64).
Since TO is assumed to contain binary data, it is not Since TO is assumed to contain binary data, it is not
NUL-terminated. The function returns the length of the data NUL-terminated. The function returns the length of the data
@ -1920,7 +1928,7 @@ base64_decode (const char *base64, char *to)
{ {
/* Table of base64 values for first 128 characters. Note that this /* Table of base64 values for first 128 characters. Note that this
assumes ASCII (but so does Wget in other places). */ assumes ASCII (but so does Wget in other places). */
static short base64_char_to_value[128] = static signed char base64_char_to_value[128] =
{ {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
@ -1936,36 +1944,39 @@ base64_decode (const char *base64, char *to)
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
}; };
#define BASE64_CHAR_TO_VALUE(c) ((int) base64_char_to_value[c])
const char *p = base64; const char *p = base64;
char *q = to; char *q = to;
while (1) while (1)
{ {
unsigned char c; int c;
unsigned long value; unsigned long value;
/* Process first byte of a quadruplet. */ /* Process first byte of a quadruplet. */
NEXT_BASE64_CHAR (c, p); NEXT_BASE64_CHAR (c, p);
if (!c) if (!c)
break; break;
if (c == '=') if (c == '=' || c == -1)
return -1; /* illegal '=' while decoding base64 */ return -1; /* illegal char while decoding base64 */
value = base64_char_to_value[c] << 18; value = BASE64_CHAR_TO_VALUE (c) << 18;
/* Process scond byte of a quadruplet. */ /* Process scond byte of a quadruplet. */
NEXT_BASE64_CHAR (c, p); NEXT_BASE64_CHAR (c, p);
if (!c) if (!c)
return -1; /* premature EOF while decoding base64 */ return -1; /* premature EOF while decoding base64 */
if (c == '=') if (c == '=' || c == -1)
return -1; /* illegal `=' while decoding base64 */ return -1; /* illegal char while decoding base64 */
value |= base64_char_to_value[c] << 12; value |= BASE64_CHAR_TO_VALUE (c) << 12;
*q++ = value >> 16; *q++ = value >> 16;
/* Process third byte of a quadruplet. */ /* Process third byte of a quadruplet. */
NEXT_BASE64_CHAR (c, p); NEXT_BASE64_CHAR (c, p);
if (!c) if (!c)
return -1; /* premature EOF while decoding base64 */ return -1; /* premature EOF while decoding base64 */
if (c == -1)
return -1; /* illegal char while decoding base64 */
if (c == '=') if (c == '=')
{ {
@ -1977,7 +1988,7 @@ base64_decode (const char *base64, char *to)
continue; continue;
} }
value |= base64_char_to_value[c] << 6; value |= BASE64_CHAR_TO_VALUE (c) << 6;
*q++ = 0xff & value >> 8; *q++ = 0xff & value >> 8;
/* Process fourth byte of a quadruplet. */ /* Process fourth byte of a quadruplet. */
@ -1986,10 +1997,13 @@ base64_decode (const char *base64, char *to)
return -1; /* premature EOF while decoding base64 */ return -1; /* premature EOF while decoding base64 */
if (c == '=') if (c == '=')
continue; continue;
if (c == -1)
return -1; /* illegal char while decoding base64 */
value |= base64_char_to_value[c]; value |= BASE64_CHAR_TO_VALUE (c);
*q++ = 0xff & value; *q++ = 0xff & value;
} }
#undef BASE64_CHAR_TO_VALUE
return q - to; return q - to;
} }