diff options
author | Nikias Bassen | 2013-02-20 18:03:42 +0100 |
---|---|---|
committer | Nikias Bassen | 2013-02-20 18:03:42 +0100 |
commit | d86c2a34bdaa37dfd07c8ded8a19afbfc1066949 (patch) | |
tree | ce99c4eb7efd55459f4655356b9b4b3bca720e37 | |
parent | f70f1876b9287dc21302ebce4d5374291087fc2b (diff) | |
download | libvformat-d86c2a34bdaa37dfd07c8ded8a19afbfc1066949.tar.gz libvformat-d86c2a34bdaa37dfd07c8ded8a19afbfc1066949.tar.bz2 |
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.
-rw-r--r-- | src/vf_parser.c | 52 |
1 files 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; + } } } } @@ -944,15 +985,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. */ |