1 | /* Tests for ns_name_pton. |
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/nameser.h> |
20 | #include <array_length.h> |
21 | #include <stdbool.h> |
22 | #include <stdio.h> |
23 | #include <stdlib.h> |
24 | #include <string.h> |
25 | #include <support/check.h> |
26 | #include <support/support.h> |
27 | #include <support/test-driver.h> |
28 | |
29 | /* Bits which indicate which functions are supposed to report |
30 | success. */ |
31 | enum |
32 | { |
33 | hnok = 1, |
34 | dnok = 2, |
35 | mailok = 4, |
36 | ownok = 8, |
37 | allnomailok = hnok | dnok | ownok, |
38 | allok = hnok | dnok | mailok | ownok |
39 | }; |
40 | |
41 | /* A string of 60 characters. */ |
42 | #define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" |
43 | |
44 | /* A string of 63 characters (maximum label length). */ |
45 | #define STRING63 STRING60 "zzz" |
46 | |
47 | /* A string of 60 bytes (non-ASCII). */ |
48 | #define STRING60OCT \ |
49 | "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ |
50 | "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ |
51 | "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ |
52 | "\377\377\377\377\377\377\377\377\377" |
53 | |
54 | /* A string of 63 bytes (non-ASCII). */ |
55 | #define STRING63OCT STRING60OCT "\377\377\377" |
56 | |
57 | /* A string of 60 bytes (non-ASCII, quoted decimal). */ |
58 | #define STRING60DEC \ |
59 | "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ |
60 | "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ |
61 | "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ |
62 | "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ |
63 | "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ |
64 | "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" |
65 | |
66 | /* A string of 63 bytes (non-ASCII, quoted decimal). */ |
67 | #define STRING63DEC STRING60DEC "\\255\\255\\255" |
68 | |
69 | /* Combines a test name with the expected results. */ |
70 | struct test_case |
71 | { |
72 | const char *dn; |
73 | const char *back; /* Expected test result converted using ns_name_ntop. */ |
74 | bool fully_qualified; /* True if the domain name has a trailing dot. */ |
75 | }; |
76 | |
77 | static const struct test_case tests[] = |
78 | { |
79 | { "" , "." , false }, |
80 | { "." , "." , true }, |
81 | { ".." , NULL, }, |
82 | { "www" , "www" , false }, |
83 | { "www." , "www" , true }, |
84 | { "www\\." , "www\\." , false }, |
85 | { ".www" , NULL, }, |
86 | { ".www\\." , NULL, }, |
87 | { "example.com" , "example.com" , false }, |
88 | { "example.com." , "example.com" , true }, |
89 | { ".example.com" , NULL, }, |
90 | { ".example.com." , NULL, }, |
91 | { "example\\.com" , "example\\.com" , false }, |
92 | { "example\\.com." , "example\\.com" , true }, |
93 | { "example.." , NULL, }, |
94 | { "example..com" , NULL, }, |
95 | { "example..com" , NULL, }, |
96 | { "\\0" , NULL, }, |
97 | { "\\00" , NULL, }, |
98 | { "\\000" , "\\000" , false }, |
99 | { "\\1" , NULL, }, |
100 | { "\\01" , NULL, }, |
101 | { "\\001" , "\\001" , false }, |
102 | { "\\1x" , NULL, }, |
103 | { "\\01x" , NULL, }, |
104 | { "\\001x" , "\\001x" , false }, |
105 | { "\\256" , NULL, }, |
106 | { "\\0641" , "\\@1" , false }, |
107 | { "\\0011" , "\\0011" , false }, |
108 | { STRING63, STRING63, false }, |
109 | { STRING63 "." , STRING63, true }, |
110 | { STRING63 "z" , NULL, }, |
111 | { STRING63 "\\." , NULL, }, |
112 | { STRING60 "zz\\." , STRING60 "zz\\." , false }, |
113 | { STRING60 "zz\\.." , STRING60 "zz\\." , true }, |
114 | { STRING63 "." STRING63 "." STRING63 "." STRING60 "z" , |
115 | STRING63 "." STRING63 "." STRING63 "." STRING60 "z" , false }, |
116 | { STRING63 "." STRING63 "." STRING63 "." STRING60 "z." , |
117 | STRING63 "." STRING63 "." STRING63 "." STRING60 "z" , true }, |
118 | { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz" , NULL, }, |
119 | { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz" , NULL, }, |
120 | { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377" , |
121 | STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255" , |
122 | false }, |
123 | { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377." , |
124 | STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255" , |
125 | true }, |
126 | { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT |
127 | "\377\377" , NULL, }, |
128 | { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT |
129 | "\377\377\377" , NULL, }, |
130 | { "\\" , NULL, }, |
131 | { "\\\\" , "\\\\" , false }, |
132 | { "\\\\." , "\\\\" , true }, |
133 | { "\\\\\\" , NULL, }, |
134 | { "a\\" , NULL, }, |
135 | { "a.\\" , NULL, }, |
136 | { "a.b\\" , NULL, }, |
137 | }; |
138 | |
139 | static int |
140 | do_test (void) |
141 | { |
142 | unsigned char *wire = xmalloc (NS_MAXCDNAME); |
143 | char *text = xmalloc (NS_MAXDNAME); |
144 | for (const struct test_case *test = tests; test < array_end (tests); ++test) |
145 | { |
146 | if (test_verbose) |
147 | printf (format: "info: testing domain name [[[%s]]]\n" , test->dn); |
148 | int ret = ns_name_pton (test->dn, wire, NS_MAXCDNAME); |
149 | if (ret == -1) |
150 | { |
151 | if (test->back != NULL) |
152 | { |
153 | support_record_failure (); |
154 | printf (format: "error: unexpected decoding failure for [[%s]]\n" , |
155 | test->dn); |
156 | } |
157 | /* Otherwise, we have an expected decoding failure. */ |
158 | continue; |
159 | } |
160 | |
161 | if (ret < -1 || ret > 1) |
162 | { |
163 | support_record_failure (); |
164 | printf (format: "error: invalid return value %d for [[%s]]\n" , |
165 | ret, test->dn); |
166 | continue; |
167 | } |
168 | |
169 | int ret2 = ns_name_ntop (wire, text, NS_MAXDNAME); |
170 | |
171 | if (ret2 < 0) |
172 | { |
173 | support_record_failure (); |
174 | printf (format: "error: failure to convert back [[%s]]\n" , test->dn); |
175 | } |
176 | |
177 | if (test->back == NULL) |
178 | { |
179 | support_record_failure (); |
180 | printf (format: "error: unexpected success converting [[%s]]\n" , test->dn); |
181 | if (ret2 >= 1) |
182 | printf (format: "error: result converts back to [[%s]]\n" , test->dn); |
183 | continue; |
184 | } |
185 | |
186 | if (strcmp (s1: text, s2: test->back) != 0) |
187 | { |
188 | support_record_failure (); |
189 | printf (format: "error: back-conversion of [[%s]] did not match\n" , |
190 | test->dn); |
191 | printf (format: "error: expected: [[%s]]\n" , test->back); |
192 | printf (format: "error: actual: [[%s]]\n" , text); |
193 | } |
194 | |
195 | if (ret != test->fully_qualified) |
196 | { |
197 | support_record_failure (); |
198 | printf (format: "error: invalid fully-qualified status for [[%s]]\n" , |
199 | test->dn); |
200 | printf (format: "error: expected: %d\n" , (int) test->fully_qualified); |
201 | printf (format: "error: actual: %d\n" , ret); |
202 | } |
203 | } |
204 | |
205 | free (ptr: text); |
206 | free (ptr: wire); |
207 | return 0; |
208 | } |
209 | |
210 | #include <support/test-driver.c> |
211 | |