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.  */
27 enum
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.  */
44 struct test_case
45 {
46   const char *dn;
47   unsigned int result;          /* Combination of the *ok flags.  */
48 };
49 
50 static 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.  */
95 static void
one_test(const struct test_case * test,const char * funcname,int (* func)(const char *),unsigned int bit)96 one_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 ("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.  */
112 static void
one_char(const char * prefix,const char * accepted,const char * suffix,const char * funcname,int (* func)(const char *))113 one_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 (dn, sizeof (dn), "%s%c%s", prefix, ch, suffix);
120       int expected = strchr (accepted, ch) != NULL;
121       int actual = func (dn);
122       if (actual != expected)
123         {
124           support_record_failure ();
125           printf ("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 
137 static int
do_test(void)138 do_test (void)
139 {
140   for (const struct test_case *test = tests; test < array_end (tests); ++test)
141     {
142       if (test_verbose)
143         printf ("info: testing domain name [[[%s]]] (0x%x)\n",
144                 test->dn, test->result);
145       one_test (test, "res_hnok", res_hnok, hnok);
146       one_test (test, "res_dnok", res_dnok, dnok);
147       one_test (test, "res_mailok", res_mailok, mailok);
148       one_test (test, "res_ownok", res_ownok, ownok);
149     }
150 
151   one_char
152     ("", LETTERSDIGITS "._", "", "res_hnok", res_hnok);
153   one_char
154     ("middle",
155      LETTERSDIGITS ".-_\\", /* "middle\\suffix" == "middlesuffix", so good.  */
156      "suffix", "res_hnok", res_hnok);
157   one_char
158     ("middle",
159      LETTERSDIGITS ".-_" PRINTABLE,
160      "suffix.example", "res_mailok", res_mailok);
161   one_char
162     ("mailbox.middle",
163      LETTERSDIGITS ".-_\\",
164      "suffix.example", "res_mailok", res_mailok);
165 
166   return 0;
167 }
168 
169 #include <support/test-driver.c>
170