# HG changeset patch # User Timo Sirainen # Date 1496836632 -10800 # Node ID 7bb6969f1f08f198c30646f43419c723db9debfc # Parent 293249bf0b5a6721983afce23fce82ccb9081295 lib-mail: message_address_parse() - Fix reading out-of-bounds read on invalid input diff -r 293249bf0b5a -r 7bb6969f1f08 src/lib-mail/message-address.c --- a/src/lib-mail/message-address.c Wed Jun 07 13:34:39 2017 +0300 +++ b/src/lib-mail/message-address.c Wed Jun 07 14:57:12 2017 +0300 @@ -338,7 +338,8 @@ max_addresses--; if ((ret = parse_address(ctx)) == 0) break; - if (*ctx->parser.data != ',') { + if (ctx->parser.data == ctx->parser.end || + *ctx->parser.data != ',') { ret = -1; break; } diff -r 293249bf0b5a -r 7bb6969f1f08 src/lib-mail/test-message-address.c --- a/src/lib-mail/test-message-address.c Wed Jun 07 13:34:39 2017 +0300 +++ b/src/lib-mail/test-message-address.c Wed Jun 07 14:57:12 2017 +0300 @@ -15,6 +15,20 @@ a1->invalid_syntax == a2->invalid_syntax; } +static const struct message_address *test_parse_address(const char *input) +{ + /* duplicate the input (without trailing NUL) so valgrind notices + if there's any out-of-bounds access */ + size_t input_len = strlen(input); + unsigned char *input_dup = i_malloc(input_len); + memcpy(input_dup, input, input_len); + const struct message_address *addr = + message_address_parse(pool_datastack_create(), + input_dup, input_len, UINT_MAX, FALSE); + i_free(input_dup); + return addr; +} + static void test_message_address(void) { static const struct test { @@ -113,7 +127,7 @@ static struct message_address group_suffix = { NULL, NULL, NULL, NULL, NULL, FALSE }; - struct message_address *addr; + const struct message_address *addr; string_t *str, *group; const char *wanted_string; unsigned int i; @@ -126,9 +140,7 @@ for (i = 0; i < N_ELEMENTS(tests); i++) { const struct test *test = &tests[i]; - addr = message_address_parse(pool_datastack_create(), - (const unsigned char *)test->input, - strlen(test->input), UINT_MAX, FALSE); + addr = test_parse_address(test->input); test_assert_idx(addr != NULL && addr->next == NULL && cmp_addr(addr, &test->addr), i); @@ -151,8 +163,7 @@ test_end(); test_begin("message address parsing with groups"); - addr = message_address_parse(pool_datastack_create(), str_data(group), - str_len(group), UINT_MAX, FALSE); + addr = test_parse_address(str_c(group)); test_assert(addr != NULL && cmp_addr(addr, &group_prefix)); addr = addr->next; for (i = 0; i < N_ELEMENTS(tests) && addr != NULL; i++) { @@ -170,8 +181,7 @@ test_begin("message address parsing with empty group"); str_truncate(group, 0); str_append(group, "group:;"); - addr = message_address_parse(pool_datastack_create(), str_data(group), - str_len(group), UINT_MAX, FALSE); + addr = test_parse_address(str_c(group)); str_truncate(str, 0); message_address_write(str, addr); test_assert(addr != NULL && cmp_addr(addr, &group_prefix));