arrfab / rpms / glibc

Forked from rpms/glibc 4 years ago
Clone

Blame SOURCES/glibc-rh1673465-6.patch

147e83
commit 108bc4049f8ae82710aec26a92ffdb4b439c83fd
147e83
Author: Florian Weimer <fweimer@redhat.com>
147e83
Date:   Mon Jan 21 21:26:03 2019 +0100
147e83
147e83
    CVE-2016-10739: getaddrinfo: Fully parse IPv4 address strings [BZ #20018]
147e83
    
147e83
    The IPv4 address parser in the getaddrinfo function is changed so that
147e83
    it does not ignore trailing whitespace and all characters after it.
147e83
    For backwards compatibility, the getaddrinfo function still recognizes
147e83
    legacy name syntax, such as 192.000.002.010 interpreted as 192.0.2.8
147e83
    (octal).
147e83
    
147e83
    This commit does not change the behavior of inet_addr and inet_aton.
147e83
    gethostbyname already had additional sanity checks (but is switched
147e83
    over to the new __inet_aton_exact function for completeness as well).
147e83
    
147e83
    To avoid sending the problematic query names over DNS, commit
147e83
    6ca53a2453598804a2559a548a08424fca96434a ("resolv: Do not send queries
147e83
    for non-host-names in nss_dns [BZ #24112]") is needed.
147e83
147e83
diff --git a/include/arpa/inet.h b/include/arpa/inet.h
147e83
index c3f28f2baaa2ed66..19aec74275069a45 100644
147e83
--- a/include/arpa/inet.h
147e83
+++ b/include/arpa/inet.h
147e83
@@ -1,10 +1,10 @@
147e83
 #include <inet/arpa/inet.h>
147e83
 
147e83
 #ifndef _ISOMAC
147e83
-extern int __inet_aton (const char *__cp, struct in_addr *__inp);
147e83
-libc_hidden_proto (__inet_aton)
147e83
+/* Variant of inet_aton which rejects trailing garbage.  */
147e83
+extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp);
147e83
+libc_hidden_proto (__inet_aton_exact)
147e83
 
147e83
-libc_hidden_proto (inet_aton)
147e83
 libc_hidden_proto (inet_ntop)
147e83
 libc_hidden_proto (inet_pton)
147e83
 extern __typeof (inet_pton) __inet_pton;
147e83
diff --git a/nscd/gai.c b/nscd/gai.c
147e83
index 018b449339813df5..dbe878fcf699dbc1 100644
147e83
--- a/nscd/gai.c
147e83
+++ b/nscd/gai.c
147e83
@@ -20,7 +20,6 @@
147e83
 
147e83
 /* This file uses the getaddrinfo code but it compiles it without NSCD
147e83
    support.  We just need a few symbol renames.  */
147e83
-#define __inet_aton inet_aton
147e83
 #define __ioctl ioctl
147e83
 #define __getsockname getsockname
147e83
 #define __socket socket
147e83
diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c
147e83
index 2ab75e469eca1589..958a12d063f1e3e6 100644
147e83
--- a/nscd/gethstbynm3_r.c
147e83
+++ b/nscd/gethstbynm3_r.c
147e83
@@ -38,8 +38,6 @@
147e83
 #define HAVE_LOOKUP_BUFFER	1
147e83
 #define HAVE_AF			1
147e83
 
147e83
-#define __inet_aton inet_aton
147e83
-
147e83
 /* We are nscd, so we don't want to be talking to ourselves.  */
147e83
 #undef	USE_NSCD
147e83
 
147e83
diff --git a/nss/digits_dots.c b/nss/digits_dots.c
147e83
index 0c1fa97e3977a81e..5f7e5b5fb120c387 100644
147e83
--- a/nss/digits_dots.c
147e83
+++ b/nss/digits_dots.c
147e83
@@ -29,7 +29,6 @@
147e83
 #include "nsswitch.h"
147e83
 
147e83
 #ifdef USE_NSCD
147e83
-# define inet_aton __inet_aton
147e83
 # include <nscd/nscd_proto.h>
147e83
 #endif
147e83
 
147e83
@@ -160,7 +159,7 @@ __nss_hostname_digits_dots_context (struct resolv_context *ctx,
147e83
 		     255.255.255.255?  The test below will succeed
147e83
 		     spuriously... ???  */
147e83
 		  if (af == AF_INET)
147e83
-		    ok = __inet_aton (name, (struct in_addr *) host_addr);
147e83
+		    ok = __inet_aton_exact (name, (struct in_addr *) host_addr);
147e83
 		  else
147e83
 		    {
147e83
 		      assert (af == AF_INET6);
147e83
diff --git a/resolv/Makefile b/resolv/Makefile
147e83
index 1124897ce5f9610b..988871086a70b291 100644
147e83
--- a/resolv/Makefile
147e83
+++ b/resolv/Makefile
147e83
@@ -34,6 +34,9 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
147e83
 tests = tst-aton tst-leaks tst-inet_ntop
147e83
 xtests = tst-leaks2
147e83
 
147e83
+tests-internal += tst-inet_aton_exact
147e83
+
147e83
+
147e83
 generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace
147e83
 
147e83
 extra-libs := libresolv libnss_dns
147e83
@@ -51,8 +54,10 @@ tests += \
147e83
   tst-resolv-basic \
147e83
   tst-resolv-edns \
147e83
   tst-resolv-network \
147e83
+  tst-resolv-nondecimal \
147e83
   tst-resolv-res_init-multi \
147e83
   tst-resolv-search \
147e83
+  tst-resolv-trailing \
147e83
 
147e83
 # These tests need libdl.
147e83
 ifeq (yes,$(build-shared))
147e83
@@ -164,9 +169,11 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
147e83
   $(shared-thread-library)
147e83
 $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
147e83
   $(shared-thread-library)
147e83
+$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
147e83
 $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
147e83
 $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
147e83
 $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
147e83
+$(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library)
147e83
 $(objpfx)tst-resolv-threads: \
147e83
   $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
147e83
 $(objpfx)tst-resolv-canonname: \
147e83
diff --git a/resolv/Versions b/resolv/Versions
147e83
index b05778d9654aa0f2..9a82704af75f789b 100644
147e83
--- a/resolv/Versions
147e83
+++ b/resolv/Versions
147e83
@@ -27,6 +27,7 @@ libc {
147e83
     __h_errno; __resp;
147e83
 
147e83
     __res_iclose;
147e83
+    __inet_aton_exact;
147e83
     __inet_pton_length;
147e83
     __resolv_context_get;
147e83
     __resolv_context_get_preinit;
147e83
diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c
147e83
index 32f58b0e13598b32..41b6166a5bd5a44b 100644
147e83
--- a/resolv/inet_addr.c
147e83
+++ b/resolv/inet_addr.c
147e83
@@ -96,26 +96,14 @@
147e83
 #include <limits.h>
147e83
 #include <errno.h>
147e83
 
147e83
-/* ASCII IPv4 Internet address interpretation routine.  The value
147e83
-   returned is in network order.  */
147e83
-in_addr_t
147e83
-__inet_addr (const char *cp)
147e83
-{
147e83
-  struct in_addr val;
147e83
-
147e83
-  if (__inet_aton (cp, &val))
147e83
-    return val.s_addr;
147e83
-  return INADDR_NONE;
147e83
-}
147e83
-weak_alias (__inet_addr, inet_addr)
147e83
-
147e83
 /* Check whether "cp" is a valid ASCII representation of an IPv4
147e83
    Internet address and convert it to a binary address.  Returns 1 if
147e83
    the address is valid, 0 if not.  This replaces inet_addr, the
147e83
    return value from which cannot distinguish between failure and a
147e83
-   local broadcast address.  */
147e83
-int
147e83
-__inet_aton (const char *cp, struct in_addr *addr)
147e83
+   local broadcast address.  Write a pointer to the first
147e83
+   non-converted character to *endp.  */
147e83
+static int
147e83
+inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
147e83
 {
147e83
   static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
147e83
   in_addr_t val;
147e83
@@ -180,6 +168,7 @@ __inet_aton (const char *cp, struct in_addr *addr)
147e83
 
147e83
   if (addr != NULL)
147e83
     addr->s_addr = res.word | htonl (val);
147e83
+  *endp = cp;
147e83
 
147e83
   __set_errno (saved_errno);
147e83
   return 1;
147e83
@@ -188,6 +177,41 @@ __inet_aton (const char *cp, struct in_addr *addr)
147e83
   __set_errno (saved_errno);
147e83
   return 0;
147e83
 }
147e83
-weak_alias (__inet_aton, inet_aton)
147e83
-libc_hidden_def (__inet_aton)
147e83
-libc_hidden_weak (inet_aton)
147e83
+
147e83
+int
147e83
+__inet_aton_exact (const char *cp, struct in_addr *addr)
147e83
+{
147e83
+  struct in_addr val;
147e83
+  const char *endp;
147e83
+  /* Check that inet_aton_end parsed the entire string.  */
147e83
+  if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0)
147e83
+    {
147e83
+      *addr = val;
147e83
+      return 1;
147e83
+    }
147e83
+  else
147e83
+    return 0;
147e83
+}
147e83
+libc_hidden_def (__inet_aton_exact)
147e83
+
147e83
+/* inet_aton ignores trailing garbage.  */
147e83
+int
147e83
+__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr)
147e83
+{
147e83
+  const char *endp;
147e83
+  return  inet_aton_end (cp, addr, &endp);
147e83
+}
147e83
+weak_alias (__inet_aton_ignore_trailing, inet_aton)
147e83
+
147e83
+/* ASCII IPv4 Internet address interpretation routine.  The value
147e83
+   returned is in network order.  */
147e83
+in_addr_t
147e83
+__inet_addr (const char *cp)
147e83
+{
147e83
+  struct in_addr val;
147e83
+  const char *endp;
147e83
+  if (inet_aton_end (cp, &val, &endp))
147e83
+    return val.s_addr;
147e83
+  return INADDR_NONE;
147e83
+}
147e83
+weak_alias (__inet_addr, inet_addr)
147e83
diff --git a/resolv/res_init.c b/resolv/res_init.c
147e83
index c29bc4e9b99b6bee..9ea9c01d1029ba5f 100644
147e83
--- a/resolv/res_init.c
147e83
+++ b/resolv/res_init.c
147e83
@@ -399,8 +399,16 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
147e83
               cp = parser->buffer + sizeof ("nameserver") - 1;
147e83
               while (*cp == ' ' || *cp == '\t')
147e83
                 cp++;
147e83
+
147e83
+              /* Ignore trailing contents on the name server line.  */
147e83
+              {
147e83
+                char *el;
147e83
+                if ((el = strpbrk (cp, " \t\n")) != NULL)
147e83
+                  *el = '\0';
147e83
+              }
147e83
+
147e83
               struct sockaddr *sa;
147e83
-              if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a))
147e83
+              if ((*cp != '\0') && (*cp != '\n') && __inet_aton_exact (cp, &a))
147e83
                 {
147e83
                   sa = allocate_address_v4 (a, NAMESERVER_PORT);
147e83
                   if (sa == NULL)
147e83
@@ -410,9 +418,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
147e83
                 {
147e83
                   struct in6_addr a6;
147e83
                   char *el;
147e83
-
147e83
-                  if ((el = strpbrk (cp, " \t\n")) != NULL)
147e83
-                    *el = '\0';
147e83
                   if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL)
147e83
                     *el = '\0';
147e83
                   if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0))
147e83
@@ -472,7 +477,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
147e83
                   char separator = *cp;
147e83
                   *cp = 0;
147e83
                   struct resolv_sortlist_entry e;
147e83
-                  if (__inet_aton (net, &a))
147e83
+                  if (__inet_aton_exact (net, &a))
147e83
                     {
147e83
                       e.addr = a;
147e83
                       if (is_sort_mask (separator))
147e83
@@ -484,7 +489,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
147e83
                             cp++;
147e83
                           separator = *cp;
147e83
                           *cp = 0;
147e83
-                          if (__inet_aton (net, &a))
147e83
+                          if (__inet_aton_exact (net, &a))
147e83
                             e.mask = a.s_addr;
147e83
                           else
147e83
                             e.mask = net_mask (e.addr);
147e83
diff --git a/resolv/tst-aton.c b/resolv/tst-aton.c
147e83
index 08110a007af909ff..eb734d7758d6ed87 100644
147e83
--- a/resolv/tst-aton.c
147e83
+++ b/resolv/tst-aton.c
147e83
@@ -1,11 +1,29 @@
147e83
+/* Test legacy IPv4 text-to-address function inet_aton.
147e83
+   Copyright (C) 1998-2019 Free Software Foundation, Inc.
147e83
+   This file is part of the GNU C Library.
147e83
+
147e83
+   The GNU C Library is free software; you can redistribute it and/or
147e83
+   modify it under the terms of the GNU Lesser General Public
147e83
+   License as published by the Free Software Foundation; either
147e83
+   version 2.1 of the License, or (at your option) any later version.
147e83
+
147e83
+   The GNU C Library is distributed in the hope that it will be useful,
147e83
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
147e83
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147e83
+   Lesser General Public License for more details.
147e83
+
147e83
+   You should have received a copy of the GNU Lesser General Public
147e83
+   License along with the GNU C Library; if not, see
147e83
+   <http://www.gnu.org/licenses/>.  */
147e83
+
147e83
+#include <array_length.h>
147e83
 #include <stdio.h>
147e83
 #include <stdint.h>
147e83
 #include <sys/socket.h>
147e83
 #include <netinet/in.h>
147e83
 #include <arpa/inet.h>
147e83
 
147e83
-
147e83
-static struct tests
147e83
+static const struct tests
147e83
 {
147e83
   const char *input;
147e83
   int valid;
147e83
@@ -16,6 +34,7 @@ static struct tests
147e83
   { "-1", 0, 0 },
147e83
   { "256", 1, 0x00000100 },
147e83
   { "256.", 0, 0 },
147e83
+  { "255a", 0, 0 },
147e83
   { "256a", 0, 0 },
147e83
   { "0x100", 1, 0x00000100 },
147e83
   { "0200.0x123456", 1, 0x80123456 },
147e83
@@ -40,7 +59,12 @@ static struct tests
147e83
   { "1.2.256.4", 0, 0 },
147e83
   { "1.2.3.0x100", 0, 0 },
147e83
   { "323543357756889", 0, 0 },
147e83
-  { "10.1.2.3.4", 0, 0},
147e83
+  { "10.1.2.3.4", 0, 0 },
147e83
+  { "192.0.2.1", 1, 0xc0000201 },
147e83
+  { "192.0.2.2\nX", 1, 0xc0000202 },
147e83
+  { "192.0.2.3 Y", 1, 0xc0000203 },
147e83
+  { "192.0.2.3Z", 0, 0 },
147e83
+  { "192.000.002.010", 1, 0xc0000208 },
147e83
 };
147e83
 
147e83
 
147e83
@@ -50,7 +74,7 @@ do_test (void)
147e83
   int result = 0;
147e83
   size_t cnt;
147e83
 
147e83
-  for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt)
147e83
+  for (cnt = 0; cnt < array_length (tests); ++cnt)
147e83
     {
147e83
       struct in_addr addr;
147e83
 
147e83
@@ -73,5 +97,4 @@ do_test (void)
147e83
   return result;
147e83
 }
147e83
 
147e83
-#define TEST_FUNCTION do_test ()
147e83
-#include "../test-skeleton.c"
147e83
+#include <support/test-driver.c>
147e83
diff --git a/resolv/tst-inet_aton_exact.c b/resolv/tst-inet_aton_exact.c
147e83
new file mode 100644
147e83
index 0000000000000000..0fdfa3d6aa9aef91
147e83
--- /dev/null
147e83
+++ b/resolv/tst-inet_aton_exact.c
147e83
@@ -0,0 +1,47 @@
147e83
+/* Test internal legacy IPv4 text-to-address function __inet_aton_exact.
147e83
+   Copyright (C) 2019 Free Software Foundation, Inc.
147e83
+   This file is part of the GNU C Library.
147e83
+
147e83
+   The GNU C Library is free software; you can redistribute it and/or
147e83
+   modify it under the terms of the GNU Lesser General Public
147e83
+   License as published by the Free Software Foundation; either
147e83
+   version 2.1 of the License, or (at your option) any later version.
147e83
+
147e83
+   The GNU C Library is distributed in the hope that it will be useful,
147e83
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
147e83
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147e83
+   Lesser General Public License for more details.
147e83
+
147e83
+   You should have received a copy of the GNU Lesser General Public
147e83
+   License along with the GNU C Library; if not, see
147e83
+   <http://www.gnu.org/licenses/>.  */
147e83
+
147e83
+#include <arpa/inet.h>
147e83
+#include <support/check.h>
147e83
+
147e83
+static int
147e83
+do_test (void)
147e83
+{
147e83
+  struct in_addr addr = { };
147e83
+
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.1", &addr), 1);
147e83
+  TEST_COMPARE (ntohl (addr.s_addr), 0xC0000201);
147e83
+
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.000.002.010", &addr), 1);
147e83
+  TEST_COMPARE (ntohl (addr.s_addr), 0xC0000208);
147e83
+  TEST_COMPARE (__inet_aton_exact ("0xC0000234", &addr), 1);
147e83
+  TEST_COMPARE (ntohl (addr.s_addr), 0xC0000234);
147e83
+
147e83
+  /* Trailing content is not accepted.  */
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.2X", &addr), 0);
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.3 Y", &addr), 0);
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.4\nZ", &addr), 0);
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.5\tT", &addr), 0);
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.6 Y", &addr), 0);
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.7\n", &addr), 0);
147e83
+  TEST_COMPARE (__inet_aton_exact ("192.0.2.8\t", &addr), 0);
147e83
+
147e83
+  return 0;
147e83
+}
147e83
+
147e83
+#include <support/test-driver.c>
147e83
diff --git a/resolv/tst-resolv-nondecimal.c b/resolv/tst-resolv-nondecimal.c
147e83
new file mode 100644
147e83
index 0000000000000000..a0df6f332ae8faf7
147e83
--- /dev/null
147e83
+++ b/resolv/tst-resolv-nondecimal.c
147e83
@@ -0,0 +1,139 @@
147e83
+/* Test name resolution behavior for octal, hexadecimal IPv4 addresses.
147e83
+   Copyright (C) 2019 Free Software Foundation, Inc.
147e83
+   This file is part of the GNU C Library.
147e83
+
147e83
+   The GNU C Library is free software; you can redistribute it and/or
147e83
+   modify it under the terms of the GNU Lesser General Public
147e83
+   License as published by the Free Software Foundation; either
147e83
+   version 2.1 of the License, or (at your option) any later version.
147e83
+
147e83
+   The GNU C Library is distributed in the hope that it will be useful,
147e83
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
147e83
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147e83
+   Lesser General Public License for more details.
147e83
+
147e83
+   You should have received a copy of the GNU Lesser General Public
147e83
+   License along with the GNU C Library; if not, see
147e83
+   <http://www.gnu.org/licenses/>.  */
147e83
+
147e83
+#include <netdb.h>
147e83
+#include <stdlib.h>
147e83
+#include <support/check.h>
147e83
+#include <support/check_nss.h>
147e83
+#include <support/resolv_test.h>
147e83
+#include <support/support.h>
147e83
+
147e83
+static void
147e83
+response (const struct resolv_response_context *ctx,
147e83
+          struct resolv_response_builder *b,
147e83
+          const char *qname, uint16_t qclass, uint16_t qtype)
147e83
+{
147e83
+  /* The tests are not supposed send any DNS queries.  */
147e83
+  FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype);
147e83
+}
147e83
+
147e83
+static void
147e83
+run_query_addrinfo (const char *query, const char *address)
147e83
+{
147e83
+  char *quoted_query = support_quote_string (query);
147e83
+
147e83
+  struct addrinfo *ai;
147e83
+  struct addrinfo hints =
147e83
+    {
147e83
+     .ai_socktype = SOCK_STREAM,
147e83
+     .ai_protocol = IPPROTO_TCP,
147e83
+    };
147e83
+
147e83
+  char *context = xasprintf ("getaddrinfo \"%s\" AF_INET", quoted_query);
147e83
+  char *expected = xasprintf ("address: STREAM/TCP %s 80\n", address);
147e83
+  hints.ai_family = AF_INET;
147e83
+  int ret = getaddrinfo (query, "80", &hints, &ai;;
147e83
+  check_addrinfo (context, ai, ret, expected);
147e83
+  if (ret == 0)
147e83
+    freeaddrinfo (ai);
147e83
+  free (context);
147e83
+
147e83
+  context = xasprintf ("getaddrinfo \"%s\" AF_UNSPEC", quoted_query);
147e83
+  hints.ai_family = AF_UNSPEC;
147e83
+  ret = getaddrinfo (query, "80", &hints, &ai;;
147e83
+  check_addrinfo (context, ai, ret, expected);
147e83
+  if (ret == 0)
147e83
+    freeaddrinfo (ai);
147e83
+  free (expected);
147e83
+  free (context);
147e83
+
147e83
+  context = xasprintf ("getaddrinfo \"%s\" AF_INET6", quoted_query);
147e83
+  expected = xasprintf ("flags: AI_V4MAPPED\n"
147e83
+                        "address: STREAM/TCP ::ffff:%s 80\n",
147e83
+                        address);
147e83
+  hints.ai_family = AF_INET6;
147e83
+  hints.ai_flags = AI_V4MAPPED;
147e83
+  ret = getaddrinfo (query, "80", &hints, &ai;;
147e83
+  check_addrinfo (context, ai, ret, expected);
147e83
+  if (ret == 0)
147e83
+    freeaddrinfo (ai);
147e83
+  free (expected);
147e83
+  free (context);
147e83
+
147e83
+  free (quoted_query);
147e83
+}
147e83
+
147e83
+static void
147e83
+run_query (const char *query, const char *address)
147e83
+{
147e83
+  char *quoted_query = support_quote_string (query);
147e83
+  char *context = xasprintf ("gethostbyname (\"%s\")", quoted_query);
147e83
+  char *expected = xasprintf ("name: %s\n"
147e83
+                              "address: %s\n", query, address);
147e83
+  check_hostent (context, gethostbyname (query), expected);
147e83
+  free (context);
147e83
+
147e83
+  context = xasprintf ("gethostbyname_r \"%s\"", quoted_query);
147e83
+  struct hostent storage;
147e83
+  char buf[4096];
147e83
+  struct hostent *e = NULL;
147e83
+  TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf),
147e83
+                                 &e, &h_errno), 0);
147e83
+  check_hostent (context, e, expected);
147e83
+  free (context);
147e83
+
147e83
+  context = xasprintf ("gethostbyname2 (\"%s\", AF_INET)", quoted_query);
147e83
+  check_hostent (context, gethostbyname2 (query, AF_INET), expected);
147e83
+  free (context);
147e83
+
147e83
+  context = xasprintf ("gethostbyname2_r \"%s\" AF_INET", quoted_query);
147e83
+  e = NULL;
147e83
+  TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf),
147e83
+                                  &e, &h_errno), 0);
147e83
+  check_hostent (context, e, expected);
147e83
+  free (context);
147e83
+  free (expected);
147e83
+
147e83
+  free (quoted_query);
147e83
+
147e83
+  /* The gethostbyname tests are always valid for getaddrinfo, but not
147e83
+     vice versa.  */
147e83
+  run_query_addrinfo (query, address);
147e83
+}
147e83
+
147e83
+static int
147e83
+do_test (void)
147e83
+{
147e83
+  struct resolv_test *aux = resolv_test_start
147e83
+    ((struct resolv_redirect_config)
147e83
+     {
147e83
+       .response_callback = response,
147e83
+     });
147e83
+
147e83
+  run_query ("192.000.002.010", "192.0.2.8");
147e83
+
147e83
+  /* Hexadecimal numbers are not accepted by gethostbyname.  */
147e83
+  run_query_addrinfo ("0xc0000210", "192.0.2.16");
147e83
+  run_query_addrinfo ("192.0x234", "192.0.2.52");
147e83
+
147e83
+  resolv_test_end (aux);
147e83
+
147e83
+  return 0;
147e83
+}
147e83
+
147e83
+#include <support/test-driver.c>
147e83
diff --git a/resolv/tst-resolv-trailing.c b/resolv/tst-resolv-trailing.c
147e83
new file mode 100644
147e83
index 0000000000000000..7504bdae572ed8d0
147e83
--- /dev/null
147e83
+++ b/resolv/tst-resolv-trailing.c
147e83
@@ -0,0 +1,136 @@
147e83
+/* Test name resolution behavior with trailing characters.
147e83
+   Copyright (C) 2019 Free Software Foundation, Inc.
147e83
+   This file is part of the GNU C Library.
147e83
+
147e83
+   The GNU C Library is free software; you can redistribute it and/or
147e83
+   modify it under the terms of the GNU Lesser General Public
147e83
+   License as published by the Free Software Foundation; either
147e83
+   version 2.1 of the License, or (at your option) any later version.
147e83
+
147e83
+   The GNU C Library is distributed in the hope that it will be useful,
147e83
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
147e83
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147e83
+   Lesser General Public License for more details.
147e83
+
147e83
+   You should have received a copy of the GNU Lesser General Public
147e83
+   License along with the GNU C Library; if not, see
147e83
+   <http://www.gnu.org/licenses/>.  */
147e83
+
147e83
+#include <array_length.h>
147e83
+#include <netdb.h>
147e83
+#include <support/check.h>
147e83
+#include <support/check_nss.h>
147e83
+#include <support/resolv_test.h>
147e83
+#include <support/support.h>
147e83
+
147e83
+static void
147e83
+response (const struct resolv_response_context *ctx,
147e83
+          struct resolv_response_builder *b,
147e83
+          const char *qname, uint16_t qclass, uint16_t qtype)
147e83
+{
147e83
+  /* The tests are not supposed send any DNS queries.  */
147e83
+  FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype);
147e83
+}
147e83
+
147e83
+static int
147e83
+do_test (void)
147e83
+{
147e83
+  struct resolv_test *aux = resolv_test_start
147e83
+    ((struct resolv_redirect_config)
147e83
+     {
147e83
+       .response_callback = response,
147e83
+     });
147e83
+
147e83
+  static const char *const queries[] =
147e83
+    {
147e83
+     "192.0.2.1 ",
147e83
+     "192.0.2.2\t",
147e83
+     "192.0.2.3\n",
147e83
+     "192.0.2.4 X",
147e83
+     "192.0.2.5\tY",
147e83
+     "192.0.2.6\nZ",
147e83
+     "192.0.2. ",
147e83
+     "192.0.2.\t",
147e83
+     "192.0.2.\n",
147e83
+     "192.0.2. X",
147e83
+     "192.0.2.\tY",
147e83
+     "192.0.2.\nZ",
147e83
+     "2001:db8::1 ",
147e83
+     "2001:db8::2\t",
147e83
+     "2001:db8::3\n",
147e83
+     "2001:db8::4 X",
147e83
+     "2001:db8::5\tY",
147e83
+     "2001:db8::6\nZ",
147e83
+    };
147e83
+  for (size_t query_idx = 0; query_idx < array_length (queries); ++query_idx)
147e83
+    {
147e83
+      const char *query = queries[query_idx];
147e83
+      struct hostent storage;
147e83
+      char buf[4096];
147e83
+      struct hostent *e;
147e83
+
147e83
+      h_errno = 0;
147e83
+      TEST_VERIFY (gethostbyname (query) == NULL);
147e83
+      TEST_COMPARE (h_errno, HOST_NOT_FOUND);
147e83
+
147e83
+      h_errno = 0;
147e83
+      e = NULL;
147e83
+      TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf),
147e83
+                                     &e, &h_errno), 0);
147e83
+      TEST_VERIFY (e == NULL);
147e83
+      TEST_COMPARE (h_errno, HOST_NOT_FOUND);
147e83
+
147e83
+      h_errno = 0;
147e83
+      TEST_VERIFY (gethostbyname2 (query, AF_INET) == NULL);
147e83
+      TEST_COMPARE (h_errno, HOST_NOT_FOUND);
147e83
+
147e83
+      h_errno = 0;
147e83
+      e = NULL;
147e83
+      TEST_COMPARE (gethostbyname2_r (query, AF_INET,
147e83
+                                      &storage, buf, sizeof (buf),
147e83
+                                     &e, &h_errno), 0);
147e83
+      TEST_VERIFY (e == NULL);
147e83
+      TEST_COMPARE (h_errno, HOST_NOT_FOUND);
147e83
+
147e83
+      h_errno = 0;
147e83
+      TEST_VERIFY (gethostbyname2 (query, AF_INET6) == NULL);
147e83
+      TEST_COMPARE (h_errno, HOST_NOT_FOUND);
147e83
+
147e83
+      h_errno = 0;
147e83
+      e = NULL;
147e83
+      TEST_COMPARE (gethostbyname2_r (query, AF_INET6,
147e83
+                                      &storage, buf, sizeof (buf),
147e83
+                                     &e, &h_errno), 0);
147e83
+      TEST_VERIFY (e == NULL);
147e83
+      TEST_COMPARE (h_errno, HOST_NOT_FOUND);
147e83
+
147e83
+      static const int gai_flags[] =
147e83
+        {
147e83
+         0,
147e83
+         AI_ADDRCONFIG,
147e83
+         AI_NUMERICHOST,
147e83
+         AI_IDN,
147e83
+         AI_IDN | AI_NUMERICHOST,
147e83
+         AI_V4MAPPED,
147e83
+         AI_V4MAPPED | AI_NUMERICHOST,
147e83
+        };
147e83
+      for (size_t gai_flags_idx; gai_flags_idx < array_length (gai_flags);
147e83
+             ++gai_flags_idx)
147e83
+        {
147e83
+          struct addrinfo hints = { .ai_flags = gai_flags[gai_flags_idx], };
147e83
+          struct addrinfo *ai;
147e83
+          hints.ai_family = AF_INET;
147e83
+          TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME);
147e83
+          hints.ai_family = AF_INET6;
147e83
+          TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME);
147e83
+          hints.ai_family = AF_UNSPEC;
147e83
+          TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME);
147e83
+        }
147e83
+    };
147e83
+
147e83
+  resolv_test_end (aux);
147e83
+
147e83
+  return 0;
147e83
+}
147e83
+
147e83
+#include <support/test-driver.c>
147e83
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
147e83
index 2c4b6d6793a4c3a9..52f1b590f00c518e 100644
147e83
--- a/sysdeps/posix/getaddrinfo.c
147e83
+++ b/sysdeps/posix/getaddrinfo.c
147e83
@@ -508,7 +508,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
147e83
 	}
147e83
 #endif
147e83
 
147e83
-      if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
147e83
+      if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0)
147e83
 	{
147e83
 	  if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
147e83
 	    at->family = AF_INET;