diff --git a/SOURCES/glibc-armhfp-ELF_MACHINE_NO_REL-undefined.patch b/SOURCES/glibc-armhfp-ELF_MACHINE_NO_REL-undefined.patch new file mode 100644 index 00000000..78d7c4be --- /dev/null +++ b/SOURCES/glibc-armhfp-ELF_MACHINE_NO_REL-undefined.patch @@ -0,0 +1,36 @@ +From patchwork Thu Jul 3 13:26:40 2014 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: ARM: Define ELF_MACHINE_NO_REL +X-Patchwork-Submitter: Will Newton +X-Patchwork-Id: 366862 +Message-Id: <1404394000-13429-1-git-send-email-will.newton@linaro.org> +To: libc-alpha@sourceware.org +Date: Thu, 3 Jul 2014 14:26:40 +0100 +From: Will Newton +List-Id: + +Fix a -Wundef warning on ARM. + +ChangeLog: + +2014-07-03 Will Newton + + * sysdeps/arm/dl-machine.h (ELF_MACHINE_NO_REL): Define. +--- + sysdeps/arm/dl-machine.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h +index c5ffc93..d6b0c52 100644 +--- a/sysdeps/arm/dl-machine.h ++++ b/sysdeps/arm/dl-machine.h +@@ -296,6 +296,7 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc, + /* ARM never uses Elf32_Rela relocations for the dynamic linker. + Prelinked libraries may use Elf32_Rela though. */ + #define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP ++#define ELF_MACHINE_NO_REL 0 + + /* Names of the architecture-specific auditing callback functions. */ + #define ARCH_LA_PLTENTER arm_gnu_pltenter diff --git a/SOURCES/glibc-rh1039304-1.patch b/SOURCES/glibc-rh1039304-1.patch new file mode 100644 index 00000000..f2bbe6ef --- /dev/null +++ b/SOURCES/glibc-rh1039304-1.patch @@ -0,0 +1,185 @@ +commit 5c1a69238fcb87ff7f916a5ce7960b2864afb3a1 +Author: Florian Weimer +Date: Sat Nov 11 11:23:40 2017 +0100 + + resolv: Add tst-res_hnok + +diff --git a/resolv/Makefile b/resolv/Makefile +index 988871086a70b291..b1fd2e2db8736f9b 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -50,6 +50,7 @@ tests += \ + tst-ns_name \ + tst-ns_name_compress \ + tst-res_hconf_reorder \ ++ tst-res_hnok \ + tst-res_use_inet6 \ + tst-resolv-basic \ + tst-resolv-edns \ +@@ -182,6 +183,7 @@ $(objpfx)tst-resolv-canonname: \ + $(objpfx)tst-ns_name: $(objpfx)libresolv.so + $(objpfx)tst-ns_name.out: tst-ns_name.data + $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so ++$(objpfx)tst-res_hnok: $(objpfx)libresolv.so + + + # This test case uses the deprecated RES_USE_INET6 resolver option. +diff --git a/resolv/tst-res_hnok.c b/resolv/tst-res_hnok.c +new file mode 100644 +index 0000000000000000..9c923038218e965c +--- /dev/null ++++ b/resolv/tst-res_hnok.c +@@ -0,0 +1,153 @@ ++/* Tests for res_hnok and related functions. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Bits which indicate which functions are supposed to report ++ success. */ ++enum ++ { ++ hnok = 1, ++ dnok = 2, ++ mailok = 4, ++ ownok = 8, ++ allnomailok = hnok | dnok | ownok, ++ allok = hnok | dnok | mailok | ownok ++ }; ++ ++/* A string of 60 characters. */ ++#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" ++ ++/* A string of 63 characters (maximum label length). */ ++#define STRING63 STRING60 "zzz" ++ ++/* Combines a test name with the expected results. */ ++struct test_case ++{ ++ const char *dn; ++ unsigned int result; /* Combination of the *ok flags. */ ++}; ++ ++static const struct test_case tests[] = ++ { ++ { "", allok }, ++ { ".", allok }, ++ { "www", allnomailok }, ++ { "example", allnomailok }, ++ { "example.com", allok }, ++ { "www.example.com", allok }, ++ { "www.example.com.", allok }, ++ { "*.example.com", dnok | mailok | ownok }, ++ { "-v", dnok }, ++ { "-v.example.com", mailok | dnok }, ++ { "**.example.com", dnok | mailok }, ++ { STRING63, allnomailok }, ++ { STRING63 ".example.com", allok }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok }, ++ { "hostmaster@mail.example.com", dnok | mailok }, ++ { "with whitespace", 0 }, ++ { "with\twhitespace", 0 }, ++ { "with\nwhitespace", 0 }, ++ { "with.whitespace ", 0 }, ++ { "with.whitespace\t", 0 }, ++ { "with.whitespace\n", 0 }, ++ { "with\\ whitespace", 0 }, ++ { "with\\\twhitespace", 0 }, ++ { "with\\\nwhitespace", 0 }, ++ { "with.whitespace\\ ", 0 }, ++ { "with.whitespace\\\t", 0 }, ++ { "with.whitespace\\\n", 0 }, ++ }; ++ ++/* Run test case *TEST with FUNC (named FUNCNAME) and report an error ++ if the result does not match the result flag at BIT. */ ++static void ++one_test (const struct test_case *test, const char *funcname, ++ int (*func) (const char *), unsigned int bit) ++{ ++ int expected = (test->result & bit) != 0; ++ int actual = func (test->dn); ++ if (actual != expected) ++ { ++ support_record_failure (); ++ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", ++ funcname, test->dn, expected, actual); ++ } ++} ++ ++/* Run 255 tests using all the bytes from 1 to 255, surround the byte ++ with the strings PREFIX and SUFFIX, and check that FUNC (named ++ FUNCNAME) accepts only those bytes listed in ACCEPTED. */ ++static void ++one_char (const char *prefix, const char *accepted, const char *suffix, ++ const char *funcname, int (*func) (const char *)) ++{ ++ for (int ch = 1; ch <= 255; ++ch) ++ { ++ char dn[1024]; ++ snprintf (dn, sizeof (dn), "%s%c%s", prefix, ch, suffix); ++ int expected = strchr (accepted, ch) != NULL; ++ int actual = func (dn); ++ if (actual != expected) ++ { ++ support_record_failure (); ++ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", ++ funcname, dn, expected, actual); ++ } ++ } ++} ++ ++static int ++do_test (void) ++{ ++ for (const struct test_case *test = tests; test < array_end (tests); ++test) ++ { ++ if (test_verbose) ++ printf ("info: testing domain name [[[%s]]] (0x%x)\n", ++ test->dn, test->result); ++ one_test (test, "res_hnok", res_hnok, hnok); ++ one_test (test, "res_dnok", res_dnok, dnok); ++ one_test (test, "res_mailok", res_mailok, mailok); ++ one_test (test, "res_ownok", res_ownok, ownok); ++ } ++ ++ one_char ++ ("", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.", ++ "", "res_hnok", res_hnok); ++ one_char ++ ("middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ "suffix", "res_hnok", res_hnok); ++ one_char ++ ("middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_" ++ "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~", ++ "suffix.example", "res_mailok", res_mailok); ++ one_char ++ ("mailbox.middle", ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-_", ++ "suffix.example", "res_mailok", res_mailok); ++ ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-rh1039304-2.patch b/SOURCES/glibc-rh1039304-2.patch new file mode 100644 index 00000000..7bea4a37 --- /dev/null +++ b/SOURCES/glibc-rh1039304-2.patch @@ -0,0 +1,235 @@ +commit e2a9fca8101443076235a8dbcfceaa2d96bf4801 +Author: Florian Weimer +Date: Sat Nov 11 11:33:32 2017 +0100 + + resolv: Add tst-ns_name_pton + +diff --git a/resolv/Makefile b/resolv/Makefile +index b1fd2e2db8736f9b..0130a09db2d69451 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -49,6 +49,7 @@ tests += \ + tst-bug18665-tcp \ + tst-ns_name \ + tst-ns_name_compress \ ++ tst-ns_name_pton \ + tst-res_hconf_reorder \ + tst-res_hnok \ + tst-res_use_inet6 \ +@@ -183,6 +184,7 @@ $(objpfx)tst-resolv-canonname: \ + $(objpfx)tst-ns_name: $(objpfx)libresolv.so + $(objpfx)tst-ns_name.out: tst-ns_name.data + $(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so ++$(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so + $(objpfx)tst-res_hnok: $(objpfx)libresolv.so + + +diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c +new file mode 100644 +index 0000000000000000..879d97c9d3816210 +--- /dev/null ++++ b/resolv/tst-ns_name_pton.c +@@ -0,0 +1,203 @@ ++/* Tests for ns_name_pton. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Bits which indicate which functions are supposed to report ++ success. */ ++enum ++ { ++ hnok = 1, ++ dnok = 2, ++ mailok = 4, ++ ownok = 8, ++ allnomailok = hnok | dnok | ownok, ++ allok = hnok | dnok | mailok | ownok ++ }; ++ ++/* A string of 60 characters. */ ++#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" ++ ++/* A string of 63 characters (maximum label length). */ ++#define STRING63 STRING60 "zzz" ++ ++/* A string of 60 bytes (non-ASCII). */ ++#define STRING60OCT \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ ++ "\377\377\377\377\377\377\377\377\377" ++ ++/* A string of 63 bytes (non-ASCII). */ ++#define STRING63OCT STRING60OCT "\377\377\377" ++ ++/* A string of 60 bytes (non-ASCII, quoted decimal). */ ++#define STRING60DEC \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ ++ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" ++ ++/* A string of 63 bytes (non-ASCII, quoted decimal). */ ++#define STRING63DEC STRING60DEC "\\255\\255\\255" ++ ++/* Combines a test name with the expected results. */ ++struct test_case ++{ ++ const char *dn; ++ const char *back; /* Expected test result converted using ns_name_ntop. */ ++ bool fully_qualified; /* True if the domain name has a trailing dot. */ ++}; ++ ++static const struct test_case tests[] = ++ { ++ { "", ".", false }, ++ { ".", ".", true }, ++ { "..", NULL, }, ++ { "www", "www", false }, ++ { "www.", "www", true }, ++ { "www\\.", "www\\.", false }, ++ { ".www", NULL, }, ++ { ".www\\.", NULL, }, ++ { "example.com", "example.com", false }, ++ { "example.com.", "example.com", true }, ++ { ".example.com", NULL, }, ++ { ".example.com.", NULL, }, ++ { "example\\.com", "example\\.com", false }, ++ { "example\\.com.", "example\\.com", true }, ++ { "example..", NULL, }, ++ { "example..com", NULL, }, ++ { "example..com", NULL, }, ++ { "\\0", NULL, }, ++ { "\\00", NULL, }, ++ { "\\000", "\\000", false }, ++ { "\\1", NULL, }, ++ { "\\01", NULL, }, ++ { "\\001", "\\001", false }, ++ { "\\1x", NULL, }, ++ { "\\01x", NULL, }, ++ { "\\001x", "\\001x", false }, ++ { "\\256", NULL, }, ++ { "\\0641", "\\@1", false }, ++ { "\\0011", "\\0011", false }, ++ { STRING63, STRING63, false }, ++ { STRING63 ".", STRING63, true }, ++ { STRING63 "z", NULL, }, ++ { STRING63 "\\.", NULL, }, ++ { STRING60 "zz\\.", STRING60 "zz\\.", false }, ++ { STRING60 "zz\\..", STRING60 "zz\\.", true }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", ++ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", false }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", ++ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", true }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", NULL, }, ++ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", NULL, }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377", ++ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", ++ false }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377.", ++ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", ++ true }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT ++ "\377\377", NULL, }, ++ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT ++ "\377\377\377", NULL, }, ++ }; ++ ++static int ++do_test (void) ++{ ++ unsigned char *wire = xmalloc (NS_MAXCDNAME); ++ char *text = xmalloc (NS_MAXDNAME); ++ for (const struct test_case *test = tests; test < array_end (tests); ++test) ++ { ++ if (test_verbose) ++ printf ("info: testing domain name [[[%s]]]\n", test->dn); ++ int ret = ns_name_pton (test->dn, wire, NS_MAXCDNAME); ++ if (ret == -1) ++ { ++ if (test->back != NULL) ++ { ++ support_record_failure (); ++ printf ("error: unexpected decoding failure for [[%s]]\n", ++ test->dn); ++ } ++ /* Otherwise, we have an expected decoding failure. */ ++ continue; ++ } ++ ++ if (ret < -1 || ret > 1) ++ { ++ support_record_failure (); ++ printf ("error: invalid return value %d for [[%s]]\n", ++ ret, test->dn); ++ continue; ++ } ++ ++ int ret2 = ns_name_ntop (wire, text, NS_MAXDNAME); ++ ++ if (ret2 < 0) ++ { ++ support_record_failure (); ++ printf ("error: failure to convert back [[%s]]\n", test->dn); ++ } ++ ++ if (test->back == NULL) ++ { ++ support_record_failure (); ++ printf ("error: unexpected success converting [[%s]]\n", test->dn); ++ if (ret2 >= 1) ++ printf ("error: result converts back to [[%s]]\n", test->dn); ++ continue; ++ } ++ ++ if (strcmp (text, test->back) != 0) ++ { ++ support_record_failure (); ++ printf ("error: back-conversion of [[%s]] did not match\n", ++ test->dn); ++ printf ("error: expected: [[%s]]\n", test->back); ++ printf ("error: actual: [[%s]]\n", text); ++ } ++ ++ if (ret != test->fully_qualified) ++ { ++ support_record_failure (); ++ printf ("error: invalid fully-qualified status for [[%s]]\n", ++ test->dn); ++ printf ("error: expected: %d\n", (int) test->fully_qualified); ++ printf ("error: actual: %d\n", ret); ++ } ++ } ++ ++ free (text); ++ free (wire); ++ return 0; ++} ++ ++#include diff --git a/SOURCES/glibc-rh1039304-3.patch b/SOURCES/glibc-rh1039304-3.patch new file mode 100644 index 00000000..d39d4d21 --- /dev/null +++ b/SOURCES/glibc-rh1039304-3.patch @@ -0,0 +1,40 @@ +commit 9e0ad3049dbae88d615bfb038e53bf365a39a634 +Author: Florian Weimer +Date: Sat Nov 11 11:41:45 2017 +0100 + + resolv: ns_name_pton should report trailing \ as error [BZ #22413] + +diff --git a/resolv/ns_name.c b/resolv/ns_name.c +index 08a75e2fe0b4edd6..73213fee2dca530b 100644 +--- a/resolv/ns_name.c ++++ b/resolv/ns_name.c +@@ -222,6 +222,11 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) + } + *bp++ = (u_char)c; + } ++ if (escaped) { ++ /* Trailing backslash. */ ++ __set_errno (EMSGSIZE); ++ return -1; ++ } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + __set_errno (EMSGSIZE); +diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c +index 879d97c9d3816210..73bdb05e08e405dc 100644 +--- a/resolv/tst-ns_name_pton.c ++++ b/resolv/tst-ns_name_pton.c +@@ -127,6 +127,13 @@ static const struct test_case tests[] = + "\377\377", NULL, }, + { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT + "\377\377\377", NULL, }, ++ { "\\", NULL, }, ++ { "\\\\", "\\\\", false }, ++ { "\\\\.", "\\\\", true }, ++ { "\\\\\\", NULL, }, ++ { "a\\", NULL, }, ++ { "a.\\", NULL, }, ++ { "a.b\\", NULL, }, + }; + + static int diff --git a/SOURCES/glibc-rh1039304-4.patch b/SOURCES/glibc-rh1039304-4.patch new file mode 100644 index 00000000..e67eab1e --- /dev/null +++ b/SOURCES/glibc-rh1039304-4.patch @@ -0,0 +1,322 @@ +commit c0a25aa92b612786f4e45292c4aee1d7d47123f8 +Author: Florian Weimer +Date: Sat Nov 11 11:51:08 2017 +0100 + + resolv: More precise checks in res_hnok, res_dnok [BZ #22409] [BZ #22412] + + res_hnok rejected some host names used on the Internet, such as + www-.example.com. res_hnok and res_dnok failed to perform basic syntax + checking on DNS domain names. + + Also fix res_mailok, res_ownok. + +diff --git a/resolv/res_comp.c b/resolv/res_comp.c +index ffb2ed59147d3680..79760e891f607daa 100644 +--- a/resolv/res_comp.c ++++ b/resolv/res_comp.c +@@ -1,3 +1,21 @@ ++/* Domain name processing functions. ++ Copyright (C) 1995-2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ + /* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. +@@ -121,110 +139,118 @@ dn_skipname(const u_char *ptr, const u_char *eom) { + } + libresolv_hidden_def (dn_skipname) + +-/* +- * Verify that a domain name uses an acceptable character set. +- */ ++/* Return true if the string consists of printable ASCII characters ++ only. */ ++static bool ++printable_string (const char *dn) ++{ ++ while (true) ++ { ++ char ch = *dn; ++ if (ch == '\0') ++ return true; ++ if (ch <= ' ' || ch > '~') ++ return false; ++ ++dn; ++ } ++} + +-/* +- * Note the conspicuous absence of ctype macros in these definitions. On +- * non-ASCII hosts, we can't depend on string literals or ctype macros to +- * tell us anything about network-format data. The rest of the BIND system +- * is not careful about this, but for some reason, we're doing it right here. +- */ +-#define PERIOD 0x2e +-#define hyphenchar(c) ((c) == 0x2d) +-#define underscorechar(c) ((c) == 0x5f) +-#define bslashchar(c) ((c) == 0x5c) +-#define periodchar(c) ((c) == PERIOD) +-#define asterchar(c) ((c) == 0x2a) +-#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ +- || ((c) >= 0x61 && (c) <= 0x7a)) +-#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) +- +-#define borderchar(c) (alphachar(c) || digitchar(c)) +-#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) +-#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) ++/* Return true if DN points to a name consisting only of [0-9a-zA-Z_-] ++ characters. DN must be in DNS wire format, without ++ compression. */ ++static bool ++binary_hnok (const unsigned char *dn) ++{ ++ while (true) ++ { ++ size_t label_length = *dn; ++ if (label_length == 0) ++ break; ++ ++dn; ++ const unsigned char *label_end = dn + label_length; ++ do ++ { ++ unsigned char ch = *dn; ++ if (!(('0' <= ch && ch <= '9') ++ || ('A' <= ch && ch <= 'Z') ++ || ('a' <= ch && ch <= 'z') ++ || ch == '-' || ch == '_')) ++ return false; ++ ++dn; ++ } ++ while (dn < label_end); ++ } ++ return true; ++} ++ ++/* Return true if the binary domain name has a first labels which ++ starts with '-'. */ ++static inline bool ++binary_leading_dash (const unsigned char *dn) ++{ ++ return dn[0] > 0 && dn[1] == '-'; ++} + ++/* Return 1 if res_hnok is a valid host name. Labels must only ++ contain [0-9a-zA-Z_-] characters, and the name must not start with ++ a '-'. The latter is to avoid confusion with program options. */ + int +-res_hnok(const char *dn) { +- int pch = PERIOD, ch = *dn++; +- +- while (ch != '\0') { +- int nch = *dn++; +- +- if (periodchar(ch)) { +- (void)NULL; +- } else if (periodchar(pch)) { +- if (!borderchar(ch)) +- return (0); +- } else if (periodchar(nch) || nch == '\0') { +- if (!borderchar(ch)) +- return (0); +- } else { +- if (!middlechar(ch)) +- return (0); +- } +- pch = ch, ch = nch; +- } +- return (1); ++res_hnok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ if (!printable_string (dn) ++ || ns_name_pton (dn, buf, sizeof (buf)) < 0 ++ || binary_leading_dash (buf)) ++ return 0; ++ return binary_hnok (buf); + } + libresolv_hidden_def (res_hnok) + +-/* +- * hostname-like (A, MX, WKS) owners can have "*" as their first label +- * but must otherwise be as a host name. +- */ ++/* Hostname-like (A, MX, WKS) owners can have "*" as their first label ++ but must otherwise be as a host name. */ + int +-res_ownok(const char *dn) { +- if (asterchar(dn[0])) { +- if (periodchar(dn[1])) +- return (res_hnok(dn+2)); +- if (dn[1] == '\0') +- return (1); +- } +- return (res_hnok(dn)); ++res_ownok (const char *dn) ++{ ++ unsigned char buf[NS_MAXCDNAME]; ++ if (!printable_string (dn) ++ || ns_name_pton (dn, buf, sizeof (buf)) < 0 ++ || binary_leading_dash (buf)) ++ return 0; ++ if (buf[0] == 1 && buf [1] == '*') ++ /* Skip over the leading "*." part. */ ++ return binary_hnok (buf + 2); ++ else ++ return binary_hnok (buf); + } + +-/* +- * SOA RNAMEs and RP RNAMEs can have any printable character in their first +- * label, but the rest of the name has to look like a host name. +- */ ++/* SOA RNAMEs and RP RNAMEs can have any byte in their first label, ++ but the rest of the name has to look like a host name. */ + int +-res_mailok(const char *dn) { +- int ch, escaped = 0; +- +- /* "." is a valid missing representation */ +- if (*dn == '\0') +- return (1); +- +- /* otherwise