summaryrefslogtreecommitdiff
path: root/sysdeps/posix
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2018-01-04 12:32:36 +0100
committerFlorian Weimer <fweimer@redhat.com>2018-01-04 12:32:36 +0100
commit0e64ee798605a042a07604e8a4bf0ec00381e28b (patch)
treea7f3a2e21ebd17596bbeed566ab0e231f3aaccee /sysdeps/posix
parente3ae300f3f2d1a94709b0f3fed2543b9449a09ca (diff)
downloadglibc-0e64ee798605a042a07604e8a4bf0ec00381e28b.tar.gz
getaddrinfo: Fix error handling in gethosts [BZ #21915] [BZ #21922]
The old code uses errno as the primary indicator for success or failure. This is wrong because errno is only set for specific combinations of the status return value and the h_errno variable. (cherry picked from commit f4a6be2582b8dfe8adfa68da3dd8decf566b3983)
Diffstat (limited to 'sysdeps/posix')
-rw-r--r--sysdeps/posix/getaddrinfo.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index bcd437c022..43cebb551a 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -241,26 +241,25 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
#define gethosts(_family, _type) \
{ \
struct hostent th; \
- struct hostent *h; \
char *localcanon = NULL; \
no_data = 0; \
- while (1) { \
- status = DL_CALL_FCT (fct, (name, _family, &th, \
- tmpbuf->data, tmpbuf->length, \
- &errno, &h_errno, NULL, &localcanon)); \
- if (errno != ERANGE || h_errno != NETDB_INTERNAL) \
- break; \
- if (!scratch_buffer_grow (tmpbuf)) \
- { \
- result = -EAI_MEMORY; \
- goto free_and_return; \
- } \
- } \
- if (status == NSS_STATUS_SUCCESS && errno == 0) \
- h = &th; \
- else \
- h = NULL; \
- if (errno != 0) \
+ while (1) \
+ { \
+ status = DL_CALL_FCT (fct, (name, _family, &th, \
+ tmpbuf->data, tmpbuf->length, \
+ &errno, &h_errno, NULL, &localcanon)); \
+ if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL \
+ || errno != ERANGE) \
+ break; \
+ if (!scratch_buffer_grow (tmpbuf)) \
+ { \
+ _res.options |= old_res_options & DEPRECATED_RES_USE_INET6; \
+ result = -EAI_MEMORY; \
+ goto free_and_return; \
+ } \
+ } \
+ if (status == NSS_STATUS_NOTFOUND \
+ || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) \
{ \
if (h_errno == NETDB_INTERNAL) \
{ \
@@ -273,9 +272,9 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
else \
no_data = h_errno == NO_DATA; \
} \
- else if (h != NULL) \
+ else if (status == NSS_STATUS_SUCCESS) \
{ \
- if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \
+ if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \
{ \
_res.options |= old_res_options & DEPRECATED_RES_USE_INET6; \
result = -EAI_SYSTEM; \