inet: Return EAI_MEMORY when nrl_domainname() fails to allocate memory

It aligns NI_NOFQDN with default behavior for getnameinfo().

Checked on x86_64-linux-gnu.
This commit is contained in:
Adhemerval Zanella 2021-11-10 15:32:42 -03:00
parent b3c68b10af
commit 2da6e43916
1 changed files with 79 additions and 73 deletions

View File

@ -83,94 +83,97 @@ libc_freeres_ptr (static char *domain);
now ignored. */
#define DEPRECATED_NI_IDN 192
static void
/* Return true if no memory allocation failure happened (even if domain
name could not be obtained) or false otherwise. */
static bool
nrl_domainname_core (struct scratch_buffer *tmpbuf)
{
char *c;
struct hostent *h, th;
int herror;
while (__gethostbyname_r ("localhost", &th,
tmpbuf->data, tmpbuf->length,
while (__gethostbyname_r ("localhost", &th, tmpbuf->data, tmpbuf->length,
&h, &herror))
{
if (herror == NETDB_INTERNAL && errno == ERANGE)
{
if (!scratch_buffer_grow (tmpbuf))
return;
return false;
}
else
break;
}
if (h != NULL && (c = strchr (h->h_name, '.')) != NULL)
domain = __strdup (++c);
else
{
/* The name contains no domain information. Use the name
now to get more information. */
while (__gethostname (tmpbuf->data, tmpbuf->length))
if (!scratch_buffer_grow (tmpbuf))
return;
if ((c = strchr (tmpbuf->data, '.')) != NULL)
domain = __strdup (++c);
else
{
/* We need to preserve the hostname. */
size_t hstnamelen = strlen (tmpbuf->data) + 1;
while (__gethostbyname_r (tmpbuf->data, &th,
tmpbuf->data + hstnamelen,
tmpbuf->length - hstnamelen,
&h, &herror))
{
if (herror == NETDB_INTERNAL && errno == ERANGE)
{
if (!scratch_buffer_grow_preserve (tmpbuf))
return;
}
else
break;
}
if (h != NULL && (c = strchr(h->h_name, '.')) != NULL)
domain = __strdup (++c);
else
{
struct in_addr in_addr;
in_addr.s_addr = htonl (INADDR_LOOPBACK);
while (__gethostbyaddr_r ((const char *) &in_addr,
sizeof (struct in_addr),
AF_INET, &th,
tmpbuf->data,
tmpbuf->length,
&h, &herror))
{
if (herror == NETDB_INTERNAL && errno == ERANGE)
{
if (!scratch_buffer_grow (tmpbuf))
return;
}
else
break;
}
if (h != NULL && (c = strchr (h->h_name, '.')) != NULL)
domain = __strdup (++c);
}
}
domain = __strdup (++c);
return domain != NULL;
}
/* The name contains no domain information. Use the name
now to get more information. */
while (__gethostname (tmpbuf->data, tmpbuf->length))
if (!scratch_buffer_grow (tmpbuf))
return false;
if ((c = strchr (tmpbuf->data, '.')) != NULL)
{
domain = __strdup (++c);
return domain != NULL;
}
/* We need to preserve the hostname. */
size_t hstnamelen = strlen (tmpbuf->data) + 1;
while (__gethostbyname_r (tmpbuf->data, &th, tmpbuf->data + hstnamelen,
tmpbuf->length - hstnamelen, &h, &herror))
{
if (herror == NETDB_INTERNAL && errno == ERANGE)
{
if (!scratch_buffer_grow_preserve (tmpbuf))
return false;
}
else
break;
}
if (h != NULL && (c = strchr(h->h_name, '.')) != NULL)
{
domain = __strdup (++c);
return domain != NULL;
}
struct in_addr in_addr = { .s_addr = htonl (INADDR_LOOPBACK) };
while (__gethostbyaddr_r ((const char *) &in_addr, sizeof (struct in_addr),
AF_INET, &th, tmpbuf->data, tmpbuf->length, &h,
&herror))
{
if (herror == NETDB_INTERNAL && errno == ERANGE)
{
if (!scratch_buffer_grow (tmpbuf))
return false;
}
else
break;
}
if (h != NULL && (c = strchr (h->h_name, '.')) != NULL)
{
domain = __strdup (++c);
return domain != NULL;
}
return true;
}
static char *
static bool
nrl_domainname (void)
{
static int not_first;
if (__glibc_likely (atomic_load_acquire (&not_first) != 0))
return domain;
return true;
int r = true;
__libc_lock_define_initialized (static, lock);
__libc_lock_lock (lock);
@ -180,16 +183,15 @@ nrl_domainname (void)
struct scratch_buffer tmpbuf;
scratch_buffer_init (&tmpbuf);
nrl_domainname_core (&tmpbuf);
if ((r = nrl_domainname_core (&tmpbuf)))
atomic_store_release (&not_first, 1);
scratch_buffer_free (&tmpbuf);
atomic_store_release (&not_first, 1);
}
__libc_lock_unlock (lock);
return domain;
return r;
};
/* Copy a string to a destination buffer with length checking. Return
@ -285,13 +287,17 @@ gni_host_inet_name (struct scratch_buffer *tmpbuf,
if (h)
{
char *c;
if ((flags & NI_NOFQDN)
&& (c = nrl_domainname ())
&& (c = strstr (h->h_name, c))
&& (c != h->h_name) && (*(--c) == '.'))
/* Terminate the string after the prefix. */
*c = '\0';
if (flags & NI_NOFQDN)
{
if (!nrl_domainname ())
return EAI_MEMORY;
char *c = domain;
if (c != NULL && (c = strstr (h->h_name, c))
&& (c != h->h_name) && (*(--c) == '.'))
/* Terminate the string after the prefix. */
*c = '\0';
}
/* If requested, convert from the IDN format. */
bool do_idn = flags & NI_IDN;