1 /* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "str.h"
5 #include "str-sanitize.h"
6 #include "test-common.h"
7 #include "smtp-syntax.h"
8 
9 /*
10  * Valid string parse tests
11  */
12 
13 struct valid_string_parse_test {
14 	const char *input, *parsed, *output;
15 };
16 
17 static const struct valid_string_parse_test
18 valid_string_parse_tests[] = {
19 	{
20 		.input = "",
21 		.parsed = "",
22 	},
23 	{
24 		.input = "atom",
25 		.parsed = "atom",
26 	},
27 	{
28 		.input = "abcdefghijklmnopqrstuvwxyz"
29 			 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
30 			 "0123456789!#$%&'*+-/=?^_`{|}~",
31 		.parsed = "abcdefghijklmnopqrstuvwxyz"
32 			  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
33 			  "0123456789!#$%&'*+-/=?^_`{|}~",
34 	},
35 	{
36 		.input = "\"quoted-string\"",
37 		.parsed = "quoted-string",
38 		.output = "quoted-string",
39 	},
40 	{
41 		.input = "\"quoted \\\"string\\\"\"",
42 		.parsed = "quoted \"string\"",
43 	},
44 	{
45 		.input = "\"quoted \\\\string\\\\\"",
46 		.parsed = "quoted \\string\\",
47 	},
48 };
49 
50 static const unsigned int valid_string_parse_test_count =
51 	N_ELEMENTS(valid_string_parse_tests);
52 
test_smtp_string_parse_valid(void)53 static void test_smtp_string_parse_valid(void)
54 {
55 	unsigned int i;
56 
57 	for (i = 0; i < valid_string_parse_test_count; i++) T_BEGIN {
58 		const struct valid_string_parse_test *test =
59 			&valid_string_parse_tests[i];
60 		const char *parsed, *error = NULL;
61 		int ret;
62 
63 		ret = smtp_string_parse(test->input, &parsed, &error);
64 
65 		test_begin(t_strdup_printf("smtp string valid [%d]", i));
66 		test_out_reason(t_strdup_printf("parse(\"%s\")", test->input),
67 				ret >= 0, error);
68 		test_assert(ret != 0 || *test->input == '\0');
69 
70 		if (!test_has_failed()) {
71 			string_t *encoded;
72 			const char *output;
73 
74 			test_out(t_strdup_printf("parsed = \"%s\"", parsed),
75 				 null_strcmp(parsed, test->parsed) == 0);
76 
77 			encoded = t_str_new(255);
78 			smtp_string_write(encoded, parsed);
79 			output = (test->output == NULL ?
80 				  test->input : test->output);
81 			test_out(t_strdup_printf("write() = \"%s\"",
82 						 str_c(encoded)),
83 				 strcmp(str_c(encoded), output) == 0);
84 		}
85 		test_end();
86 	} T_END;
87 }
88 
89 /*
90  * Invalid string parse tests
91  */
92 
93 struct invalid_string_parse_test {
94 	const char *input;
95 };
96 
97 static const struct invalid_string_parse_test
98 invalid_string_parse_tests[] = {
99 	{
100 		.input = " ",
101 	},
102 	{
103 		.input = "\\",
104 	},
105 	{
106 		.input = "\"",
107 	},
108 	{
109 		.input = "\"aa",
110 	},
111 	{
112 		.input = "aa\"",
113 	},
114 };
115 
116 static const unsigned int invalid_string_parse_test_count =
117 	N_ELEMENTS(invalid_string_parse_tests);
118 
test_smtp_string_parse_invalid(void)119 static void test_smtp_string_parse_invalid(void)
120 {
121 	unsigned int i;
122 
123 	for (i = 0; i < invalid_string_parse_test_count; i++) T_BEGIN {
124 		const struct invalid_string_parse_test *test =
125 			&invalid_string_parse_tests[i];
126 		const char *parsed, *error;
127 		int ret;
128 
129 		ret = smtp_string_parse(test->input, &parsed, &error);
130 
131 		test_begin(t_strdup_printf("smtp string invalid [%d]", i));
132 		test_out_reason(t_strdup_printf("parse(\"%s\")", test->input),
133 				ret < 0, error);
134 		test_end();
135 	} T_END;
136 }
137 
138 /*
139  * Tests
140  */
141 
main(void)142 int main(void)
143 {
144 	static void (*test_functions[])(void) = {
145 		test_smtp_string_parse_valid,
146 		test_smtp_string_parse_invalid,
147 		NULL
148 	};
149 	return test_run(test_functions);
150 }
151