1/* Tests for res_hnok and related 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 <array_length.h>
20#include <resolv.h>
21#include <string.h>
22#include <support/check.h>
23#include <support/test-driver.h>
24
25/* Bits which indicate which functions are supposed to report
26 success. */
27enum
28 {
29 hnok = 1,
30 dnok = 2,
31 mailok = 4,
32 ownok = 8,
33 allnomailok = hnok | dnok | ownok,
34 allok = hnok | dnok | mailok | ownok
35 };
36
37/* A string of 60 characters. */
38#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
39
40/* A string of 63 characters (maximum label length). */
41#define STRING63 STRING60 "zzz"
42
43/* Combines a test name with the expected results. */
44struct test_case
45{
46 const char *dn;
47 unsigned int result; /* Combination of the *ok flags. */
48};
49
50static const struct test_case tests[] =
51 {
52 { "", allok },
53 { ".", allok },
54 { "..", 0 },
55 { "www", allnomailok },
56 { "www.", allnomailok },
57 { "example", allnomailok },
58 { "example.com", allok },
59 { "www.example.com", allok },
60 { "www.example.com.", allok },
61 { "www-.example.com.", allok },
62 { "www.-example.com.", allok },
63 { "*.example.com", dnok | mailok | ownok },
64 { "-v", dnok },
65 { "-v.example.com", mailok | dnok },
66 { "**.example.com", dnok | mailok },
67 { "www.example.com\\", 0 },
68 { STRING63, allnomailok },
69 { STRING63 ".", allnomailok },
70 { STRING63 "\\.", 0 },
71 { STRING63 "z", 0 },
72 { STRING63 ".example.com", allok },
73 { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok },
74 { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", allok },
75 { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", 0 },
76 { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", 0 },
77 { "hostmaster@mail.example.com", dnok | mailok },
78 { "hostmaster\\@mail.example.com", dnok | mailok },
79 { "with whitespace", 0 },
80 { "with\twhitespace", 0 },
81 { "with\nwhitespace", 0 },
82 { "with.whitespace ", 0 },
83 { "with.whitespace\t", 0 },
84 { "with.whitespace\n", 0 },
85 { "with\\ whitespace", 0 },
86 { "with\\\twhitespace", 0 },
87 { "with\\\nwhitespace", 0 },
88 { "with.whitespace\\ ", 0 },
89 { "with.whitespace\\\t", 0 },
90 { "with.whitespace\\\n", 0 },
91 };
92
93/* Run test case *TEST with FUNC (named FUNCNAME) and report an error
94 if the result does not match the result flag at BIT. */
95static void
96one_test (const struct test_case *test, const char *funcname,
97 int (*func) (const char *), unsigned int bit)
98{
99 int expected = (test->result & bit) != 0;
100 int actual = func (test->dn);
101 if (actual != expected)
102 {
103 support_record_failure ();
104 printf (format: "error: %s (\"%s\"): expected=%d, actual=%d\n",
105 funcname, test->dn, expected, actual);
106 }
107}
108
109/* Run 255 tests using all the bytes from 1 to 255, surround the byte
110 with the strings PREFIX and SUFFIX, and check that FUNC (named
111 FUNCNAME) accepts only those bytes listed in ACCEPTED. */
112static void
113one_char (const char *prefix, const char *accepted, const char *suffix,
114 const char *funcname, int (*func) (const char *))
115{
116 for (int ch = 1; ch <= 255; ++ch)
117 {
118 char dn[1024];
119 snprintf (s: dn, maxlen: sizeof (dn), format: "%s%c%s", prefix, ch, suffix);
120 int expected = strchr (s: accepted, c: ch) != NULL;
121 int actual = func (dn);
122 if (actual != expected)
123 {
124 support_record_failure ();
125 printf (format: "error: %s (\"%s\"): expected=%d, actual=%d\n",
126 funcname, dn, expected, actual);
127 }
128 }
129}
130
131#define LETTERSDIGITS \
132 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
133
134#define PRINTABLE \
135 "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~"
136
137static int
138do_test (void)
139{
140 for (const struct test_case *test = tests; test < array_end (tests); ++test)
141 {
142 if (test_verbose)
143 printf (format: "info: testing domain name [[[%s]]] (0x%x)\n",
144 test->dn, test->result);
145 one_test (test, funcname: "res_hnok", func: res_hnok, bit: hnok);
146 one_test (test, funcname: "res_dnok", func: res_dnok, bit: dnok);
147 one_test (test, funcname: "res_mailok", func: res_mailok, bit: mailok);
148 one_test (test, funcname: "res_ownok", func: res_ownok, bit: ownok);
149 }
150
151 one_char
152 (prefix: "", LETTERSDIGITS "._", suffix: "", funcname: "res_hnok", func: res_hnok);
153 one_char
154 (prefix: "middle",
155 LETTERSDIGITS ".-_\\", /* "middle\\suffix" == "middlesuffix", so good. */
156 suffix: "suffix", funcname: "res_hnok", func: res_hnok);
157 one_char
158 (prefix: "middle",
159 LETTERSDIGITS ".-_" PRINTABLE,
160 suffix: "suffix.example", funcname: "res_mailok", func: res_mailok);
161 one_char
162 (prefix: "mailbox.middle",
163 LETTERSDIGITS ".-_\\",
164 suffix: "suffix.example", funcname: "res_mailok", func: res_mailok);
165
166 return 0;
167}
168
169#include <support/test-driver.c>
170

source code of glibc/resolv/tst-res_hnok.c