1 /* Test ns_name-related functions.
2 Copyright (C) 2017-2021 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 /* This test program processes the tst-ns_name.data file. */
27 #include <support/check.h>
28 #include <support/support.h>
29 #include <support/xstdio.h>
31 /* A byte buffer and its length. */
38 /* Convert a base64-encoded string to its binary representation. */
40 base64_to_buffer (const char *base64
, struct buffer
*result
)
42 /* "-" denotes an empty input. */
43 if (strcmp (base64
, "-") == 0)
45 result
->data
= xmalloc (1);
50 size_t size
= strlen (base64
);
51 unsigned char *data
= xmalloc (size
);
52 int ret
= b64_pton (base64
, data
, size
);
53 if (ret
< 0 || ret
> size
)
55 result
->data
= xrealloc (data
, ret
);
60 /* A test case for ns_name_unpack and ns_name_ntop. */
68 struct buffer unpack_output
;
73 /* Deallocate the buffers associated with the test case. */
75 free_test_case (struct test_case
*t
)
79 free (t
->unpack_output
.data
);
83 /* Extract the test case information from a test file line. */
85 parse_test_case (const char *path
, size_t lineno
, const char *line
,
86 struct test_case
*result
)
88 memset (result
, 0, sizeof (*result
));
89 result
->path
= xstrdup (path
);
90 result
->lineno
= lineno
;
91 result
->ntop_result
= -1;
93 char *unpack_output
= NULL
;
94 int ret
= sscanf (line
, "%ms %zu %d %ms %d %ms",
95 &input
, &result
->input_offset
,
96 &result
->unpack_result
, &unpack_output
,
97 &result
->ntop_result
, &result
->ntop_text
);
100 printf ("%s:%zu: error: missing input fields\n", path
, lineno
);
104 if (!base64_to_buffer (input
, &result
->input
))
106 printf ("%s:%zu: error: malformed base64 input data\n", path
, lineno
);
108 free (unpack_output
);
109 free (result
->ntop_text
);
114 if (unpack_output
== NULL
)
115 result
->unpack_output
= (struct buffer
) { NULL
, 0 };
116 else if (!base64_to_buffer (unpack_output
, &result
->unpack_output
))
118 printf ("%s:%zu: error: malformed base64 unpack data\n", path
, lineno
);
119 free (result
->input
.data
);
120 free (unpack_output
);
121 free (result
->ntop_text
);
124 free (unpack_output
);
126 /* At this point, all allocated buffers have been transferred to
129 if (result
->input_offset
> result
->input
.length
)
131 printf ("%s:%zu: error: input offset %zu exceeds buffer size %zu\n",
132 path
, lineno
, result
->input_offset
, result
->input
.length
);
133 free_test_case (result
);
136 if (result
->unpack_result
< -1)
138 printf ("%s:%zu: error: invalid unpack result %d\n",
139 path
, lineno
, result
->unpack_result
);
140 free_test_case (result
);
143 if (result
->ntop_result
< -1)
145 printf ("%s:%zu: error: invalid ntop result %d\n",
146 path
, lineno
, result
->ntop_result
);
147 free_test_case (result
);
151 bool fields_consistent
;
155 fields_consistent
= result
->unpack_result
== -1;
158 fields_consistent
= result
->unpack_result
!= -1
159 && result
->ntop_result
== -1;
162 fields_consistent
= result
->unpack_result
!= -1
163 && result
->ntop_result
!= -1;
166 fields_consistent
= false;
168 if (!fields_consistent
)
170 printf ("%s:%zu: error: wrong number of fields: %d\n",
172 free_test_case (result
);
178 /* Format the buffer as a hexadecimal string and write it to standard
181 print_hex (const char *label
, struct buffer buffer
)
183 printf (" %s ", label
);
184 unsigned char *p
= buffer
.data
;
185 unsigned char *end
= p
+ buffer
.length
;
188 printf ("%02X", *p
& 0xFF);
194 /* Run the test case specified in *T. */
196 run_test_case (struct test_case
*t
)
198 /* Test ns_name_unpack. */
199 unsigned char *unpacked
= xmalloc (NS_MAXCDNAME
);
200 int consumed
= ns_name_unpack
201 (t
->input
.data
, t
->input
.data
+ t
->input
.length
,
202 t
->input
.data
+ t
->input_offset
,
203 unpacked
, NS_MAXCDNAME
);
204 if (consumed
!= t
->unpack_result
)
206 support_record_failure ();
207 printf ("%s:%zu: error: wrong result from ns_name_unpack\n"
210 t
->path
, t
->lineno
, t
->unpack_result
, consumed
);
215 if (memcmp (unpacked
, t
->unpack_output
.data
,
216 t
->unpack_output
.length
) != 0)
218 support_record_failure ();
219 printf ("%s:%zu: error: wrong data from ns_name_unpack\n",
221 print_hex ("expected:", t
->unpack_output
);
222 print_hex ("actual: ",
223 (struct buffer
) { unpacked
, t
->unpack_output
.length
});
227 /* Test ns_name_ntop. */
228 char *text
= xmalloc (NS_MAXDNAME
);
229 int ret
= ns_name_ntop (unpacked
, text
, NS_MAXDNAME
);
230 if (ret
!= t
->ntop_result
)
232 support_record_failure ();
233 printf ("%s:%zu: error: wrong result from ns_name_top\n"
236 t
->path
, t
->lineno
, t
->ntop_result
, ret
);
241 if (strcmp (text
, t
->ntop_text
) != 0)
243 support_record_failure ();
244 printf ("%s:%zu: error: wrong data from ns_name_ntop\n",
246 printf (" expected: \"%s\"\n", t
->ntop_text
);
247 printf (" actual: \"%s\"\n", text
);
251 /* Test ns_name_pton. Unpacking does not check the
252 NS_MAXCDNAME limit, but packing does, so we need to
253 adjust the expected result. */
255 if (t
->unpack_output
.length
> NS_MAXCDNAME
)
257 else if (strcmp (text
, ".") == 0)
258 /* The root domain is fully qualified. */
261 /* The domain name is never fully qualified. */
263 unsigned char *repacked
= xmalloc (NS_MAXCDNAME
);
264 ret
= ns_name_pton (text
, repacked
, NS_MAXCDNAME
);
267 support_record_failure ();
268 printf ("%s:%zu: error: wrong result from ns_name_pton\n"
271 t
->path
, t
->lineno
, expected
, ret
);
275 && memcmp (repacked
, unpacked
, t
->unpack_output
.length
) != 0)
277 support_record_failure ();
278 printf ("%s:%zu: error: wrong data from ns_name_pton\n",
280 print_hex ("expected:", t
->unpack_output
);
281 print_hex ("actual: ",
282 (struct buffer
) { repacked
, t
->unpack_output
.length
});
286 /* Test ns_name_compress, no compression case. */
287 if (t
->unpack_output
.length
> NS_MAXCDNAME
)
290 expected
= t
->unpack_output
.length
;
291 memset (repacked
, '$', NS_MAXCDNAME
);
293 enum { ptr_count
= 5 };
294 const unsigned char *dnptrs
[ptr_count
] = { repacked
, };
295 ret
= ns_name_compress (text
, repacked
, NS_MAXCDNAME
,
296 dnptrs
, dnptrs
+ ptr_count
);
299 support_record_failure ();
300 printf ("%s:%zu: error: wrong result from ns_name_compress\n"
303 t
->path
, t
->lineno
, expected
, ret
);
308 TEST_VERIFY (dnptrs
[0] == repacked
);
309 TEST_VERIFY (dnptrs
[1] == NULL
);
313 if (memcmp (repacked
, unpacked
, t
->unpack_output
.length
) != 0)
315 support_record_failure ();
316 printf ("%s:%zu: error: wrong data from ns_name_compress\n",
318 print_hex ("expected:", t
->unpack_output
);
319 print_hex ("actual: ", (struct buffer
) { repacked
, ret
});
322 TEST_VERIFY (dnptrs
[0] == repacked
);
323 if (unpacked
[0] == '\0')
324 /* The root domain is not a compression target. */
325 TEST_VERIFY (dnptrs
[1] == NULL
);
328 TEST_VERIFY (dnptrs
[1] == repacked
);
329 TEST_VERIFY (dnptrs
[2] == NULL
);
334 /* Test ns_name_compress, full compression case. Skip this
335 test for invalid names and the root domain. */
336 if (expected
>= 0 && unpacked
[0] != '\0')
338 /* The destination buffer needs additional room for the
339 offset, the initial name, and the compression
341 enum { name_offset
= 259 };
342 size_t target_offset
= name_offset
+ t
->unpack_output
.length
;
343 size_t repacked_size
= target_offset
+ 2;
344 repacked
= xrealloc (repacked
, repacked_size
);
345 memset (repacked
, '@', repacked_size
);
346 memcpy (repacked
+ name_offset
,
347 t
->unpack_output
.data
, t
->unpack_output
.length
);
348 enum { ptr_count
= 5 };
349 const unsigned char *dnptrs
[ptr_count
]
350 = { repacked
, repacked
+ name_offset
, };
351 ret
= ns_name_compress
352 (text
, repacked
+ target_offset
, NS_MAXCDNAME
,
353 dnptrs
, dnptrs
+ ptr_count
);
356 support_record_failure ();
357 printf ("%s:%zu: error: wrong result from ns_name_compress"
361 t
->path
, t
->lineno
, ret
);
364 if (memcmp (repacked
+ target_offset
, "\xc1\x03", 2) != 0)
366 support_record_failure ();
367 printf ("%s:%zu: error: wrong data from ns_name_compress"
371 print_hex ("actual: ",
372 (struct buffer
) { repacked
+ target_offset
, ret
});
375 TEST_VERIFY (dnptrs
[0] == repacked
);
376 TEST_VERIFY (dnptrs
[1] == repacked
+ name_offset
);
377 TEST_VERIFY (dnptrs
[2] == NULL
);
387 /* Open the file at PATH, parse the test cases contained in it, and
390 run_test_file (const char *path
)
392 FILE *fp
= xfopen (path
, "re");
394 size_t line_allocated
= 0;
399 ssize_t ret
= getline (&line
, &line_allocated
, fp
);
404 printf ("%s: error reading file: %m\n", path
);
407 TEST_VERIFY (feof (fp
));
415 if (*p
== '\0' || *p
== '#')
418 struct test_case test_case
;
419 if (!parse_test_case (path
, lineno
, line
, &test_case
))
421 support_record_failure ();
424 run_test_case (&test_case
);
425 free_test_case (&test_case
);
434 run_test_file ("tst-ns_name.data");
438 #include <support/test-driver.c>