1 | /* Test inet_pton functions. |
2 | Copyright (C) 2017-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <arpa/inet.h> |
20 | #include <resolv/resolv-internal.h> |
21 | #include <stdbool.h> |
22 | #include <stdio.h> |
23 | #include <string.h> |
24 | #include <support/check.h> |
25 | #include <support/next_to_fault.h> |
26 | #include <support/xunistd.h> |
27 | #include <unistd.h> |
28 | |
29 | struct test_case |
30 | { |
31 | /* The input data. */ |
32 | const char *input; |
33 | |
34 | /* True if AF_INET parses successfully. */ |
35 | bool ipv4_ok; |
36 | |
37 | /* True if AF_INET6 parses successfully. */ |
38 | bool ipv6_ok; |
39 | |
40 | /* Expected result for AF_INET. */ |
41 | unsigned char ipv4_expected[4]; |
42 | |
43 | /* Expected result for AF_INET6. */ |
44 | unsigned char ipv6_expected[16]; |
45 | }; |
46 | |
47 | static void |
48 | check_result (const char *what, const struct test_case *t, int family, |
49 | void *result_buffer, int inet_ret) |
50 | { |
51 | TEST_VERIFY_EXIT (inet_ret >= -1); |
52 | TEST_VERIFY_EXIT (inet_ret <= 1); |
53 | |
54 | int ok; |
55 | const unsigned char *expected; |
56 | size_t result_size; |
57 | switch (family) |
58 | { |
59 | case AF_INET: |
60 | ok = t->ipv4_ok; |
61 | expected = t->ipv4_expected; |
62 | result_size = 4; |
63 | break; |
64 | case AF_INET6: |
65 | ok = t->ipv6_ok; |
66 | expected = t->ipv6_expected; |
67 | result_size = 16; |
68 | break; |
69 | default: |
70 | FAIL_EXIT1 ("invalid address family %d" , family); |
71 | } |
72 | |
73 | if (inet_ret != ok) |
74 | { |
75 | support_record_failure (); |
76 | printf (format: "error: %s return value mismatch for [[%s]], family %d\n" |
77 | " expected: %d\n" |
78 | " actual: %d\n" , |
79 | what, t->input, family, ok, inet_ret); |
80 | return; |
81 | } |
82 | if (memcmp (s1: result_buffer, s2: expected, n: result_size) != 0) |
83 | { |
84 | support_record_failure (); |
85 | printf (format: "error: %s result mismatch for [[%s]], family %d\n" , |
86 | what, t->input, family); |
87 | } |
88 | } |
89 | |
90 | static void |
91 | run_one_test (const struct test_case *t) |
92 | { |
93 | size_t test_len = strlen (s: t->input); |
94 | |
95 | struct support_next_to_fault ntf_out4 = support_next_to_fault_allocate (size: 4); |
96 | struct support_next_to_fault ntf_out6 = support_next_to_fault_allocate (size: 16); |
97 | |
98 | /* inet_pton requires NUL termination. */ |
99 | { |
100 | struct support_next_to_fault ntf_in |
101 | = support_next_to_fault_allocate (size: test_len + 1); |
102 | memcpy (dest: ntf_in.buffer, src: t->input, n: test_len + 1); |
103 | memset (s: ntf_out4.buffer, c: 0, n: 4); |
104 | check_result (what: "inet_pton" , t, AF_INET, result_buffer: ntf_out4.buffer, |
105 | inet_ret: inet_pton (AF_INET, cp: ntf_in.buffer, buf: ntf_out4.buffer)); |
106 | memset (s: ntf_out6.buffer, c: 0, n: 16); |
107 | check_result (what: "inet_pton" , t, AF_INET6, result_buffer: ntf_out6.buffer, |
108 | inet_ret: inet_pton (AF_INET6, cp: ntf_in.buffer, buf: ntf_out6.buffer)); |
109 | support_next_to_fault_free (&ntf_in); |
110 | } |
111 | |
112 | /* __inet_pton_length does not require NUL termination. */ |
113 | { |
114 | struct support_next_to_fault ntf_in |
115 | = support_next_to_fault_allocate (size: test_len); |
116 | memcpy (dest: ntf_in.buffer, src: t->input, n: test_len); |
117 | memset (s: ntf_out4.buffer, c: 0, n: 4); |
118 | check_result (what: "__inet_pton_length" , t, AF_INET, result_buffer: ntf_out4.buffer, |
119 | inet_ret: __inet_pton_length (AF_INET, src: ntf_in.buffer, srclen: ntf_in.length, |
120 | ntf_out4.buffer)); |
121 | memset (s: ntf_out6.buffer, c: 0, n: 16); |
122 | check_result (what: "__inet_pton_length" , t, AF_INET6, result_buffer: ntf_out6.buffer, |
123 | inet_ret: __inet_pton_length (AF_INET6, src: ntf_in.buffer, srclen: ntf_in.length, |
124 | ntf_out6.buffer)); |
125 | support_next_to_fault_free (&ntf_in); |
126 | } |
127 | |
128 | support_next_to_fault_free (&ntf_out4); |
129 | support_next_to_fault_free (&ntf_out6); |
130 | } |
131 | |
132 | /* The test cases were manually crafted and the set enhanced with |
133 | American Fuzzy Lop. */ |
134 | const struct test_case test_cases[] = |
135 | { |
136 | {.input = ".:" , }, |
137 | {.input = "0.0.0.0" , |
138 | .ipv4_ok = true, |
139 | .ipv4_expected = {0, 0, 0, 0}, |
140 | }, |
141 | {.input = "0.:" , }, |
142 | {.input = "00" , }, |
143 | {.input = "0000000" , }, |
144 | {.input = "00000000000000000" , }, |
145 | {.input = "092." , }, |
146 | {.input = "10.0.301.2" , }, |
147 | {.input = "127.0.0.1" , |
148 | .ipv4_ok = true, |
149 | .ipv4_expected = {127, 0, 0, 1}, |
150 | }, |
151 | {.input = "19.." , }, |
152 | {.input = "192.0.2.-1" , }, |
153 | {.input = "192.0.2.01" , }, |
154 | {.input = "192.0.2.1." , }, |
155 | {.input = "192.0.2.1192." , }, |
156 | {.input = "192.0.2.192.\377.." , }, |
157 | {.input = "192.0.2.256" , }, |
158 | {.input = "192.0.2.27" , |
159 | .ipv4_ok = true, |
160 | .ipv4_expected = {192, 0, 2, 27}, |
161 | }, |
162 | {.input = "192.0.201." , }, |
163 | {.input = "192.0.261." , }, |
164 | {.input = "192.0.2\256" , }, |
165 | {.input = "192.0.\262." , }, |
166 | {.input = "192.062." , }, |
167 | {.input = "192.092.\256" , }, |
168 | {.input = "192.0\2562." , }, |
169 | {.input = "192.192.0.2661\031" , }, |
170 | {.input = "192.192.00n2.1." , }, |
171 | {.input = "192.192.2.190." , }, |
172 | {.input = "192.255.255.2555" , }, |
173 | {.input = "192.92.219\023." , }, |
174 | {.input = "192.\260.2." , }, |
175 | {.input = "1:1::1:1" , |
176 | .ipv6_ok = true, |
177 | .ipv6_expected = { |
178 | 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, |
179 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1 |
180 | }, |
181 | }, |
182 | {.input = "2" , }, |
183 | {.input = "2." , }, |
184 | {.input = "2001:db8:00001::f" , }, |
185 | {.input = "2001:db8:10000::f" , }, |
186 | {.input = "2001:db8:1234:5678:abcd:ef01:2345:67" , |
187 | .ipv6_ok = true, |
188 | .ipv6_expected = { |
189 | 0x20, 0x1, 0xd, 0xb8, 0x12, 0x34, 0x56, 0x78, |
190 | 0xab, 0xcd, 0xef, 0x1, 0x23, 0x45, 0x0, 0x67 |
191 | }, |
192 | }, |
193 | {.input = "2001:db8:1234:5678:abcd:ef01:2345:6789:1" , }, |
194 | {.input = "2001:db8:1234:5678:abcd:ef01:2345::6789" , }, |
195 | {.input = "2001:db8::0" , |
196 | .ipv6_ok = true, |
197 | .ipv6_expected = { |
198 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
199 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 |
200 | }, |
201 | }, |
202 | {.input = "2001:db8::00" , |
203 | .ipv6_ok = true, |
204 | .ipv6_expected = { |
205 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
206 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 |
207 | }, |
208 | }, |
209 | {.input = "2001:db8::1" , |
210 | .ipv6_ok = true, |
211 | .ipv6_expected = { |
212 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
213 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 |
214 | }, |
215 | }, |
216 | {.input = "2001:db8::10" , |
217 | .ipv6_ok = true, |
218 | .ipv6_expected = { |
219 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
220 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10 |
221 | }, |
222 | }, |
223 | {.input = "2001:db8::19" , |
224 | .ipv6_ok = true, |
225 | .ipv6_expected = { |
226 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
227 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19 |
228 | }, |
229 | }, |
230 | {.input = "2001:db8::1::\012" , }, |
231 | {.input = "2001:db8::1::2\012" , }, |
232 | {.input = "2001:db8::2" , |
233 | .ipv6_ok = true, |
234 | .ipv6_expected = { |
235 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
236 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 |
237 | }, |
238 | }, |
239 | {.input = "2001:db8::3" , |
240 | .ipv6_ok = true, |
241 | .ipv6_expected = { |
242 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
243 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3 |
244 | }, |
245 | }, |
246 | {.input = "2001:db8::4" , |
247 | .ipv6_ok = true, |
248 | .ipv6_expected = { |
249 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
250 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 |
251 | }, |
252 | }, |
253 | {.input = "2001:db8::5" , |
254 | .ipv6_ok = true, |
255 | .ipv6_expected = { |
256 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
257 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5 |
258 | }, |
259 | }, |
260 | {.input = "2001:db8::6" , |
261 | .ipv6_ok = true, |
262 | .ipv6_expected = { |
263 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
264 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6 |
265 | }, |
266 | }, |
267 | {.input = "2001:db8::7" , |
268 | .ipv6_ok = true, |
269 | .ipv6_expected = { |
270 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
271 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7 |
272 | }, |
273 | }, |
274 | {.input = "2001:db8::8" , |
275 | .ipv6_ok = true, |
276 | .ipv6_expected = { |
277 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
278 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8 |
279 | }, |
280 | }, |
281 | {.input = "2001:db8::9" , |
282 | .ipv6_ok = true, |
283 | .ipv6_expected = { |
284 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
285 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9 |
286 | }, |
287 | }, |
288 | {.input = "2001:db8::A" , |
289 | .ipv6_ok = true, |
290 | .ipv6_expected = { |
291 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
292 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa |
293 | }, |
294 | }, |
295 | {.input = "2001:db8::B" , |
296 | .ipv6_ok = true, |
297 | .ipv6_expected = { |
298 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
299 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb |
300 | }, |
301 | }, |
302 | {.input = "2001:db8::C" , |
303 | .ipv6_ok = true, |
304 | .ipv6_expected = { |
305 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
306 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc |
307 | }, |
308 | }, |
309 | {.input = "2001:db8::D" , |
310 | .ipv6_ok = true, |
311 | .ipv6_expected = { |
312 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
313 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd |
314 | }, |
315 | }, |
316 | {.input = "2001:db8::E" , |
317 | .ipv6_ok = true, |
318 | .ipv6_expected = { |
319 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
320 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe |
321 | }, |
322 | }, |
323 | {.input = "2001:db8::F" , |
324 | .ipv6_ok = true, |
325 | .ipv6_expected = { |
326 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
327 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf |
328 | }, |
329 | }, |
330 | {.input = "2001:db8::a" , |
331 | .ipv6_ok = true, |
332 | .ipv6_expected = { |
333 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
334 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa |
335 | }, |
336 | }, |
337 | {.input = "2001:db8::b" , |
338 | .ipv6_ok = true, |
339 | .ipv6_expected = { |
340 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
341 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb |
342 | }, |
343 | }, |
344 | {.input = "2001:db8::c" , |
345 | .ipv6_ok = true, |
346 | .ipv6_expected = { |
347 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
348 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc |
349 | }, |
350 | }, |
351 | {.input = "2001:db8::d" , |
352 | .ipv6_ok = true, |
353 | .ipv6_expected = { |
354 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
355 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd |
356 | }, |
357 | }, |
358 | {.input = "2001:db8::e" , |
359 | .ipv6_ok = true, |
360 | .ipv6_expected = { |
361 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
362 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe |
363 | }, |
364 | }, |
365 | {.input = "2001:db8::f" , |
366 | .ipv6_ok = true, |
367 | .ipv6_expected = { |
368 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
369 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf |
370 | }, |
371 | }, |
372 | {.input = "2001:db8::ff" , |
373 | .ipv6_ok = true, |
374 | .ipv6_expected = { |
375 | 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, |
376 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff |
377 | }, |
378 | }, |
379 | {.input = "2001:db8::ffff:2\012" , }, |
380 | {.input = "22" , }, |
381 | {.input = "2222@" , }, |
382 | {.input = "255.255.255.255" , |
383 | .ipv4_ok = true, |
384 | .ipv4_expected = {255, 255, 255, 255}, |
385 | }, |
386 | {.input = "255.255.255.255\001" , }, |
387 | {.input = "255.255.255.25555" , }, |
388 | {.input = "2:" , }, |
389 | {.input = "2:a:8:EEEE::EEEE:F:EEE8:EEEE\034*:" , }, |
390 | {.input = "2:ff:1:1:7:ff:1:1:7." , }, |
391 | {.input = "2f:0000000000000000000000000000000000000000000000000000000000" |
392 | "0000000000000000000000000000000000000000000000000000000000000000000000" |
393 | "0G01" , |
394 | }, |
395 | {.input = "429495" , }, |
396 | {.input = "5::5::" , }, |
397 | {.input = "6.6." , }, |
398 | {.input = "992." , }, |
399 | {.input = "::" , |
400 | .ipv6_ok = true, |
401 | .ipv6_expected = { |
402 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
403 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 |
404 | }, |
405 | }, |
406 | {.input = "::00001" , }, |
407 | {.input = "::1" , |
408 | .ipv6_ok = true, |
409 | .ipv6_expected = { |
410 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
411 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 |
412 | }, |
413 | }, |
414 | {.input = "::10000" , }, |
415 | {.input = "::1:1" , |
416 | .ipv6_ok = true, |
417 | .ipv6_expected = { |
418 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
419 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1 |
420 | }, |
421 | }, |
422 | {.input = "::ff:1:1:7.0.0.1" , |
423 | .ipv6_ok = true, |
424 | .ipv6_expected = { |
425 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, |
426 | 0x0, 0x1, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1 |
427 | }, |
428 | }, |
429 | {.input = "::ff:1:1:7:ff:1:1:7." , }, |
430 | {.input = "::ff:1:1:7ff:1:8:7.0.0.1" , }, |
431 | {.input = "::ff:1:1:7ff:1:8f:1:1:71" , }, |
432 | {.input = "::ffff:02fff:127.0.S1" , }, |
433 | {.input = "::ffff:127.0.0.1" , |
434 | .ipv6_ok = true, |
435 | .ipv6_expected = { |
436 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
437 | 0x0, 0x0, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x1 |
438 | }, |
439 | }, |
440 | {.input = "::ffff:1:7.0.0.1" , |
441 | .ipv6_ok = true, |
442 | .ipv6_expected = { |
443 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
444 | 0xff, 0xff, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1 |
445 | }, |
446 | }, |
447 | {.input = ":\272" , }, |
448 | {.input = "A:f:ff:1:1:D:ff:1:1::7." , }, |
449 | {.input = "AAAAA." , }, |
450 | {.input = "D:::" , }, |
451 | {.input = "DF8F" , }, |
452 | {.input = "F::" , |
453 | .ipv6_ok = true, |
454 | .ipv6_expected = { |
455 | 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, |
456 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 |
457 | }, |
458 | }, |
459 | {.input = "F:A:8:EEEE:8:EEEE\034*:" , }, |
460 | {.input = "F:a:8:EEEE:8:EEEE\034*:" , }, |
461 | {.input = "F:ff:100:7ff:1:8:7.0.10.1" , |
462 | .ipv6_ok = true, |
463 | .ipv6_expected = { |
464 | 0x0, 0xf, 0x0, 0xff, 0x1, 0x0, 0x7, 0xff, |
465 | 0x0, 0x1, 0x0, 0x8, 0x7, 0x0, 0xa, 0x1 |
466 | }, |
467 | }, |
468 | {.input = "d92." , }, |
469 | {.input = "ff:00000000000000000000000000000000000000000000000000000000000" |
470 | "00000000000000000000000000000000000000000000000000000000000000000001" , |
471 | }, |
472 | {.input = "fff2:2::ff2:2:f7" , |
473 | .ipv6_ok = true, |
474 | .ipv6_expected = { |
475 | 0xff, 0xf2, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, |
476 | 0x0, 0x0, 0xf, 0xf2, 0x0, 0x2, 0x0, 0xf7 |
477 | }, |
478 | }, |
479 | {.input = "ffff:ff:ff:fff:ff:ff:ff:" , }, |
480 | {.input = "\272:" , }, |
481 | {NULL} |
482 | }; |
483 | |
484 | static int |
485 | do_test (void) |
486 | { |
487 | for (size_t i = 0; test_cases[i].input != NULL; ++i) |
488 | run_one_test (t: test_cases + i); |
489 | return 0; |
490 | } |
491 | |
492 | #include <support/test-driver.c> |
493 | |