diff options
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index 6ae6744fe4..47f421fddf 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -120,6 +120,7 @@ struct gaih_result { struct gaih_addrtuple *at; char *canon; + char *h_name; bool free_at; bool got_ipv6; }; @@ -165,6 +166,7 @@ gaih_result_reset (struct gaih_result *res) if (res->free_at) free (res->at); free (res->canon); + free (res->h_name); memset (res, 0, sizeof (*res)); } @@ -203,9 +205,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, return 0; } -/* Convert struct hostent to a list of struct gaih_addrtuple objects. h_name - is not copied, and the struct hostent object must not be deallocated - prematurely. The new addresses are appended to the tuple array in RES. */ +/* Convert struct hostent to a list of struct gaih_addrtuple objects. The new + addresses are appended to the tuple array in RES. */ static bool convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family, struct hostent *h, struct gaih_result *res) @@ -238,6 +239,15 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family, res->at = array; res->free_at = true; + /* Duplicate h_name because it may get reclaimed when the underlying storage + is freed. */ + if (res->h_name == NULL) + { + res->h_name = __strdup (h->h_name); + if (res->h_name == NULL) + return false; + } + /* Update the next pointers on reallocation. */ for (size_t i = 0; i < old; i++) array[i].next = array + i + 1; @@ -262,7 +272,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family, } array[i].next = array + i + 1; } - array[0].name = h->h_name; array[count - 1].next = NULL; return true; @@ -324,15 +333,15 @@ gethosts (nss_gethostbyname3_r fct, int family, const char *name, memory allocation failure. The returned string is allocated on the heap; the caller has to free it. */ static char * -getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name) +getcanonname (nss_action_list nip, const char *hname, const char *name) { nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r"); char *s = (char *) name; if (cfct != NULL) { char buf[256]; - if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf), - &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS) + if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf), &s, &errno, + &h_errno)) != NSS_STATUS_SUCCESS) /* If the canonical name cannot be determined, use the passed string. */ s = (char *) name; @@ -771,7 +780,7 @@ get_nss_addresses (const char *name, const struct addrinfo *req, if ((req->ai_flags & AI_CANONNAME) != 0 && res->canon == NULL) { - char *canonbuf = getcanonname (nip, res->at, name); + char *canonbuf = getcanonname (nip, res->h_name, name); if (canonbuf == NULL) { __resolv_context_put (res_ctx); |