1 /* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "istream.h"
5 #include "message-size.h"
6 #include "test-common.h"
7 
8 static const char test_msg[] =
9 "Return-Path: <test@example.org>\n"
10 "Subject: Hello world\n"
11 "From: Test User <test@example.org>\n"
12 "To: Another User <test2@example.org>\n"
13 "Message-Id: <1.2.3.4@example>\n"
14 "Mime-Version: 1.0\n"
15 "Date: Sun, 23 May 2007 04:58:08 +0300\n"
16 "Content-Type: multipart/signed; micalg=pgp-sha1;\n"
17 "	protocol=\"application/pgp-signature\";\n"
18 "	boundary=\"=-GNQXLhuj24Pl1aCkk4/d\"\n"
19 "\n"
20 "--=-GNQXLhuj24Pl1aCkk4/d\n"
21 "Content-Type: text/plain\n"
22 "Content-Transfer-Encoding: quoted-printable\n"
23 "\n"
24 "There was a day=20\n"
25 "a happy=20day\n"
26 "\n"
27 "--=-GNQXLhuj24Pl1aCkk4/d\n"
28 "Content-Type: application/pgp-signature; name=signature.asc\n"
29 "\n"
30 "-----BEGIN PGP SIGNATURE-----\n"
31 "Version: GnuPG v1.2.4 (GNU/Linux)\n"
32 "\n"
33 "invalid\n"
34 "-----END PGP SIGNATURE-----\n"
35 "\n"
36 "--=-GNQXLhuj24Pl1aCkk4/d--\n"
37 "\n"
38 "\n";
39 
40 static const char test_msg_with_nuls[] =
41 "Return-Path: <test@example.org>\n"
42 "Subject: Hello world\n"
43 "From: Test User <test@example.org>\n"
44 "To: Another User <test2@example.org>\n"
45 "Message-Id: <1.2.3.4@example>\n"
46 "Mime-Version: 1.0\0\n"
47 "Date: Sun, 23 May 2007 04:58:08 +0300\n"
48 "Content-Type: multipart/signed; micalg=pgp-sha1;\n"
49 "	protocol=\"application/pgp-signature\";\n"
50 "	boundary=\"=-GNQXLhuj24Pl1aCkk4/d\"\n"
51 "\n"
52 "--=-GNQXLhuj24Pl1aCkk4/d\n"
53 "\n"
54 "Content-Type: text/plain\n"
55 "Content-Transfer-Encoding: quoted-printable\n"
56 "\n"
57 "There was\0 a day=20\n"
58 "a happy=20day\n"
59 "\n"
60 "--=-GNQXLhuj24Pl1aCkk4/d\n"
61 "Content-Type: application/pgp-signature; name=signature.asc\n"
62 "\n"
63 "-----BEGIN PGP SIGNATURE-----\n"
64 "Version: GnuPG v1.2.4 (GNU/Linux)\n"
65 "\n"
66 "inva\0lid\n"
67 "-----END PGP SIGNATURE-----\n"
68 "\n"
69 "--=-GNQXLhuj24Pl1aCkk4/d--\n"
70 "\n"
71 "\n";
72 
73 struct test_case {
74 	const char *test_name;
75 	const char *message;
76 	bool has_nuls;
77 	unsigned int body_newlines;
78 	unsigned int header_newlines;
79 	unsigned int message_len;
80 	unsigned int header_len;
81 };
82 static const struct test_case test_cases[] = {
83 	{
84 		.test_name = "message size",
85 		.message = test_msg,
86 		.has_nuls = FALSE,
87 		.body_newlines = 19,
88 		.header_newlines = 11,
89 		.message_len = sizeof(test_msg)-1,
90 		.header_len = 335,
91 	},
92 	{
93 		.test_name = "message size with nuls",
94 		.message = test_msg_with_nuls,
95 		.has_nuls = TRUE,
96 		.body_newlines = 20,
97 		.header_newlines = 11,
98 		.message_len = sizeof(test_msg_with_nuls)-1,
99 		.header_len = 336,
100 	},
101 };
102 
test_message_size(void)103 static void test_message_size(void)
104 {
105 	struct istream *input;
106 	struct message_size body_size, header_size;
107 	bool has_nuls;
108 	bool last_cr;
109 	unsigned int i;
110 
111 	for (i = 0; i < N_ELEMENTS(test_cases); i++) {
112 		test_begin(test_cases[i].test_name);
113 		input = i_stream_create_from_data(test_cases[i].message,
114 						  test_cases[i].message_len);
115 
116 		/* Read physical_size */
117 		message_get_header_size(input, &header_size, &has_nuls);
118 		test_assert_idx(has_nuls == test_cases[i].has_nuls, i);
119 		test_assert_idx(input->v_offset == test_cases[i].header_len, i);
120 		message_get_body_size(input, &body_size, &has_nuls);
121 		test_assert_idx(has_nuls == test_cases[i].has_nuls, i);
122 		test_assert_idx(input->v_offset  - body_size.physical_size ==
123 				test_cases[i].header_len, i);
124 		test_assert_idx(body_size.physical_size + header_size.physical_size ==
125 				test_cases[i].message_len, i);
126 
127 		/* Test last_cr handling */
128 		i_stream_seek(input, 0);
129 		message_skip_virtual(input, 0, &last_cr);
130 		test_assert_idx(!last_cr, i);
131 		message_skip_virtual(input, header_size.virtual_size-1, &last_cr);
132 		test_assert_idx(last_cr, i);
133 		message_skip_virtual(input, 2, &last_cr);
134 		test_assert_idx(!last_cr, i);
135 
136 		/* Skipped header size so read body again */
137 		message_get_body_size(input, &body_size, &has_nuls);
138 		test_assert_idx(has_nuls == test_cases[i].has_nuls, i);
139 		test_assert_idx(input->v_offset  - body_size.physical_size ==
140 				test_cases[i].header_len, i);
141 		test_assert_idx(body_size.physical_size + test_cases[i].body_newlines ==
142 				body_size.virtual_size, i);
143 		test_assert_idx(body_size.virtual_size + header_size.virtual_size -
144 				test_cases[i].body_newlines - test_cases[i].header_newlines ==
145 				test_cases[i].message_len, i);
146 
147 		i_stream_unref(&input);
148 		test_end();
149 	}
150 }
151 
main(void)152 int main(void)
153 {
154 	static void (*const test_functions[])(void) = {
155 		test_message_size,
156 		NULL
157 	};
158 	return test_run(test_functions);
159 }
160