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 | |
parent | 5f8340f583fe3d4f5734bd2371c5a45ecff2db0d (diff) | |
download | glibc-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.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); \ |