test-message-parser.c revision 7a12331c6360968b141a0888e0bf04dd24145f23
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainenstatic const char test_msg[] =
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen"Return-Path: <test@example.org>\n"
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen"Subject: Hello world\n"
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen"From: Test User <test@example.org>\n"
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen"To: Another User <test2@example.org>\n"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen"Message-Id: <1.2.3.4@example>\n"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen"Mime-Version: 1.0\n"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen"Date: Sun, 23 May 2007 04:58:08 +0300\n"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen"Content-Type: multipart/signed; micalg=pgp-sha1;\n"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen" protocol=\"application/pgp-signature\";\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen" boundary=\"=-GNQXLhuj24Pl1aCkk4/d\"\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"--=-GNQXLhuj24Pl1aCkk4/d\n"
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen"Content-Type: text/plain\n"
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen"Content-Transfer-Encoding: quoted-printable\n"
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen"There was a day=20\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"a happy=20day\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"--=-GNQXLhuj24Pl1aCkk4/d\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"Content-Type: application/pgp-signature; name=signature.asc\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"-----BEGIN PGP SIGNATURE-----\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"Version: GnuPG v1.2.4 (GNU/Linux)\n"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen"-----END PGP SIGNATURE-----\n"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen"--=-GNQXLhuj24Pl1aCkk4/d--\n"
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic bool msg_parts_cmp(struct message_part *p1, struct message_part *p2)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if ((p1->children != NULL) != (p2->children != NULL))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!msg_parts_cmp(p1->children, p2->children))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->header_size.physical_size != p2->header_size.physical_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->header_size.virtual_size != p2->header_size.virtual_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->header_size.lines != p2->header_size.lines ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->body_size.physical_size != p2->body_size.physical_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p1->body_size.virtual_size != p2->body_size.virtual_size ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void test_message_parser_small_blocks(void)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i, end_of_headers_idx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool = pool_alloconly_create("message parser", 10240);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* full parsing */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS |
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(strcmp(test_msg, str_c(output)) == 0);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen /* parsing in small blocks */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen parser = message_parser_init(pool, input, 0, 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while ((ret = message_parser_parse_next_block(parser,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert((ret == 0 && i <= TEST_MSG_LEN*2) ||
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen test_assert(message_parser_deinit(&parser, &parts2) == 0);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* parsing in small blocks from preparsed parts */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen end_of_headers_idx = (strstr(test_msg, "\n-----") - test_msg);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen parser = message_parser_init_from_parts(parts, input, 0,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen while ((ret = message_parser_parse_next_block(parser,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen test_assert((ret == 0 && i/2 <= end_of_headers_idx) ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(message_parser_deinit(&parser, &parts2) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void test_message_parser_truncated_mime_headers(void)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic const char input_msg[] =
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen"Content-Type: multipart/mixed; boundary=\":foo\"\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"Content-Type: text/plain\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"Content-Type: text/plain\r\n"
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen"Content-Type: text/html\n"
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_begin("message parser truncated mime headers");
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen pool = pool_alloconly_create("message parser", 10240);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen parser = message_parser_init(pool, input, 0, 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert((parts->flags & MESSAGE_PART_FLAG_MULTIPART) != 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->body_size.physical_size == 112);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen test_assert(parts->body_size.virtual_size == 112+7);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->header_size.physical_size == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->body_size.physical_size == 0);
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen test_assert(parts->children->body_size.lines == 0);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->header_size.physical_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->header_size.virtual_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->header_size.lines == 0);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->next->header_size.physical_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->next->header_size.virtual_size == 24);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk test_assert(parts->children->next->next->header_size.lines == 0);
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen test_assert(parts->children->next->next->next->header_size.physical_size == 23);
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen test_assert(parts->children->next->next->next->header_size.virtual_size == 23);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->next->next->next->header_size.lines == 0);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen for (part = parts->children; part != NULL; part = part->next) {
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen test_assert(part->body_size.physical_size == 0);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen test_assert(part->body_size.virtual_size == 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->next->next->next->next == NULL);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic void test_message_parser_duplicate_mime_boundary(void)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic const char input_msg[] =
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen"Content-Type: multipart/mixed; boundary=\"a\"\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"Content-Type: multipart/mixed; boundary=\"a\"\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"Content-Type: text/plain\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen test_begin("message parser duplicate mime boundary");
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen pool = pool_alloconly_create("message parser", 10240);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen parser = message_parser_init(pool, input, 0, 0);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->header_size.physical_size == 45);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->header_size.virtual_size == 45+2);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->body_size.physical_size == 84);
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen test_assert(parts->body_size.virtual_size == 84+7);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->physical_pos == 49);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->header_size.lines == 2);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->header_size.physical_size == 45);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->header_size.virtual_size == 45+2);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->body_size.lines == 4);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->body_size.physical_size == 35);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->body_size.virtual_size == 35+4);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME));
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->physical_pos == 98);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.lines == 2);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.physical_size == 26);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->header_size.virtual_size == 26+2);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen test_assert(parts->children->children->body_size.lines == 1);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.physical_size == 5);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.virtual_size == 5+1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void test_message_parser_continuing_mime_boundary(void)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic const char input_msg[] =
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen"Content-Type: multipart/mixed; boundary=\"a\"\n"
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen"Content-Type: multipart/mixed; boundary=\"ab\"\n"
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen"Content-Type: text/plain\n"
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen test_begin("message parser continuing mime boundary");
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen pool = pool_alloconly_create("message parser", 10240);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen parser = message_parser_init(pool, input, 0, 0);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->header_size.physical_size == 45);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->header_size.virtual_size == 45+2);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->body_size.physical_size == 86);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->body_size.virtual_size == 86+7);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->physical_pos == 49);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->header_size.lines == 2);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen test_assert(parts->children->header_size.physical_size == 46);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->header_size.virtual_size == 46+2);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->body_size.lines == 4);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->body_size.physical_size == 36);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->body_size.virtual_size == 36+4);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME));
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->physical_pos == 100);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.lines == 2);
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen test_assert(parts->children->children->header_size.physical_size == 26);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen test_assert(parts->children->children->header_size.virtual_size == 26+2);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.lines == 1);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.physical_size == 5);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen test_assert(parts->children->children->body_size.virtual_size == 5+1);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen pool = pool_alloconly_create("message parser", 10240);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen parser = message_parser_init(pool, input, 0, 0);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen test_assert(message_parser_parse_next_block(parser, &block) > 0 &&
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen block.hdr != NULL && strcmp(block.hdr->name, "a") == 0 &&
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen block.hdr->value_len == 1 && block.hdr->value[0] == 'b');
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen test_assert(message_parser_parse_next_block(parser, &block) > 0 &&
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen test_assert(message_parser_parse_next_block(parser, &block) < 0);
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen test_assert(message_parser_deinit(&parser, &parts) == 0);
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen static void (*test_functions[])(void) = {