Skip to content

Commit

Permalink
lib-mail: rfc822-parser: Improve domain-literal parsing
Browse files Browse the repository at this point in the history
Strip away folding whitespace. Treat any extra '[' as an error.
  • Loading branch information
sirainen committed Aug 30, 2018
1 parent c98c10e commit 5ee7896
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 6 deletions.
36 changes: 30 additions & 6 deletions src/lib-mail/rfc822-parser.c
Expand Up @@ -312,6 +312,7 @@ static int
rfc822_parse_domain_literal(struct rfc822_parser_context *ctx, string_t *str)
{
const unsigned char *start;
size_t len;

/*
domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS]
Expand All @@ -324,15 +325,38 @@ rfc822_parse_domain_literal(struct rfc822_parser_context *ctx, string_t *str)
i_assert(ctx->data < ctx->end);
i_assert(*ctx->data == '[');

for (start = ctx->data; ctx->data < ctx->end; ctx->data++) {
if (*ctx->data == '\\') {
for (start = ctx->data++; ctx->data < ctx->end; ctx->data++) {
switch (*ctx->data) {
case '[':
/* not allowed */
return -1;
case ']':
str_append_data(str, start, ctx->data - start + 1);
ctx->data++;
return rfc822_skip_lwsp(ctx);
case '\n':
/* folding whitespace, remove the (CR)LF */
len = ctx->data - start;
if (len > 0 && start[len-1] == '\r')
len--;
str_append_data(str, start, len);
start = ctx->data + 1;
break;
case '\\':
/* note: the '\' is preserved in the output */
ctx->data++;
if (ctx->data >= ctx->end)
return -1;

if (*ctx->data == '\r' || *ctx->data == '\n') {
/* quoted-pair doesn't allow CR/LF.
They are part of the obs-qp though, so don't
return them as error. */
str_append_data(str, start, ctx->data - start);
start = ctx->data;
ctx->data--;
break;
} else if (*ctx->data == ']') {
ctx->data++;
str_append_data(str, start, ctx->data - start);
return rfc822_skip_lwsp(ctx);
}
}
}

Expand Down
34 changes: 34 additions & 0 deletions src/lib-mail/test-rfc822-parser.c
Expand Up @@ -41,6 +41,39 @@ static void test_rfc822_parse_quoted_string(void)
test_end();
}

static void test_rfc822_parse_domain_literal(void)
{
static const struct {
const char *input, *output;
int ret;
} tests[] = {
{ "@[", "", -1 },
{ "@[foo", "", -1 },
{ "@[foo[]", "", -1 },
{ "@[foo[]]", "", -1 },
{ "@[]", "[]", 0 },
{ "@[foo bar]", "[foo bar]", 0 },
{ "@[foo\n bar]", "[foo bar]", 0 },
{ "@[foo\n\t\t bar]", "[foo\t\t bar]", 0 },
{ "@[foo\\\n bar]", "[foo\\ bar]", 0 },
};
struct rfc822_parser_context parser;
string_t *str = t_str_new(64);
unsigned int i = 0;

test_begin("rfc822 parse domain literal");
for (i = 0; i < N_ELEMENTS(tests); i++) {
rfc822_parser_init(&parser, (const void *)tests[i].input,
strlen(tests[i].input), NULL);
test_assert_idx(rfc822_parse_domain(&parser, str) == tests[i].ret, i);
test_assert_idx(tests[i].ret < 0 ||
strcmp(tests[i].output, str_c(str)) == 0, i);
rfc822_parser_deinit(&parser);
str_truncate(str, 0);
}
test_end();
}

static void test_rfc822_parse_content_param(void)
{
const char *input =
Expand Down Expand Up @@ -76,6 +109,7 @@ int main(void)
{
static void (*const test_functions[])(void) = {
test_rfc822_parse_quoted_string,
test_rfc822_parse_domain_literal,
test_rfc822_parse_content_param,
NULL
};
Expand Down

0 comments on commit 5ee7896

Please sign in to comment.