This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] getaddrinfo: Always allocate canonical name on the heap
- From: Siddhesh Poyarekar <siddhesh at gotplt dot org>
- To: Florian Weimer <fweimer at redhat dot com>, libc-alpha at sourceware dot org
- Date: Thu, 18 May 2017 23:58:54 +0530
- Subject: Re: [PATCH] getaddrinfo: Always allocate canonical name on the heap
- Authentication-results: sourceware.org; auth=none
- References: <20170511100718.1F66A401E714A@oldenburg.str.redhat.com>
On Thursday 11 May 2017 03:37 PM, Florian Weimer wrote:
> A further simplification could eliminate the canon variable in
> gaih_inet and replace it with canonbuf. However, canonbuf is
> used as a flag in the nscd code, which makes this somewhat
> non-straightforward.
>
> 2017-05-11 Florian Weimer <fweimer@redhat.com>
>
> * sysdeps/posix/getaddrinfo.c (getcanonname): New function.
> (gaih_inet): Remove malloc_canonbuf variable. Call getcanonname.
LGTM (and the G here is not just good, it's great), thank you for
cleaning up!
Siddhesh
> diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
> index dc02b11..d92db70 100644
> --- a/sysdeps/posix/getaddrinfo.c
> +++ b/sysdeps/posix/getaddrinfo.c
> @@ -308,6 +308,30 @@ typedef enum nss_status (*nss_getcanonname_r)
> int *errnop, int *h_errnop);
> extern service_user *__nss_hosts_database attribute_hidden;
>
> +/* This function is called if a canonical name is requested, but if
> + the service function did not provide it. It tries to obtain the
> + name using getcanonname_r from the same service NIP. If the name
> + cannot be canonicalized, return a copy of NAME. Return NULL on
> + memory allocation failure. The returned string is allocated on the
> + heap; the caller has to free it. */
> +static char *
> +getcanonname (service_user *nip, struct gaih_addrtuple *at, const char *name)
> +{
> + nss_getcanonname_r cfct = __nss_lookup_function (nip, "getcanonname_r");
> + char *s = (char *) name;
> + if (cfct != NULL)
> + {
> + char buf[256];
> + int herrno;
> + int rc;
> + if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf),
> + &s, &rc, &herrno)) != NSS_STATUS_SUCCESS)
> + /* If the canonical name cannot be determined, use the passed
> + string. */
> + s = (char *) name;
> + }
> + return strdup (name);
> +}
>
> static int
> gaih_inet (const char *name, const struct gaih_service *service,
> @@ -443,7 +467,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
>
> bool malloc_name = false;
> struct gaih_addrtuple *addrmem = NULL;
> - bool malloc_canonbuf = false;
> char *canonbuf = NULL;
> int result = 0;
>
> @@ -702,22 +725,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
> (*pat)->name = NULL;
> else if (canonbuf == NULL)
> {
> - size_t canonlen = strlen (air->canon) + 1;
> - if ((req->ai_flags & AI_CANONIDN) != 0
> - && __libc_use_alloca (alloca_used + canonlen))
> - canonbuf = alloca_account (canonlen, alloca_used);
> - else
> + canonbuf = strdup (air->canon);
> + if (canonbuf == NULL)
> {
> - canonbuf = malloc (canonlen);
> - if (canonbuf == NULL)
> - {
> - result = -EAI_MEMORY;
> - goto free_and_return;
> - }
> - malloc_canonbuf = true;
> + result = -EAI_MEMORY;
> + goto free_and_return;
> }
> - canon = (*pat)->name = memcpy (canonbuf, air->canon,
> - canonlen);
> + canon = (*pat)->name = canonbuf;
> }
>
> if (air->family[i] == AF_INET
> @@ -924,55 +938,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
> if ((req->ai_flags & AI_CANONNAME) != 0
> && canon == NULL)
> {
> - /* If we need the canonical name, get it
> - from the same service as the result. */
> - nss_getcanonname_r cfct;
> - int herrno;
> -
> - cfct = __nss_lookup_function (nip,
> - "getcanonname_r");
> - if (cfct != NULL)
> + canonbuf = getcanonname (nip, at, name);
> + if (canonbuf == NULL)
> {
> - const size_t max_fqdn_len = 256;
> - if ((req->ai_flags & AI_CANONIDN) != 0
> - && __libc_use_alloca (alloca_used
> - + max_fqdn_len))
> - canonbuf = alloca_account (max_fqdn_len,
> - alloca_used);
> - else
> - {
> - canonbuf = malloc (max_fqdn_len);
> - if (canonbuf == NULL)
> - {
> - _res.options
> - |= old_res_options
> - & DEPRECATED_RES_USE_INET6;
> - result = -EAI_MEMORY;
> - goto free_and_return;
> - }
> - malloc_canonbuf = true;
> - }
> - char *s;
> -
> - if (DL_CALL_FCT (cfct, (at->name ?: name,
> - canonbuf,
> - max_fqdn_len,
> - &s, &rc, &herrno))
> - == NSS_STATUS_SUCCESS)
> - canon = s;
> - else
> - {
> - /* If the canonical name cannot be
> - determined, use the passed in
> - string. */
> - if (malloc_canonbuf)
> - {
> - free (canonbuf);
> - malloc_canonbuf = false;
> - }
> - canon = name;
> - }
> + _res.options
> + |= old_res_options
> + & DEPRECATED_RES_USE_INET6;
> + result = -EAI_MEMORY;
> + goto free_and_return;
> }
> + canon = canonbuf;
> }
> status = NSS_STATUS_SUCCESS;
> }
> @@ -1118,9 +1093,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
> #ifdef HAVE_LIBIDN
> make_copy:
> #endif
> - if (malloc_canonbuf)
> - /* We already allocated the string using malloc. */
> - malloc_canonbuf = false;
> + if (canonbuf != NULL)
> + /* We already allocated the string using malloc, but
> + the buffer is now owned by canon. */
> + canonbuf = NULL;
> else
> {
> canon = __strdup (canon);
> @@ -1215,8 +1191,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
> if (malloc_name)
> free ((char *) name);
> free (addrmem);
> - if (malloc_canonbuf)
> - free (canonbuf);
> + free (canonbuf);
>
> return result;
> }
>