aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/posix
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-09-01 09:34:29 +0200
committerFlorian Weimer <fweimer@redhat.com>2017-09-01 09:34:29 +0200
commitf4a6be2582b8dfe8adfa68da3dd8decf566b3983 (patch)
tree76ea7e82a506bf4aed59e1492eaa1970b575bf99 /sysdeps/posix
parent5f8340f583fe3d4f5734bd2371c5a45ecff2db0d (diff)
downloadglibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.zip
glibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.tar.gz
glibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.tar.bz2
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.
Diffstat (limited to 'sysdeps/posix')
-rw-r--r--sysdeps/posix/getaddrinfo.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 0471a2f..ce099bd 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -242,28 +242,26 @@ 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)) \
- { \
- __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
- __resolv_context_put (res_ctx); \
- 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)) \
+ { \
+ __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
+ __resolv_context_put (res_ctx); \
+ 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) \
{ \
@@ -277,9 +275,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)) \
{ \
__resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
__resolv_context_put (res_ctx); \