From d86c2a34bdaa37dfd07c8ded8a19afbfc1066949 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Wed, 20 Feb 2013 18:03:42 +0100 Subject: Fix base64 decoding for multi-line data The base64 decoder assumed that all data passed to it is a complete base64 blob. However due to the nature of different encoding schemes vformat data can also be spanned over multiple lines, usually prefixed by one or more spaces. The problem arises when a base64 line is broken in a non-by-4-dividable manner. We fix this by storing a remainder if the base64 data is not dividable by 4 and prepend it to the next decode operation. --- src/vf_parser.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/vf_parser.c b/src/vf_parser.c index 1197154..0d4e71e 100644 --- a/src/vf_parser.c +++ b/src/vf_parser.c @@ -171,6 +171,7 @@ typedef struct int state; /* Main state variable */ char qpchar; /* Workspace for QuotedPrintable decoder */ char *p_b64buf; /* Workspace for BASE64 decoder */ + char *p_b64rem; /* used during BASE64 decoding */ VOBJECT_T **pp_root_object; /* Pointer to the root */ VOBJECT_T *p_object; /* Current position in tree */ VPROP_T prop; /* Current property, copied into tree on completion */ @@ -556,7 +557,42 @@ bool_t vf_parse_text( { if (p_parse->p_b64buf) { - ok = handle_base64_chars(p_parse, p_parse->p_b64buf, p_strlen(p_parse->p_b64buf)); + char* b64buf = p_parse->p_b64buf; + int len = p_strlen(b64buf); + + /* skip spaces */ + while ((0 < len) && (SPACE == b64buf[0])) { + b64buf++; + len--; + } + + /* handle remainder */ + if (p_parse->p_b64rem) + { + char* newbuf = (char*)vf_malloc(len + p_strlen(p_parse->p_b64rem + 1)); + p_strcpy(newbuf, p_parse->p_b64rem); + + p_strcat(newbuf, b64buf); + b64buf = newbuf; + vf_free(p_parse->p_b64rem); + p_parse->p_b64rem = NULL; + } + + /* make sure length is dividable by 4 */ + len = p_strlen(b64buf); + int remaining = (len % 4); + int decode_len = len - remaining; + + /* store remainder if any */ + if (remaining > 0) + { + p_parse->p_b64rem = (char*)vf_malloc(remaining+1); + p_strcpy(p_parse->p_b64rem, b64buf + decode_len); + b64buf[decode_len] = '\0'; + } + + /* decode base64 data */ + ok = handle_base64_chars(p_parse, b64buf, decode_len); vf_free(p_parse->p_b64buf); p_parse->p_b64buf = NULL; @@ -574,6 +610,11 @@ bool_t vf_parse_text( vf_free(p_parse->p_b64buf); p_parse->p_b64buf = NULL; + if (p_parse->p_b64rem) + { + vf_free(p_parse->p_b64rem); + p_parse->p_b64rem = NULL; + } } } } @@ -943,15 +984,6 @@ bool_t handle_base64_chars( { bool_t ok = TRUE; - /* - * Skip spaces. - */ - while ((0 < numchars) && (SPACE == p_chars[0])) - { - numchars--; - p_chars++; - } - /* * Convert groups of 4 characters to byte triplets & append the bytes * to the binary data. -- cgit v1.1-32-gdbae