Created
January 29, 2015 16:30
-
-
Save eduherraiz/ea6884ca90622dede558 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From d5dd6189d506068ed11c8bfa1e1e9bffde04decd Mon Sep 17 00:00:00 2001 | |
From: Andreas Schwab <[email protected]> | |
Date: Mon, 21 Jan 2013 17:41:28 +0100 | |
Subject: [PATCH] Fix parsing of numeric hosts in gethostbyname_r | |
--- | |
ChangeLog | 14 +++++++++ | |
NEWS | 12 ++++---- | |
nss/Makefile | 2 +- | |
nss/digits_dots.c | 73 +++++++++++++---------------------------------- | |
nss/getXXbyYY_r.c | 5 ++- | |
nss/test-digits-dots.c | 38 +++++++++++++++++++++++++ | |
6 files changed, 83 insertions(+), 61 deletions(-) | |
create mode 100644 nss/test-digits-dots.c | |
diff --git a/nss/Makefile b/nss/Makefile | |
index 449a258..553eafa 100644 | |
--- a/nss/Makefile | |
+++ b/nss/Makefile | |
@@ -37,7 +37,7 @@ install-bin := getent makedb | |
makedb-modules = xmalloc hash-string | |
extra-objs += $(makedb-modules:=.o) | |
-tests = test-netdb | |
+tests = test-netdb test-digits-dots | |
xtests = bug-erange | |
include ../Makeconfig | |
diff --git a/nss/digits_dots.c b/nss/digits_dots.c | |
index 2b86295..e007ef4 100644 | |
--- a/nss/digits_dots.c | |
+++ b/nss/digits_dots.c | |
@@ -46,7 +46,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
{ | |
if (h_errnop) | |
*h_errnop = NETDB_INTERNAL; | |
- *result = NULL; | |
+ if (buffer_size == NULL) | |
+ *status = NSS_STATUS_TRYAGAIN; | |
+ else | |
+ *result = NULL; | |
return -1; | |
} | |
@@ -83,14 +86,16 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
} | |
size_needed = (sizeof (*host_addr) | |
- + sizeof (*h_addr_ptrs) + strlen (name) + 1); | |
+ + sizeof (*h_addr_ptrs) | |
+ + sizeof (*h_alias_ptr) + strlen (name) + 1); | |
if (buffer_size == NULL) | |
{ | |
if (buflen < size_needed) | |
{ | |
+ *status = NSS_STATUS_TRYAGAIN; | |
if (h_errnop != NULL) | |
- *h_errnop = TRY_AGAIN; | |
+ *h_errnop = NETDB_INTERNAL; | |
__set_errno (ERANGE); | |
goto done; | |
} | |
@@ -109,7 +114,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
*buffer_size = 0; | |
__set_errno (save); | |
if (h_errnop != NULL) | |
- *h_errnop = TRY_AGAIN; | |
+ *h_errnop = NETDB_INTERNAL; | |
*result = NULL; | |
goto done; | |
} | |
@@ -149,7 +154,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
if (! ok) | |
{ | |
*h_errnop = HOST_NOT_FOUND; | |
- if (buffer_size) | |
+ if (buffer_size == NULL) | |
+ *status = NSS_STATUS_NOTFOUND; | |
+ else | |
*result = NULL; | |
goto done; | |
} | |
@@ -190,7 +197,7 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
if (buffer_size == NULL) | |
*status = NSS_STATUS_SUCCESS; | |
else | |
- *result = resbuf; | |
+ *result = resbuf; | |
goto done; | |
} | |
@@ -201,15 +208,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':') | |
{ | |
- const char *cp; | |
- char *hostname; | |
- typedef unsigned char host_addr_t[16]; | |
- host_addr_t *host_addr; | |
- typedef char *host_addr_list_t[2]; | |
- host_addr_list_t *h_addr_ptrs; | |
- size_t size_needed; | |
- int addr_size; | |
- | |
switch (af) | |
{ | |
default: | |
@@ -225,7 +223,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
/* This is not possible. We cannot represent an IPv6 address | |
in an `struct in_addr' variable. */ | |
*h_errnop = HOST_NOT_FOUND; | |
- *result = NULL; | |
+ if (buffer_size == NULL) | |
+ *status = NSS_STATUS_NOTFOUND; | |
+ else | |
+ *result = NULL; | |
goto done; | |
case AF_INET6: | |
@@ -233,42 +234,6 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
break; | |
} | |
- size_needed = (sizeof (*host_addr) | |
- + sizeof (*h_addr_ptrs) + strlen (name) + 1); | |
- | |
- if (buffer_size == NULL && buflen < size_needed) | |
- { | |
- if (h_errnop != NULL) | |
- *h_errnop = TRY_AGAIN; | |
- __set_errno (ERANGE); | |
- goto done; | |
- } | |
- else if (buffer_size != NULL && *buffer_size < size_needed) | |
- { | |
- char *new_buf; | |
- *buffer_size = size_needed; | |
- new_buf = realloc (*buffer, *buffer_size); | |
- | |
- if (new_buf == NULL) | |
- { | |
- save = errno; | |
- free (*buffer); | |
- __set_errno (save); | |
- *buffer = NULL; | |
- *buffer_size = 0; | |
- *result = NULL; | |
- goto done; | |
- } | |
- *buffer = new_buf; | |
- } | |
- | |
- memset (*buffer, '\0', size_needed); | |
- | |
- host_addr = (host_addr_t *) *buffer; | |
- h_addr_ptrs = (host_addr_list_t *) | |
- ((char *) host_addr + sizeof (*host_addr)); | |
- hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs); | |
- | |
for (cp = name;; ++cp) | |
{ | |
if (!*cp) | |
@@ -281,7 +246,9 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, | |
if (inet_pton (AF_INET6, name, host_addr) <= 0) | |
{ | |
*h_errnop = HOST_NOT_FOUND; | |
- if (buffer_size) | |
+ if (buffer_size == NULL) | |
+ *status = NSS_STATUS_NOTFOUND; | |
+ else | |
*result = NULL; | |
goto done; | |
} | |
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c | |
index 1067744..44d00f4 100644 | |
--- a/nss/getXXbyYY_r.c | |
+++ b/nss/getXXbyYY_r.c | |
@@ -179,6 +179,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer, | |
case -1: | |
return errno; | |
case 1: | |
+#ifdef NEED_H_ERRNO | |
+ any_service = true; | |
+#endif | |
goto done; | |
} | |
#endif | |
diff --git a/nss/test-digits-dots.c b/nss/test-digits-dots.c | |
new file mode 100644 | |
index 0000000..1efa344 | |
--- /dev/null | |
+++ b/nss/test-digits-dots.c | |
@@ -0,0 +1,38 @@ | |
+/* Copyright (C) 2013 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 | |
+ <http://www.gnu.org/licenses/>. */ | |
+ | |
+/* Testcase for BZ #15014 */ | |
+ | |
+#include <stdlib.h> | |
+#include <netdb.h> | |
+#include <errno.h> | |
+ | |
+static int | |
+do_test (void) | |
+{ | |
+ char buf[32]; | |
+ struct hostent *result = NULL; | |
+ struct hostent ret; | |
+ int h_err = 0; | |
+ int err; | |
+ | |
+ err = gethostbyname_r ("1.2.3.4", &ret, buf, sizeof (buf), &result, &h_err); | |
+ return err == ERANGE && h_err == NETDB_INTERNAL ? EXIT_SUCCESS : EXIT_FAILURE; | |
+} | |
+ | |
+#define TEST_FUNCTION do_test () | |
+#include "../test-skeleton.c" | |
-- | |
1.7.1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment