getaddrinfo: Always allocate canonical name on the heap
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.
This commit is contained in:
parent
91b6eb1140
commit
673cb072a4
|
@ -1,3 +1,8 @@
|
||||||
|
2017-06-02 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
* sysdeps/posix/getaddrinfo.c (getcanonname): New function.
|
||||||
|
(gaih_inet): Remove malloc_canonbuf variable. Call getcanonname.
|
||||||
|
|
||||||
2017-06-02 Florian Weimer <fweimer@redhat.com>
|
2017-06-02 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
* malloc/Makefile (routines): Add dynarray_at_failure,
|
* malloc/Makefile (routines): Add dynarray_at_failure,
|
||||||
|
|
|
@ -308,6 +308,30 @@ typedef enum nss_status (*nss_getcanonname_r)
|
||||||
int *errnop, int *h_errnop);
|
int *errnop, int *h_errnop);
|
||||||
extern service_user *__nss_hosts_database attribute_hidden;
|
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
|
static int
|
||||||
gaih_inet (const char *name, const struct gaih_service *service,
|
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;
|
bool malloc_name = false;
|
||||||
struct gaih_addrtuple *addrmem = NULL;
|
struct gaih_addrtuple *addrmem = NULL;
|
||||||
bool malloc_canonbuf = false;
|
|
||||||
char *canonbuf = NULL;
|
char *canonbuf = NULL;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
|
@ -702,22 +725,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||||
(*pat)->name = NULL;
|
(*pat)->name = NULL;
|
||||||
else if (canonbuf == NULL)
|
else if (canonbuf == NULL)
|
||||||
{
|
{
|
||||||
size_t canonlen = strlen (air->canon) + 1;
|
canonbuf = strdup (air->canon);
|
||||||
if ((req->ai_flags & AI_CANONIDN) != 0
|
if (canonbuf == NULL)
|
||||||
&& __libc_use_alloca (alloca_used + canonlen))
|
|
||||||
canonbuf = alloca_account (canonlen, alloca_used);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
canonbuf = malloc (canonlen);
|
result = -EAI_MEMORY;
|
||||||
if (canonbuf == NULL)
|
goto free_and_return;
|
||||||
{
|
|
||||||
result = -EAI_MEMORY;
|
|
||||||
goto free_and_return;
|
|
||||||
}
|
|
||||||
malloc_canonbuf = true;
|
|
||||||
}
|
}
|
||||||
canon = (*pat)->name = memcpy (canonbuf, air->canon,
|
canon = (*pat)->name = canonbuf;
|
||||||
canonlen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (air->family[i] == AF_INET
|
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
|
if ((req->ai_flags & AI_CANONNAME) != 0
|
||||||
&& canon == NULL)
|
&& canon == NULL)
|
||||||
{
|
{
|
||||||
/* If we need the canonical name, get it
|
canonbuf = getcanonname (nip, at, name);
|
||||||
from the same service as the result. */
|
if (canonbuf == NULL)
|
||||||
nss_getcanonname_r cfct;
|
|
||||||
int herrno;
|
|
||||||
|
|
||||||
cfct = __nss_lookup_function (nip,
|
|
||||||
"getcanonname_r");
|
|
||||||
if (cfct != NULL)
|
|
||||||
{
|
{
|
||||||
const size_t max_fqdn_len = 256;
|
_res.options
|
||||||
if ((req->ai_flags & AI_CANONIDN) != 0
|
|= old_res_options
|
||||||
&& __libc_use_alloca (alloca_used
|
& DEPRECATED_RES_USE_INET6;
|
||||||
+ max_fqdn_len))
|
result = -EAI_MEMORY;
|
||||||
canonbuf = alloca_account (max_fqdn_len,
|
goto free_and_return;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
canon = canonbuf;
|
||||||
}
|
}
|
||||||
status = NSS_STATUS_SUCCESS;
|
status = NSS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1118,9 +1093,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||||
#ifdef HAVE_LIBIDN
|
#ifdef HAVE_LIBIDN
|
||||||
make_copy:
|
make_copy:
|
||||||
#endif
|
#endif
|
||||||
if (malloc_canonbuf)
|
if (canonbuf != NULL)
|
||||||
/* We already allocated the string using malloc. */
|
/* We already allocated the string using malloc, but
|
||||||
malloc_canonbuf = false;
|
the buffer is now owned by canon. */
|
||||||
|
canonbuf = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
canon = __strdup (canon);
|
canon = __strdup (canon);
|
||||||
|
@ -1215,8 +1191,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||||
if (malloc_name)
|
if (malloc_name)
|
||||||
free ((char *) name);
|
free ((char *) name);
|
||||||
free (addrmem);
|
free (addrmem);
|
||||||
if (malloc_canonbuf)
|
free (canonbuf);
|
||||||
free (canonbuf);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue