xref: /aosp_15_r20/external/cronet/net/dns/dns_names_util_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/dns/dns_names_util.h"
6 
7 #include <climits>
8 #include <cstdint>
9 #include <cstring>
10 #include <optional>
11 #include <string>
12 #include <string_view>
13 #include <vector>
14 
15 #include "base/containers/span_reader.h"
16 #include "base/numerics/safe_conversions.h"
17 #include "net/dns/dns_util.h"
18 #include "net/dns/public/dns_protocol.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace net::dns_names_util {
23 namespace {
24 
25 using ::testing::Eq;
26 using ::testing::Optional;
27 
28 // ToBytes converts a char* to a std::vector<uint8_t> and includes the
29 // terminating NUL in the result.
ToBytes(const char * in)30 std::vector<uint8_t> ToBytes(const char* in) {
31   size_t size = strlen(in) + 1;
32   std::vector<uint8_t> out(size, 0);
33   memcpy(out.data(), in, size);
34   return out;
35 }
36 
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidation)37 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidation) {
38   EXPECT_THAT(
39       DottedNameToNetwork("com", /*require_valid_internet_hostname=*/true),
40       Optional(ToBytes("\003com")));
41   EXPECT_THAT(DottedNameToNetwork("google.com",
42                                   /*require_valid_internet_hostname=*/true),
43               Optional(ToBytes("\x006google\003com")));
44   EXPECT_THAT(DottedNameToNetwork("www.google.com",
45                                   /*require_valid_internet_hostname=*/true),
46               Optional(ToBytes("\003www\006google\003com")));
47 }
48 
TEST(DnsNamesUtilTest,DottedNameToNetwork)49 TEST(DnsNamesUtilTest, DottedNameToNetwork) {
50   EXPECT_THAT(
51       DottedNameToNetwork("com", /*require_valid_internet_hostname=*/false),
52       Optional(ToBytes("\003com")));
53   EXPECT_THAT(DottedNameToNetwork("google.com",
54                                   /*require_valid_internet_hostname=*/false),
55               Optional(ToBytes("\x006google\003com")));
56   EXPECT_THAT(DottedNameToNetwork("www.google.com",
57                                   /*require_valid_internet_hostname=*/false),
58               Optional(ToBytes("\003www\006google\003com")));
59 }
60 
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationRejectsEmptyLabels)61 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidationRejectsEmptyLabels) {
62   EXPECT_FALSE(DottedNameToNetwork("", /*require_valid_internet_hostname=*/true)
63                    .has_value());
64   EXPECT_FALSE(
65       DottedNameToNetwork(".", /*require_valid_internet_hostname=*/true)
66           .has_value());
67   EXPECT_FALSE(
68       DottedNameToNetwork("..", /*require_valid_internet_hostname=*/true)
69           .has_value());
70   EXPECT_FALSE(DottedNameToNetwork(".google.com",
71                                    /*require_valid_internet_hostname=*/true)
72                    .has_value());
73   EXPECT_FALSE(DottedNameToNetwork("www..google.com",
74                                    /*require_valid_internet_hostname=*/true)
75                    .has_value());
76 }
77 
TEST(DnsNamesUtilTest,DottedNameToNetworkRejectsEmptyLabels)78 TEST(DnsNamesUtilTest, DottedNameToNetworkRejectsEmptyLabels) {
79   EXPECT_FALSE(
80       DottedNameToNetwork("", /*require_valid_internet_hostname=*/false)
81           .has_value());
82   EXPECT_FALSE(
83       DottedNameToNetwork(".", /*require_valid_internet_hostname=*/false)
84           .has_value());
85   EXPECT_FALSE(
86       DottedNameToNetwork("..", /*require_valid_internet_hostname=*/false)
87           .has_value());
88   EXPECT_FALSE(DottedNameToNetwork(".google.com",
89                                    /*require_valid_internet_hostname=*/false)
90                    .has_value());
91   EXPECT_FALSE(DottedNameToNetwork("www..google.com",
92                                    /*require_valid_internet_hostname=*/false)
93                    .has_value());
94 }
95 
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationAcceptsEmptyLabelAtEnd)96 TEST(DnsNamesUtilTest,
97      DottedNameToNetworkWithValidationAcceptsEmptyLabelAtEnd) {
98   EXPECT_THAT(DottedNameToNetwork("www.google.com.",
99                                   /*require_valid_internet_hostname=*/true),
100               Optional(ToBytes("\003www\006google\003com")));
101 }
102 
TEST(DnsNamesUtilTest,DottedNameToNetworkAcceptsEmptyLabelAtEnd)103 TEST(DnsNamesUtilTest, DottedNameToNetworkAcceptsEmptyLabelAtEnd) {
104   EXPECT_THAT(DottedNameToNetwork("www.google.com.",
105                                   /*require_valid_internet_hostname=*/false),
106               Optional(ToBytes("\003www\006google\003com")));
107 }
108 
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationAllowsLongNames)109 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidationAllowsLongNames) {
110   // Label is 63 chars: still valid
111   EXPECT_THAT(
112       DottedNameToNetwork(
113           "z23456789a123456789a123456789a123456789a123456789a123456789a123",
114           /*require_valid_internet_hostname=*/true),
115       Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
116                        "789a123456789a123")));
117   EXPECT_THAT(
118       DottedNameToNetwork(
119           "z23456789a123456789a123456789a123456789a123456789a123456789a123.",
120           /*require_valid_internet_hostname=*/true),
121       Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
122                        "789a123456789a123")));
123 
124   // 253 characters in the name: still valid
125   EXPECT_THAT(
126       DottedNameToNetwork(
127           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
128           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
129           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
130           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
131           "abcdefghi.abc",
132           /*require_valid_internet_hostname=*/true),
133       Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
134                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
135                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
136                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
137                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
138                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
139                        "\011abcdefghi\003abc")));
140 
141   // 253 characters in the name plus final dot: still valid
142   EXPECT_THAT(
143       DottedNameToNetwork(
144           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
145           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
146           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
147           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
148           "abcdefghi.abc.",
149           /*require_valid_internet_hostname=*/true),
150       Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
151                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
152                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
153                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
154                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
155                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
156                        "\011abcdefghi\003abc")));
157 }
158 
TEST(DnsNamesUtilTest,DottedNameToNetworkAllowsLongNames)159 TEST(DnsNamesUtilTest, DottedNameToNetworkAllowsLongNames) {
160   // Label is 63 chars: still valid
161   EXPECT_THAT(
162       DottedNameToNetwork(
163           "z23456789a123456789a123456789a123456789a123456789a123456789a123",
164           /*require_valid_internet_hostname=*/false),
165       Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
166                        "789a123456789a123")));
167   // Label is 63 chars: still valid
168   EXPECT_THAT(
169       DottedNameToNetwork(
170           "z23456789a123456789a123456789a123456789a123456789a123456789a123.",
171           /*require_valid_internet_hostname=*/false),
172       Optional(ToBytes("\077z23456789a123456789a123456789a123456789a123456"
173                        "789a123456789a123")));
174 
175   // 253 characters in the name: still valid
176   EXPECT_THAT(
177       DottedNameToNetwork(
178           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
179           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
180           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
181           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
182           "abcdefghi.abc",
183           /*require_valid_internet_hostname=*/false),
184       Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
185                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
186                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
187                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
188                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
189                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
190                        "\011abcdefghi\003abc")));
191 
192   // 253 characters in the name plus final dot: still valid
193   EXPECT_THAT(
194       DottedNameToNetwork(
195           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
196           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
197           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
198           "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
199           "abcdefghi.abc.",
200           /*require_valid_internet_hostname=*/false),
201       Optional(ToBytes("\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
202                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
203                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
204                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
205                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
206                        "\011abcdefghi\011abcdefghi\011abcdefghi\011abcdefghi"
207                        "\011abcdefghi\003abc")));
208 }
209 
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationRejectsTooLongNames)210 TEST(DnsNamesUtilTest, DottedNameToNetworkWithValidationRejectsTooLongNames) {
211   // Label is too long: invalid
212   EXPECT_FALSE(
213       DottedNameToNetwork(
214           "123456789a123456789a123456789a123456789a123456789a123456789a1234",
215           /*require_valid_internet_hostname=*/true)
216           .has_value());
217   EXPECT_FALSE(
218       DottedNameToNetwork(
219           "123456789a123456789a123456789a123456789a123456789a123456789a1234.",
220           /*require_valid_internet_hostname=*/true)
221           .has_value());
222 
223   // 254 characters in the name: invalid
224   EXPECT_FALSE(
225       DottedNameToNetwork(
226           "123456789.123456789.123456789.123456789.123456789.123456789."
227           "123456789.123456789.123456789.123456789.123456789.123456789."
228           "123456789.123456789.123456789.123456789.123456789.123456789."
229           "123456789.123456789.123456789.123456789.123456789.123456789."
230           "123456789.1234",
231           /*require_valid_internet_hostname=*/true)
232           .has_value());
233   EXPECT_FALSE(
234       DottedNameToNetwork(
235           "123456789.123456789.123456789.123456789.123456789.123456789."
236           "123456789.123456789.123456789.123456789.123456789.123456789."
237           "123456789.123456789.123456789.123456789.123456789.123456789."
238           "123456789.123456789.123456789.123456789.123456789.123456789."
239           "123456789.1234.",
240           /*require_valid_internet_hostname=*/true)
241           .has_value());
242 
243   // 255 characters in the name: invalid before even trying to add a final
244   // zero-length termination
245   EXPECT_FALSE(
246       DottedNameToNetwork(
247           "123456789.123456789.123456789.123456789.123456789.123456789."
248           "123456789.123456789.123456789.123456789.123456789.123456789."
249           "123456789.123456789.123456789.123456789.123456789.123456789."
250           "123456789.123456789.123456789.123456789.123456789.123456789."
251           "123456789.12345",
252           /*require_valid_internet_hostname=*/true)
253           .has_value());
254   EXPECT_FALSE(
255       DottedNameToNetwork(
256           "123456789.123456789.123456789.123456789.123456789.123456789."
257           "123456789.123456789.123456789.123456789.123456789.123456789."
258           "123456789.123456789.123456789.123456789.123456789.123456789."
259           "123456789.123456789.123456789.123456789.123456789.123456789."
260           "123456789.12345.",
261           /*require_valid_internet_hostname=*/true)
262           .has_value());
263 }
264 
TEST(DnsNamesUtilTest,DottedNameToNetworkRejectsTooLongNames)265 TEST(DnsNamesUtilTest, DottedNameToNetworkRejectsTooLongNames) {
266   // Label is too long: invalid
267   EXPECT_FALSE(
268       DottedNameToNetwork(
269           "123456789a123456789a123456789a123456789a123456789a123456789a1234",
270           /*require_valid_internet_hostname=*/false)
271           .has_value());
272   EXPECT_FALSE(
273       DottedNameToNetwork(
274           "123456789a123456789a123456789a123456789a123456789a123456789a1234.",
275           /*require_valid_internet_hostname=*/false)
276           .has_value());
277 
278   // 254 characters in the name: invalid
279   EXPECT_FALSE(
280       DottedNameToNetwork(
281           "123456789.123456789.123456789.123456789.123456789.123456789."
282           "123456789.123456789.123456789.123456789.123456789.123456789."
283           "123456789.123456789.123456789.123456789.123456789.123456789."
284           "123456789.123456789.123456789.123456789.123456789.123456789."
285           "123456789.1234",
286           /*require_valid_internet_hostname=*/false)
287           .has_value());
288   EXPECT_FALSE(
289       DottedNameToNetwork(
290           "123456789.123456789.123456789.123456789.123456789.123456789."
291           "123456789.123456789.123456789.123456789.123456789.123456789."
292           "123456789.123456789.123456789.123456789.123456789.123456789."
293           "123456789.123456789.123456789.123456789.123456789.123456789."
294           "123456789.1234.",
295           /*require_valid_internet_hostname=*/false)
296           .has_value());
297 
298   // 255 characters in the name: invalid before even trying to add a final
299   // zero-length termination
300   EXPECT_FALSE(
301       DottedNameToNetwork(
302           "123456789.123456789.123456789.123456789.123456789.123456789."
303           "123456789.123456789.123456789.123456789.123456789.123456789."
304           "123456789.123456789.123456789.123456789.123456789.123456789."
305           "123456789.123456789.123456789.123456789.123456789.123456789."
306           "123456789.12345",
307           /*require_valid_internet_hostname=*/false)
308           .has_value());
309   EXPECT_FALSE(
310       DottedNameToNetwork(
311           "123456789.123456789.123456789.123456789.123456789.123456789."
312           "123456789.123456789.123456789.123456789.123456789.123456789."
313           "123456789.123456789.123456789.123456789.123456789.123456789."
314           "123456789.123456789.123456789.123456789.123456789.123456789."
315           "123456789.12345.",
316           /*require_valid_internet_hostname=*/false)
317           .has_value());
318 }
319 
TEST(DnsNamesUtilTest,DottedNameToNetworkWithValidationRejectsRestrictedCharacters)320 TEST(DnsNamesUtilTest,
321      DottedNameToNetworkWithValidationRejectsRestrictedCharacters) {
322   EXPECT_FALSE(DottedNameToNetwork("foo,bar.com",
323                                    /*require_valid_internet_hostname=*/true)
324                    .has_value());
325   EXPECT_FALSE(DottedNameToNetwork("_ipp._tcp.local.foo printer (bar)",
326                                    /*require_valid_internet_hostname=*/true)
327                    .has_value());
328 }
329 
TEST(DnsNamesUtilTest,DottedNameToNetworkAcceptsRestrictedCharacters)330 TEST(DnsNamesUtilTest, DottedNameToNetworkAcceptsRestrictedCharacters) {
331   EXPECT_THAT(DottedNameToNetwork("foo,bar.com",
332                                   /*require_valid_internet_hostname=*/false),
333               Optional(ToBytes("\007foo,bar\003com")));
334 
335   EXPECT_THAT(
336       DottedNameToNetwork("_ipp._tcp.local.foo printer (bar)",
337                           /*require_valid_internet_hostname=*/false),
338       Optional(ToBytes("\004_ipp\004_tcp\005local\021foo printer (bar)")));
339 }
340 
TEST(DnsNamesUtilTest,NetworkToDottedNameAdvancesReader)341 TEST(DnsNamesUtilTest, NetworkToDottedNameAdvancesReader) {
342   {
343     auto reader = base::SpanReader(base::byte_span_from_cstring("\003com"));
344     EXPECT_THAT(NetworkToDottedName(reader), Optional(Eq("com")));
345     EXPECT_EQ(reader.remaining(), 0u);
346   }
347   {
348     auto reader =
349         base::SpanReader(base::byte_span_from_cstring("\003com\0ZZZ"));
350     EXPECT_THAT(NetworkToDottedName(reader), Optional(Eq("com")));
351     EXPECT_EQ(reader.remaining(), 3u);
352   }
353 }
354 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleSimpleNames)355 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleSimpleNames) {
356   std::string dns_name = "\003foo";
357   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
358               Optional(Eq("foo")));
359 
360   dns_name += "\003bar";
361   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
362               Optional(Eq("foo.bar")));
363 
364   dns_name += "\002uk";
365   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
366               Optional(Eq("foo.bar.uk")));
367 
368   dns_name += '\0';
369   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
370               Optional(Eq("foo.bar.uk")));
371 }
372 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleEmpty)373 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleEmpty) {
374   std::string dns_name;
375 
376   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
377               Optional(Eq("")));
378 
379   dns_name += '\0';
380   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
381               Optional(Eq("")));
382 }
383 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectEmptyIncomplete)384 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectEmptyIncomplete) {
385   std::string dns_name;
386 
387   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name),
388                                   false /* require_complete */),
389               Optional(Eq("")));
390 
391   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name),
392                                 true /* require_complete */),
393             std::nullopt);
394 }
395 
396 // Test `require_complete` functionality given an input with terminating zero-
397 // length label.
TEST(DnsNamesUtilTest,NetworkToDottedNameComplete)398 TEST(DnsNamesUtilTest, NetworkToDottedNameComplete) {
399   std::string dns_name("\003foo\004test");
400   dns_name += '\0';
401 
402   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name),
403                                   false /* require_complete */),
404               Optional(Eq("foo.test")));
405 
406   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name),
407                                   true /* require_complete */),
408               Optional(Eq("foo.test")));
409 }
410 
411 // Test `require_complete` functionality given an input without terminating
412 // zero-length label.
TEST(DnsNamesUtilTest,NetworkToDottedNameNotComplete)413 TEST(DnsNamesUtilTest, NetworkToDottedNameNotComplete) {
414   std::string dns_name("\003boo\004test");
415 
416   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name),
417                                   false /* require_complete */),
418               Optional(Eq("boo.test")));
419 
420   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name),
421                                 true /* require_complete */),
422             std::nullopt);
423 }
424 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectEmptyWhenRequiringComplete)425 TEST(DnsNamesUtilTest,
426      NetworkToDottedNameShouldRejectEmptyWhenRequiringComplete) {
427   std::string dns_name;
428 
429   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name),
430                                   false /* require_complete */),
431               Optional(Eq("")));
432 
433   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name),
434                                 true /* require_complete */),
435             std::nullopt);
436 
437   dns_name += '\0';
438   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name),
439                                   true /* require_complete */),
440               Optional(Eq("")));
441 }
442 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectCompression)443 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectCompression) {
444   std::string dns_name = CreateNamePointer(152);
445 
446   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
447 
448   dns_name = "\005hello";
449   dns_name += CreateNamePointer(152);
450 
451   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
452 }
453 
454 // Test that extra input past the terminating zero-length label are ignored.
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleExcessInput)455 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleExcessInput) {
456   std::string dns_name("\004cool\004name\004test");
457   dns_name += '\0';
458   dns_name += "blargh!";
459 
460   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
461               Optional(Eq("cool.name.test")));
462 
463   dns_name = "\002hi";
464   dns_name += '\0';
465   dns_name += "goodbye";
466 
467   EXPECT_THAT(NetworkToDottedName(base::as_byte_span(dns_name)),
468               Optional(Eq("hi")));
469 }
470 
471 // Test that input is malformed if it ends mid label.
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTruncatedNames)472 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTruncatedNames) {
473   std::string dns_name = "\07cheese";
474   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
475 
476   dns_name = "\006cheesy\05test";
477   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
478 }
479 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongSingleLabel)480 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongSingleLabel) {
481   std::string dns_name(1, static_cast<char>(dns_protocol::kMaxLabelLength));
482   for (int i = 0; i < dns_protocol::kMaxLabelLength; ++i) {
483     dns_name += 'a';
484   }
485 
486   EXPECT_NE(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
487 }
488 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongSecondLabel)489 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongSecondLabel) {
490   std::string dns_name("\003foo");
491   dns_name += static_cast<char>(dns_protocol::kMaxLabelLength);
492   for (int i = 0; i < dns_protocol::kMaxLabelLength; ++i) {
493     dns_name += 'a';
494   }
495 
496   EXPECT_NE(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
497 }
498 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongSingleLabel)499 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongSingleLabel) {
500   std::string dns_name(1, static_cast<char>(dns_protocol::kMaxLabelLength));
501   for (int i = 0; i < dns_protocol::kMaxLabelLength + 1; ++i) {
502     dns_name += 'a';
503   }
504 
505   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
506 }
507 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongSecondLabel)508 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongSecondLabel) {
509   std::string dns_name("\003foo");
510   dns_name += static_cast<char>(dns_protocol::kMaxLabelLength);
511   for (int i = 0; i < dns_protocol::kMaxLabelLength + 1; ++i) {
512     dns_name += 'a';
513   }
514 
515   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
516 }
517 
518 #if CHAR_MIN < 0
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectCharMinLabels)519 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectCharMinLabels) {
520   ASSERT_GT(static_cast<uint8_t>(CHAR_MIN), dns_protocol::kMaxLabelLength);
521 
522   std::string dns_name;
523   dns_name += base::checked_cast<char>(CHAR_MIN);
524 
525   // Wherever possible, make the name otherwise valid.
526   if (static_cast<uint8_t>(CHAR_MIN) < UINT8_MAX) {
527     for (uint8_t i = 0; i < static_cast<uint8_t>(CHAR_MIN); ++i) {
528       dns_name += 'a';
529     }
530   }
531 
532   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
533 }
534 #endif  // if CHAR_MIN < 0
535 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongName)536 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongName) {
537   std::string dns_name;
538   for (int i = 0; i < dns_protocol::kMaxNameLength;
539        i += (dns_protocol::kMaxLabelLength + 1)) {
540     int label_size = std::min(dns_protocol::kMaxNameLength - 1 - i,
541                               dns_protocol::kMaxLabelLength);
542     dns_name += static_cast<char>(label_size);
543     for (int j = 0; j < label_size; ++j) {
544       dns_name += 'a';
545     }
546   }
547   ASSERT_EQ(dns_name.size(), static_cast<size_t>(dns_protocol::kMaxNameLength));
548 
549   EXPECT_NE(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
550 }
551 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongName)552 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongName) {
553   std::string dns_name;
554   for (int i = 0; i < dns_protocol::kMaxNameLength + 1;
555        i += (dns_protocol::kMaxLabelLength + 1)) {
556     int label_size = std::min(dns_protocol::kMaxNameLength - i,
557                               dns_protocol::kMaxLabelLength);
558     dns_name += static_cast<char>(label_size);
559     for (int j = 0; j < label_size; ++j) {
560       dns_name += 'a';
561     }
562   }
563   ASSERT_EQ(dns_name.size(),
564             static_cast<size_t>(dns_protocol::kMaxNameLength + 1));
565 
566   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
567 }
568 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldHandleLongCompleteName)569 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldHandleLongCompleteName) {
570   std::string dns_name;
571   for (int i = 0; i < dns_protocol::kMaxNameLength;
572        i += (dns_protocol::kMaxLabelLength + 1)) {
573     int label_size = std::min(dns_protocol::kMaxNameLength - 1 - i,
574                               dns_protocol::kMaxLabelLength);
575     dns_name += static_cast<char>(label_size);
576     for (int j = 0; j < label_size; ++j) {
577       dns_name += 'a';
578     }
579   }
580   dns_name += '\0';
581   ASSERT_EQ(dns_name.size(),
582             static_cast<size_t>(dns_protocol::kMaxNameLength + 1));
583 
584   EXPECT_NE(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
585 }
586 
TEST(DnsNamesUtilTest,NetworkToDottedNameShouldRejectTooLongCompleteName)587 TEST(DnsNamesUtilTest, NetworkToDottedNameShouldRejectTooLongCompleteName) {
588   std::string dns_name;
589   for (int i = 0; i < dns_protocol::kMaxNameLength + 1;
590        i += (dns_protocol::kMaxLabelLength + 1)) {
591     int label_size = std::min(dns_protocol::kMaxNameLength - i,
592                               dns_protocol::kMaxLabelLength);
593     dns_name += static_cast<char>(label_size);
594     for (int j = 0; j < label_size; ++j) {
595       dns_name += 'a';
596     }
597   }
598   dns_name += '\0';
599   ASSERT_EQ(dns_name.size(),
600             static_cast<size_t>(dns_protocol::kMaxNameLength + 2));
601 
602   EXPECT_EQ(NetworkToDottedName(base::as_byte_span(dns_name)), std::nullopt);
603 }
604 
TEST(DnsNamesUtilTest,ValidDnsNames)605 TEST(DnsNamesUtilTest, ValidDnsNames) {
606   constexpr std::string_view kGoodHostnames[] = {
607       "www.noodles.blorg",   "1www.noodles.blorg",    "www.2noodles.blorg",
608       "www.n--oodles.blorg", "www.noodl_es.blorg",    "www.no-_odles.blorg",
609       "www_.noodles.blorg",  "www.noodles.blorg.",    "_privet._tcp.local",
610       "%20%20noodles.blorg", "noo dles.blorg ",       "noo dles_ipp._tcp.local",
611       "www.nood(les).blorg", "noo dl(es)._tcp.local",
612   };
613 
614   for (std::string_view good_hostname : kGoodHostnames) {
615     EXPECT_TRUE(IsValidDnsName(good_hostname));
616     EXPECT_TRUE(IsValidDnsRecordName(good_hostname));
617   }
618 }
619 
TEST(DnsNamesUtilTest,EmptyNotValidDnsName)620 TEST(DnsNamesUtilTest, EmptyNotValidDnsName) {
621   EXPECT_FALSE(IsValidDnsName(""));
622   EXPECT_FALSE(IsValidDnsRecordName(""));
623 }
624 
TEST(DnsNamesUtilTest,EmptyLabelNotValidDnsName)625 TEST(DnsNamesUtilTest, EmptyLabelNotValidDnsName) {
626   EXPECT_FALSE(IsValidDnsName("www..test"));
627   EXPECT_FALSE(IsValidDnsName(".foo.test"));
628 
629   EXPECT_FALSE(IsValidDnsRecordName("www..test"));
630   EXPECT_FALSE(IsValidDnsRecordName(".foo.test"));
631 }
632 
TEST(DnsNameUtilTest,LongLabelsInValidDnsNames)633 TEST(DnsNameUtilTest, LongLabelsInValidDnsNames) {
634   EXPECT_TRUE(IsValidDnsName(
635       "z23456789a123456789a123456789a123456789a123456789a123456789a123"));
636   EXPECT_TRUE(IsValidDnsName(
637       "z23456789a123456789a123456789a123456789a123456789a123456789a123."));
638 
639   EXPECT_TRUE(IsValidDnsRecordName(
640       "z23456789a123456789a123456789a123456789a123456789a123456789a123"));
641   EXPECT_TRUE(IsValidDnsRecordName(
642       "z23456789a123456789a123456789a123456789a123456789a123456789a123."));
643 }
644 
TEST(DnsNameUtilTest,TooLongLabelsInInvalidDnsNames)645 TEST(DnsNameUtilTest, TooLongLabelsInInvalidDnsNames) {
646   EXPECT_FALSE(IsValidDnsName(
647       "123456789a123456789a123456789a123456789a123456789a123456789a1234"));
648   EXPECT_FALSE(IsValidDnsName(
649       "z23456789a123456789a123456789a123456789a123456789a123456789a1234."));
650 
651   EXPECT_FALSE(IsValidDnsRecordName(
652       "z23456789a123456789a123456789a123456789a123456789a123456789a1234"));
653   EXPECT_FALSE(IsValidDnsRecordName(
654       "z23456789a123456789a123456789a123456789a123456789a123456789a1234."));
655 }
656 
TEST(DnsNameUtilTest,LongValidDnsNames)657 TEST(DnsNameUtilTest, LongValidDnsNames) {
658   EXPECT_TRUE(IsValidDnsName(
659       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
660       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
661       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
662       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
663       "abcdefghi.abc"));
664   EXPECT_TRUE(IsValidDnsName(
665       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
666       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
667       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
668       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
669       "abcdefghi.abc."));
670 
671   EXPECT_TRUE(IsValidDnsRecordName(
672       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
673       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
674       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
675       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
676       "abcdefghi.abc"));
677   EXPECT_TRUE(IsValidDnsRecordName(
678       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
679       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
680       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
681       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
682       "abcdefghi.abc."));
683 }
684 
TEST(DnsNameUtilTest,TooLongInalidDnsNames)685 TEST(DnsNameUtilTest, TooLongInalidDnsNames) {
686   EXPECT_FALSE(IsValidDnsName(
687       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
688       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
689       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
690       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
691       "abcdefghi.abcd"));
692   EXPECT_FALSE(IsValidDnsName(
693       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
694       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
695       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
696       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
697       "abcdefghi.abcd."));
698 
699   EXPECT_FALSE(IsValidDnsRecordName(
700       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
701       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
702       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
703       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
704       "abcdefghi.abcd"));
705   EXPECT_FALSE(IsValidDnsRecordName(
706       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
707       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
708       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
709       "abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi.abcdefghi."
710       "abcdefghi.abcd."));
711 }
712 
TEST(DnsNameUtilTest,LocalhostNotValidDnsRecordName)713 TEST(DnsNameUtilTest, LocalhostNotValidDnsRecordName) {
714   EXPECT_TRUE(IsValidDnsName("localhost"));
715   EXPECT_FALSE(IsValidDnsRecordName("localhost"));
716 }
717 
TEST(DnsNameUtilTest,IpAddressNotValidDnsRecordName)718 TEST(DnsNameUtilTest, IpAddressNotValidDnsRecordName) {
719   EXPECT_TRUE(IsValidDnsName("1.2.3.4"));
720   EXPECT_FALSE(IsValidDnsRecordName("1.2.3.4"));
721 
722   EXPECT_TRUE(IsValidDnsName("[2001:4860:4860::8888]"));
723   EXPECT_FALSE(IsValidDnsRecordName("[2001:4860:4860::8888]"));
724 
725   EXPECT_TRUE(IsValidDnsName("2001:4860:4860::8888"));
726   EXPECT_FALSE(IsValidDnsRecordName("2001:4860:4860::8888"));
727 }
728 
TEST(DnsUtilTest,CanonicalizeNames)729 TEST(DnsUtilTest, CanonicalizeNames) {
730   EXPECT_EQ(UrlCanonicalizeNameIfAble("GOOGLE.test"), "google.test");
731 
732   EXPECT_EQ(UrlCanonicalizeNameIfAble("g{oo}gle.test"), "g{oo}gle.test");
733   EXPECT_EQ(UrlCanonicalizeNameIfAble("G{OO}GLE.test"), "g{oo}gle.test");
734 
735   // g�gle.test
736   EXPECT_EQ(UrlCanonicalizeNameIfAble("g\u00FCgle.test"), "xn--ggle-0ra.test");
737   EXPECT_EQ(UrlCanonicalizeNameIfAble("G\u00fcGLE.test"), "xn--ggle-0ra.test");
738 }
739 
TEST(DnsUtilTest,IgnoreUncanonicalizeableNames)740 TEST(DnsUtilTest, IgnoreUncanonicalizeableNames) {
741   EXPECT_EQ(UrlCanonicalizeNameIfAble(""), "");
742 
743   // Forbidden domain code point.
744   // https://url.spec.whatwg.org/#forbidden-domain-code-point
745   EXPECT_EQ(UrlCanonicalizeNameIfAble("g<oo>gle.test"), "g<oo>gle.test");
746   EXPECT_EQ(UrlCanonicalizeNameIfAble("G<OO>GLE.test"), "G<OO>GLE.test");
747 
748   // Invalid UTF8 character.
749   EXPECT_EQ(UrlCanonicalizeNameIfAble("g\x00FCgle.test"), "g\x00fcgle.test");
750   EXPECT_EQ(UrlCanonicalizeNameIfAble("G\x00fcGLE.test"), "G\x00fcGLE.test");
751 
752   // Disallowed ASCII character.
753   EXPECT_EQ(UrlCanonicalizeNameIfAble("google\n.test"), "google\n.test");
754   EXPECT_EQ(UrlCanonicalizeNameIfAble("GOOGLE\n.test"), "GOOGLE\n.test");
755 }
756 
TEST(DnsNamesUtilTest,ReadU8LengthPrefixed)757 TEST(DnsNamesUtilTest, ReadU8LengthPrefixed) {
758   const uint8_t kArray[] = {'b', '4', 3, 'a', 'b', 'c', 'd'};
759   auto reader = base::SpanReader(base::span(kArray));
760   EXPECT_TRUE(reader.Skip(2u));
761   EXPECT_EQ(reader.remaining(), 5u);
762   EXPECT_EQ(reader.num_read(), 2u);
763   base::span<const uint8_t> s;
764   EXPECT_TRUE(ReadU8LengthPrefixed(reader, &s));
765   EXPECT_EQ(s, base::span(kArray).subspan(3u, 3u));
766   EXPECT_EQ(reader.remaining(), 1u);
767   EXPECT_EQ(reader.num_read(), 6u);
768 }
769 
TEST(DnsNamesUtilTest,ReadU16LengthPrefixed)770 TEST(DnsNamesUtilTest, ReadU16LengthPrefixed) {
771   const uint8_t kArray[] = {'b', '4', 0, 3, 'a', 'b', 'c', 'd'};
772   auto reader = base::SpanReader(base::span(kArray));
773   EXPECT_TRUE(reader.Skip(2u));
774   EXPECT_EQ(reader.remaining(), 6u);
775   EXPECT_EQ(reader.num_read(), 2u);
776   base::span<const uint8_t> s;
777   EXPECT_TRUE(ReadU16LengthPrefixed(reader, &s));
778   EXPECT_EQ(s, base::span(kArray).subspan(4u, 3u));
779   EXPECT_EQ(reader.remaining(), 1u);
780   EXPECT_EQ(reader.num_read(), 7u);
781 }
782 
783 }  // namespace
784 }  // namespace net::dns_names_util
785