diff --git a/src/lib-mail/rfc2231-parser.c b/src/lib-mail/rfc2231-parser.c index e940b9492f..9b6cd4d360 100644 --- a/src/lib-mail/rfc2231-parser.c +++ b/src/lib-mail/rfc2231-parser.c @@ -47,8 +47,14 @@ int rfc2231_parse(struct rfc822_parser_context *ctx, string_t *str; unsigned int i, j, count, next, next_idx; bool ok, have_extended, broken = FALSE; + char prev_replacement_char; int ret; + /* Temporarily replace the nul_replacement_char while we're parsing + the content-params. It'll be restored before we return. */ + prev_replacement_char = ctx->nul_replacement_char; + ctx->nul_replacement_char = RFC822_NUL_REPLACEMENT_CHAR; + /* Get a list of all parameters. RFC 2231 uses key*[*]=value pairs, which we want to merge to a key[*]=value pair. Save them to a separate array. */ @@ -97,6 +103,7 @@ int rfc2231_parse(struct rfc822_parser_context *ctx, array_append(&result, &value, 1); } } + ctx->nul_replacement_char = prev_replacement_char; if (array_count(&rfc2231_params_arr) == 0) { /* No RFC 2231 parameters */ diff --git a/src/lib-mail/rfc2231-parser.h b/src/lib-mail/rfc2231-parser.h index 1c44349880..0db536fd4e 100644 --- a/src/lib-mail/rfc2231-parser.h +++ b/src/lib-mail/rfc2231-parser.h @@ -3,8 +3,9 @@ /* Parse all content parameters using rfc822_parse_content_param() and return them as a NULL-terminated [key, value] array. RFC 2231-style continuations - are merged to a single key. Returns -1 if some of the input was invalid - (but valid key/value pairs are still returned), 0 if everything looked ok. */ + are merged to a single key. NULs are converted into 0x80. Returns -1 if some + of the input was invalid (but valid key/value pairs are still returned), 0 + if everything looked ok. */ int ATTR_NOWARN_UNUSED_RESULT rfc2231_parse(struct rfc822_parser_context *ctx, const char *const **result_r); diff --git a/src/lib-mail/test-rfc2231-parser.c b/src/lib-mail/test-rfc2231-parser.c index 59204f4ee5..3c7e1b61f7 100644 --- a/src/lib-mail/test-rfc2231-parser.c +++ b/src/lib-mail/test-rfc2231-parser.c @@ -7,18 +7,18 @@ static void test_rfc2231_parser(void) { - const char *input = + const unsigned char input[] = "; key4*=us-ascii''foo" "; key*2=ba%" "; key2*0=a" "; key3*0*=us-ascii'en'xyz" - "; key*0=\"foo\"" + "; key*0=\"f\0oo\"" "; key2*1*=b%25" "; key3*1=plop%" "; key*1=baz"; const char *output[] = { "key", - "foobazba%", + "f\x80oobazba%", "key2*", "''ab%25", "key3*", @@ -32,10 +32,10 @@ static void test_rfc2231_parser(void) unsigned int i; test_begin("rfc2231 parser"); - rfc822_parser_init(&parser, (const void *)input, strlen(input), NULL); + rfc822_parser_init(&parser, input, sizeof(input)-1, NULL); test_assert(rfc2231_parse(&parser, &result) == 0); for (i = 0; output[i] != NULL && result[i] != NULL; i++) - test_assert(strcmp(output[i], result[i]) == 0); + test_assert_idx(strcmp(output[i], result[i]) == 0, i); rfc822_parser_deinit(&parser); test_assert(output[i] == NULL && result[i] == NULL); test_end();