diff options
author | Florian Weimer <fweimer@redhat.com> | 2018-01-04 12:32:36 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2018-01-04 12:32:36 +0100 |
commit | 0e64ee798605a042a07604e8a4bf0ec00381e28b (patch) | |
tree | a7f3a2e21ebd17596bbeed566ab0e231f3aaccee /sysdeps/posix | |
parent | e3ae300f3f2d1a94709b0f3fed2543b9449a09ca (diff) | |
download | glibc-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.c | 39 |
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; \ |