summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2013-02-20 18:03:42 +0100
committerGravatar Nikias Bassen2013-02-20 18:03:42 +0100
commitd86c2a34bdaa37dfd07c8ded8a19afbfc1066949 (patch)
treece99c4eb7efd55459f4655356b9b4b3bca720e37
parentf70f1876b9287dc21302ebce4d5374291087fc2b (diff)
downloadlibvformat-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.c52
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.
*/