diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-09-01 09:34:29 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-09-01 09:34:29 +0200 |
commit | f4a6be2582b8dfe8adfa68da3dd8decf566b3983 (patch) | |
tree | 76ea7e82a506bf4aed59e1492eaa1970b575bf99 /sysdeps/posix | |
parent | 5f8340f583fe3d4f5734bd2371c5a45ecff2db0d (diff) | |
download | glibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.tar.gz glibc-f4a6be2582b8dfe8adfa68da3dd8decf566b3983.tar.xz 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/posix')
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 42 |
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); \ |