Skip to content

Commit

Permalink
Revert base64 decoder optimizations to support chunked base64
Browse files Browse the repository at this point in the history
Fixes issue #150
  • Loading branch information
jstedfast committed Aug 26, 2023
1 parent 35fe6a8 commit b4de388
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 56 deletions.
82 changes: 35 additions & 47 deletions gmime/gmime-encodings.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static unsigned char gmime_base64_rank[256] = {
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,255,255,255,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
Expand Down Expand Up @@ -523,65 +523,53 @@ g_mime_encoding_base64_encode_step (const unsigned char *inbuf, size_t inlen, un
size_t
g_mime_encoding_base64_decode_step (const unsigned char *inbuf, size_t inlen, unsigned char *outbuf, int *state, guint32 *save)
{
register const unsigned char *inptr = inbuf;
const unsigned char *inend = inptr + inlen;
unsigned char *outptr = outbuf;
unsigned int saved = *save;
register const unsigned char *inptr;
register unsigned char *outptr;
const unsigned char *inend;
register guint32 saved;
unsigned char last[2];
unsigned char c, rank;
int n, eq, eof = 0;

int n;

inend = inbuf + inlen;
outptr = outbuf;
inptr = inbuf;

saved = *save;
n = *state;

/* if n == -1, then it means we've encountered the end of the base64 stream */
if (n == -1)
return 0;

/* decode every quartet into a triplet */

if (n < 0) {
last[0] = '=';
n = -n;
} else {
last[0] = '\0';
}

last[1] = '\0';

/* convert 4 base64 bytes to 3 normal bytes */
while (inptr < inend) {
rank = gmime_base64_rank[(c = *inptr++)];

if (rank != 0xFF) {
if (rank != 0xff) {
saved = (saved << 6) | rank;
last[1] = last[0];
last[0] = c;
n++;

if (n == 4) {
/* flush our decoded quartet */
*outptr++ = saved >> 16;
*outptr++ = saved >> 8;
*outptr++ = saved;
saved = 0;
if (last[1] != '=')
*outptr++ = saved >> 8;
if (last[0] != '=')
*outptr++ = saved;
n = 0;
}
} else if (c == '=') {
/* Note: this marks the end of the base64 stream. The only octet that can
* appear after this is another '=' (and possibly mailing-list junk). */
eof = 1;
break;
}
}

if (eof) {
/* Note: there shouldn't be more than 2 '=' octets at the end of a quartet,
* so if n < 2, then it means the encoder is broken. */
if (n > 1) {
/* at this point, n should be either 3 or 4 */
eq = 4 - n;
saved <<= (6 * eq);

*outptr++ = saved >> 16;
if (n > 2)
*outptr++ = saved >> 8;
}

/* Note: If the 'eof' state value changes, be sure to update logic in gmime-utils.c:rfc2047_token_decode() */
n = -1;
}

/* save state */

*state = last[0] == '=' ? -n : n;
*save = saved;
*state = n;

return (size_t) (outptr - outbuf);

return (outptr - outbuf);
}


Expand Down
12 changes: 3 additions & 9 deletions gmime/gmime-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1799,16 +1799,10 @@ rfc2047_token_decode (rfc2047_token *token, unsigned char *outbuf, int *state, g
const unsigned char *inbuf = (const unsigned char *) token->text;
size_t len = token->length;

if (token->encoding == 'B') {
/* Note: A state of -1 means that a previous rfc2047 encoded-word token ended with an '=' (aka 'eof'),
* so we need to reset the state. */
if (*state == -1)
*state = 0;

if (token->encoding == 'B')
return g_mime_encoding_base64_decode_step (inbuf, len, outbuf, state, save);
}

return quoted_decode (inbuf, len, outbuf, state, save);
else
return quoted_decode (inbuf, len, outbuf, state, save);
}

static char *
Expand Down

0 comments on commit b4de388

Please sign in to comment.