aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
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
parent5f8340f583fe3d4f5734bd2371c5a45ecff2db0d (diff)
downloadglibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.tar
glibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.tar.gz
glibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.tar.bz2
glibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.zip
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')
-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 0471a2f624..ce099bdf9c 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); \