]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: Change rfc822_parse_content_param() API to allow NULs in value
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Sat, 21 Apr 2018 09:47:22 +0000 (12:47 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 30 Aug 2018 08:12:56 +0000 (11:12 +0300)
This was the only function in rfc822-parser.h that wasn't NUL-safe.
This won't fix anything, but it makes the rfc822-parser.h API fully
consistent with the NUL handling.

Normally rfc2231_parse() should be called instead of calling
rfc822_parse_content_param() directly, so this shouldn't break any plugins.

src/lib-mail/rfc2231-parser.c
src/lib-mail/rfc822-parser.c
src/lib-mail/rfc822-parser.h
src/lib-mail/test-rfc822-parser.c

index c65b7982149fc8ae9ec1dea1e897fbe353fac11c..e940b9492ffdab9773c454dd55b17534403777e7 100644 (file)
@@ -43,7 +43,7 @@ int rfc2231_parse(struct rfc822_parser_context *ctx,
        ARRAY(struct rfc2231_parameter) rfc2231_params_arr;
        struct rfc2231_parameter rfc2231_param;
        const struct rfc2231_parameter *rfc2231_params;
-       const char *key, *value, *p, *p2;
+       const char *key, *p, *p2;
        string_t *str;
        unsigned int i, j, count, next, next_idx;
        bool ok, have_extended, broken = FALSE;
@@ -55,7 +55,8 @@ int rfc2231_parse(struct rfc822_parser_context *ctx,
        i_zero(&rfc2231_param);
        t_array_init(&result, 8);
        t_array_init(&rfc2231_params_arr, 8);
-       while ((ret = rfc822_parse_content_param(ctx, &key, &value)) != 0) {
+       str = t_str_new(64);
+       while ((ret = rfc822_parse_content_param(ctx, &key, str)) != 0) {
                if (ret < 0) {
                        /* try to continue anyway.. */
                        broken = TRUE;
@@ -85,12 +86,13 @@ int rfc2231_parse(struct rfc822_parser_context *ctx,
                                p = NULL;
                        else {
                                rfc2231_param.key = t_strdup_until(key, p2);
-                               rfc2231_param.value = value;
+                               rfc2231_param.value = t_strdup(str_c(str));
                                array_append(&rfc2231_params_arr,
                                             &rfc2231_param, 1);
                        }
                }
                if (p == NULL) {
+                       const char *value = t_strdup(str_c(str));
                        array_append(&result, &key, 1);
                        array_append(&result, &value, 1);
                }
@@ -111,7 +113,6 @@ int rfc2231_parse(struct rfc822_parser_context *ctx,
        /* keys are now sorted primarily by their name and secondarily by
           their index. If any indexes are missing, fallback to assuming
           these aren't RFC 2231 encoded parameters. */
-       str = t_str_new(64);
        for (i = 0; i < count; i = next) {
                ok = TRUE;
                have_extended = FALSE;
@@ -160,7 +161,7 @@ int rfc2231_parse(struct rfc822_parser_context *ctx,
                        key = rfc2231_params[i].key;
                        if (have_extended)
                                key = t_strconcat(key, "*", NULL);
-                       value = t_strdup(str_c(str));
+                       const char *value = t_strdup(str_c(str));
                        array_append(&result, &key, 1);
                        array_append(&result, &value, 1);
                }
index dc3409aaf27472b9c5d09029392fd043f3534743..917288cda72191c3836105b353bab778b99b7da9 100644 (file)
@@ -375,10 +375,9 @@ int rfc822_parse_content_type(struct rfc822_parser_context *ctx, string_t *str)
 }
 
 int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
-                              const char **key_r, const char **value_r)
+                              const char **key_r, string_t *value)
 {
-       string_t *tmp;
-       size_t value_pos;
+       string_t *key;
        int ret;
 
        /* .. := *(";" parameter)
@@ -387,7 +386,7 @@ int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
           value := token / quoted-string
        */
        *key_r = NULL;
-       *value_r = NULL;
+       str_truncate(value, 0);
 
        if (ctx->data >= ctx->end)
                return 0;
@@ -398,11 +397,9 @@ int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
        if (rfc822_skip_lwsp(ctx) <= 0)
                return -1;
 
-       tmp = t_str_new(64);
-       if (rfc822_parse_mime_token(ctx, tmp) <= 0)
+       key = t_str_new(64);
+       if (rfc822_parse_mime_token(ctx, key) <= 0)
                return -1;
-       str_append_c(tmp, '\0');
-       value_pos = str_len(tmp);
 
        if (*ctx->data != '=')
                return -1;
@@ -411,21 +408,20 @@ int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
        if ((ret = rfc822_skip_lwsp(ctx)) <= 0) {
                /* broken / no value */
        } else if (*ctx->data == '"') {
-               ret = rfc822_parse_quoted_string(ctx, tmp);
+               ret = rfc822_parse_quoted_string(ctx, value);
        } else if (ctx->data < ctx->end && *ctx->data == '=') {
                /* workaround for broken input:
                   name==?utf-8?b?...?= */
                while (ctx->data < ctx->end && *ctx->data != ';' &&
                       *ctx->data != ' ' && *ctx->data != '\t' &&
                       *ctx->data != '\r' && *ctx->data != '\n') {
-                       str_append_c(tmp, *ctx->data);
+                       str_append_c(value, *ctx->data);
                        ctx->data++;
                }
        } else {
-               ret = rfc822_parse_mime_token(ctx, tmp);
+               ret = rfc822_parse_mime_token(ctx, value);
        }
 
-       *key_r = str_c(tmp);
-       *value_r = *key_r + value_pos;
+       *key_r = str_c(key);
        return ret < 0 ? -1 : 1;
 }
index 466a68af5a1ce0897ae546e3bf010b59b2456af3..fe6afd26280671c15180b08ef9345e39ac5c5e6b 100644 (file)
@@ -54,9 +54,10 @@ int rfc822_parse_domain(struct rfc822_parser_context *ctx, string_t *str);
 /* Parse Content-Type header's type/subtype. */
 int rfc822_parse_content_type(struct rfc822_parser_context *ctx, string_t *str);
 /* For Content-Type style parameter parsing. Expect ";" key "=" value.
-   value is unescaped if needed. The returned strings are allocated from data
-   stack. Returns 1 = key/value set, 0 = no more data, -1 = invalid input. */
+   value is unescaped if needed. The returned key is allocated from data
+   stack. The value string is truncated for each call. Returns 1 = key/value
+   set, 0 = no more data, -1 = invalid input. */
 int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
-                              const char **key_r, const char **value_r);
+                              const char **key_r, string_t *value);
 
 #endif
index 4622962747b18ce743d1ccee76d0710ef54f455b..695021f1e5c30da46fd023335579ca7a484056b9 100644 (file)
@@ -49,16 +49,17 @@ static void test_rfc822_parse_content_param(void)
                { "key2", " \"(),/:;<=>?@[\\]" }
        };
        struct rfc822_parser_context parser;
-       const char *key, *value;
+       const char *key;
+       string_t *value = t_str_new(64);
        unsigned int i = 0;
        int ret;
 
        test_begin("rfc822 parse content param");
        rfc822_parser_init(&parser, (const void *)input, strlen(input), NULL);
-       while ((ret = rfc822_parse_content_param(&parser, &key, &value)) > 0 &&
+       while ((ret = rfc822_parse_content_param(&parser, &key, value)) > 0 &&
               i < N_ELEMENTS(output)) {
                test_assert_idx(strcmp(output[i].key, key) == 0, i);
-               test_assert_idx(strcmp(output[i].value, value) == 0, i);
+               test_assert_idx(strcmp(output[i].value, str_c(value)) == 0, i);
                i++;
        }
        rfc822_parser_deinit(&parser);