summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/t_urlencoded.c66
1 files changed, 44 insertions, 22 deletions
diff --git a/tests/t_urlencoded.c b/tests/t_urlencoded.c
index 3b3e6c2..9935c1c 100644
--- a/tests/t_urlencoded.c
+++ b/tests/t_urlencoded.c
@@ -21,7 +21,7 @@ static void case_path(void) {
21 ssize_t n; 21 ssize_t n;
22 22
23 test_case("path stops at the question mark"); 23 test_case("path stops at the question mark");
24 n = urlencoded_parse(&p, dest, SCAN_PATH); 24 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_PATH);
25 CHECK_INT(n, 9); 25 CHECK_INT(n, 9);
26 dest[n] = 0; 26 dest[n] = 0;
27 CHECK_STR(dest, "/announce"); 27 CHECK_STR(dest, "/announce");
@@ -35,22 +35,22 @@ static void case_param_and_value(void) {
35 ssize_t n; 35 ssize_t n;
36 36
37 test_case("parameter stops at '=', value stops at '&'"); 37 test_case("parameter stops at '=', value stops at '&'");
38 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); 38 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_PARAM);
39 CHECK_INT(n, 9); 39 CHECK_INT(n, 9);
40 dest[n] = 0; 40 dest[n] = 0;
41 CHECK_STR(dest, "info_hash"); 41 CHECK_STR(dest, "info_hash");
42 42
43 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 43 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
44 CHECK_INT(n, 3); 44 CHECK_INT(n, 3);
45 dest[n] = 0; 45 dest[n] = 0;
46 CHECK_STR(dest, "abc"); 46 CHECK_STR(dest, "abc");
47 47
48 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); 48 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_PARAM);
49 CHECK_INT(n, 4); 49 CHECK_INT(n, 4);
50 dest[n] = 0; 50 dest[n] = 0;
51 CHECK_STR(dest, "port"); 51 CHECK_STR(dest, "port");
52 52
53 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 53 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
54 CHECK_INT(n, 2); 54 CHECK_INT(n, 2);
55 dest[n] = 0; 55 dest[n] = 0;
56 CHECK_STR(dest, "80"); 56 CHECK_STR(dest, "80");
@@ -63,7 +63,7 @@ static void case_percent_decoding(void) {
63 ssize_t n; 63 ssize_t n;
64 64
65 test_case("percent escapes decode"); 65 test_case("percent escapes decode");
66 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 66 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
67 CHECK_INT(n, 3); 67 CHECK_INT(n, 3);
68 CHECK_MEM(dest, "ABC", 3); 68 CHECK_MEM(dest, "ABC", 3);
69} 69}
@@ -77,7 +77,7 @@ static void case_binary_info_hash(void) {
77 ssize_t n; 77 ssize_t n;
78 78
79 test_case("twenty byte binary value survives decoding"); 79 test_case("twenty byte binary value survives decoding");
80 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 80 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
81 CHECK_INT(n, 20); 81 CHECK_INT(n, 20);
82 CHECK_MEM(dest, want, 20); 82 CHECK_MEM(dest, want, 20);
83} 83}
@@ -88,7 +88,7 @@ static void case_in_place(void) {
88 ssize_t n; 88 ssize_t n;
89 89
90 test_case("decoding in place over the source is safe"); 90 test_case("decoding in place over the source is safe");
91 n = urlencoded_parse(&p, query, SCAN_SEARCHPATH_VALUE); 91 n = urlencoded_parse(&p, query, query + sizeof(query), SCAN_SEARCHPATH_VALUE);
92 CHECK_INT(n, 2); 92 CHECK_INT(n, 2);
93 CHECK_MEM(query, "AB", 2); 93 CHECK_MEM(query, "AB", 2);
94} 94}
@@ -100,7 +100,7 @@ static void case_bad_escape(void) {
100 ssize_t n; 100 ssize_t n;
101 101
102 test_case("a non hexadecimal escape is a parse error"); 102 test_case("a non hexadecimal escape is a parse error");
103 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 103 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
104 CHECK_INT(n, -1); 104 CHECK_INT(n, -1);
105} 105}
106 106
@@ -111,7 +111,7 @@ static void case_truncated_escape(void) {
111 ssize_t n; 111 ssize_t n;
112 112
113 test_case("an escape cut short by the terminator is a parse error"); 113 test_case("an escape cut short by the terminator is a parse error");
114 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 114 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
115 CHECK_INT(n, -1); 115 CHECK_INT(n, -1);
116} 116}
117 117
@@ -123,11 +123,11 @@ static void case_terminator(void) {
123 ssize_t n; 123 ssize_t n;
124 124
125 test_case("a hard terminator before any output reports end of input"); 125 test_case("a hard terminator before any output reports end of input");
126 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); 126 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_PARAM);
127 CHECK_INT(n, -2); 127 CHECK_INT(n, -2);
128 128
129 p = space; 129 p = space;
130 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_PARAM); 130 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_PARAM);
131 CHECK_INT(n, -2); 131 CHECK_INT(n, -2);
132} 132}
133 133
@@ -138,10 +138,10 @@ static void case_terminator_after_output(void) {
138 ssize_t n; 138 ssize_t n;
139 139
140 test_case("a hard terminator after output is left for the next call"); 140 test_case("a hard terminator after output is left for the next call");
141 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 141 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
142 CHECK_INT(n, 3); 142 CHECK_INT(n, 3);
143 CHECK_INT(*p, 0); 143 CHECK_INT(*p, 0);
144 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 144 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
145 CHECK_INT(n, -2); 145 CHECK_INT(n, -2);
146} 146}
147 147
@@ -157,14 +157,14 @@ static void case_separators_are_contextual(void) {
157 ssize_t n; 157 ssize_t n;
158 158
159 test_case("a question mark is literal inside a value"); 159 test_case("a question mark is literal inside a value");
160 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 160 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
161 CHECK_INT(n, 3); 161 CHECK_INT(n, 3);
162 dest[n] = 0; 162 dest[n] = 0;
163 CHECK_STR(dest, "a?b"); 163 CHECK_STR(dest, "a?b");
164 164
165 test_case("an equals sign is literal inside a value"); 165 test_case("an equals sign is literal inside a value");
166 p = equals; 166 p = equals;
167 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 167 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
168 CHECK_INT(n, 3); 168 CHECK_INT(n, 3);
169 dest[n] = 0; 169 dest[n] = 0;
170 CHECK_STR(dest, "a=b"); 170 CHECK_STR(dest, "a=b");
@@ -177,7 +177,7 @@ static void case_ampersand_in_path(void) {
177 ssize_t n; 177 ssize_t n;
178 178
179 test_case("an ampersand in a path is a parse error"); 179 test_case("an ampersand in a path is a parse error");
180 n = urlencoded_parse(&p, dest, SCAN_PATH); 180 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_PATH);
181 CHECK_INT(n, -1); 181 CHECK_INT(n, -1);
182} 182}
183 183
@@ -188,7 +188,7 @@ static void case_raw_high_byte(void) {
188 ssize_t n; 188 ssize_t n;
189 189
190 test_case("an undecoded byte above ASCII is a parse error"); 190 test_case("an undecoded byte above ASCII is a parse error");
191 n = urlencoded_parse(&p, dest, SCAN_SEARCHPATH_VALUE); 191 n = urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE);
192 CHECK_INT(n, -1); 192 CHECK_INT(n, -1);
193} 193}
194 194
@@ -215,15 +215,15 @@ static void case_find_keywords(void) {
215 char *p = match; 215 char *p = match;
216 216
217 test_case("a known keyword returns its value"); 217 test_case("a known keyword returns its value");
218 CHECK_INT(urlencoded_match_keyword(keywords, &p, SCAN_SEARCHPATH_PARAM), 2); 218 CHECK_INT(urlencoded_match_keyword(keywords, &p, match + sizeof(match), SCAN_SEARCHPATH_PARAM), 2);
219 219
220 test_case("an unknown keyword returns -3"); 220 test_case("an unknown keyword returns -3");
221 p = nomatch; 221 p = nomatch;
222 CHECK_INT(urlencoded_match_keyword(keywords, &p, SCAN_SEARCHPATH_PARAM), -3); 222 CHECK_INT(urlencoded_match_keyword(keywords, &p, nomatch + sizeof(nomatch), SCAN_SEARCHPATH_PARAM), -3);
223 223
224 test_case("a prefix of a keyword does not match it"); 224 test_case("a prefix of a keyword does not match it");
225 p = prefix; 225 p = prefix;
226 CHECK_INT(urlencoded_match_keyword(keywords, &p, SCAN_SEARCHPATH_PARAM), -3); 226 CHECK_INT(urlencoded_match_keyword(keywords, &p, prefix + sizeof(prefix), SCAN_SEARCHPATH_PARAM), -3);
227} 227}
228 228
229/* The encoding direction. Which bytes survive unescaped is fixed by what 229/* The encoding direction. Which bytes survive unescaped is fixed by what
@@ -313,10 +313,30 @@ static void case_fmt_decoder_disagrees_on_dollar(void) {
313 dest[n] = 0; 313 dest[n] = 0;
314 CHECK_STR(dest, "a$b"); 314 CHECK_STR(dest, "a$b");
315 315
316 got = urlencoded_parse(&p, scanned, SCAN_SEARCHPATH_VALUE); 316 got = urlencoded_parse(&p, scanned, scanned + sizeof(scanned), SCAN_SEARCHPATH_VALUE);
317 CHECK_INT(got, -1); 317 CHECK_INT(got, -1);
318} 318}
319 319
320static void case_value_stops_at_dest_end(void) {
321 /* A value that decodes to more than the destination holds is a parse error,
322 not a write past the buffer. (ip= used to overflow ws->outbuf this way.) */
323 char query[] = "AAAAAAAAAA&x=1"; /* ten A's then a terminator */
324 char dest[4];
325 char *p = query;
326 test_case("a value longer than the destination returns -1");
327 CHECK_INT((int)urlencoded_parse(&p, dest, dest + sizeof(dest), SCAN_SEARCHPATH_VALUE), -1);
328}
329
330static void case_keyword_with_decoded_nul_does_not_match(void) {
331 /* A percent-encoded NUL used to make a value match a shorter keyword and
332 then index the keyword past its end. */
333 static const ot_keywords keywords[] = {{"port", 1}, {NULL, -3}};
334 char query[] = "port%00xxxx=1";
335 char *p = query;
336 test_case("a keyword followed by a decoded NUL does not match the keyword");
337 CHECK_INT(urlencoded_match_keyword(keywords, &p, query + sizeof(query), SCAN_SEARCHPATH_PARAM), -3);
338}
339
320void test_urlencoded(void) { 340void test_urlencoded(void) {
321 case_path(); 341 case_path();
322 case_param_and_value(); 342 case_param_and_value();
@@ -332,6 +352,8 @@ void test_urlencoded(void) {
332 case_raw_high_byte(); 352 case_raw_high_byte();
333 case_skipvalue(); 353 case_skipvalue();
334 case_find_keywords(); 354 case_find_keywords();
355 case_value_stops_at_dest_end();
356 case_keyword_with_decoded_nul_does_not_match();
335 case_fmt_passes_safe_bytes(); 357 case_fmt_passes_safe_bytes();
336 case_fmt_escapes_the_rest(); 358 case_fmt_escapes_the_rest();
337 case_fmt_hex_is_lower_case(); 359 case_fmt_hex_is_lower_case();