mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 19:00:07 +00:00
Don't unconditionally use alloca in gaih_inet
This commit is contained in:
parent
78e64fdcaa
commit
34a9094f49
@ -1,5 +1,10 @@
|
||||
2011-05-20 Ulrich Drepper <drepper@gmail.com>
|
||||
|
||||
[BZ #11869]
|
||||
* sysdeps/posix/getaddrinfo.c (gaih_inet): Don't unconditionally use
|
||||
alloca.
|
||||
* include/alloca.h (extend_alloca_account): Define.
|
||||
|
||||
[BZ #11857]
|
||||
* posix/regex.h: Fix comments with documentation of user-accessible
|
||||
fields after compilation and describe correct free'ing of pattern
|
||||
|
12
NEWS
12
NEWS
@ -11,12 +11,12 @@ Version 2.14
|
||||
|
||||
386, 6420, 7101, 9730, 9732, 9809, 10138, 10149, 10157, 11257, 11258,
|
||||
11487, 11532, 11578, 11653, 11668, 11697, 11724, 11820, 11837, 11857,
|
||||
11892, 11895, 11901, 11945, 11947, 11952, 11987, 12052, 12083, 12158,
|
||||
12178, 12200, 12346, 12393, 12420, 12432, 12445, 12449, 12453, 12454,
|
||||
12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12541, 12545,
|
||||
12551, 12582, 12583, 12587, 12597, 12601, 12611, 12625, 12626, 12631,
|
||||
12650, 12653, 12655, 12660, 12681, 12685, 12711, 12713, 12714, 12717,
|
||||
12723, 12724, 12734, 12738, 12746, 12766, 12775
|
||||
11869, 11892, 11895, 11901, 11945, 11947, 11952, 11987, 12052, 12083,
|
||||
12158, 12178, 12200, 12346, 12393, 12420, 12432, 12445, 12449, 12453,
|
||||
12454, 12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12541,
|
||||
12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611, 12625, 12626,
|
||||
12631, 12650, 12653, 12655, 12660, 12681, 12685, 12711, 12713, 12714,
|
||||
12717, 12723, 12724, 12734, 12738, 12746, 12766, 12775
|
||||
|
||||
* The RPC implementation in libc is obsoleted. Old programs keep working
|
||||
but new programs cannot be linked with the routines in libc anymore.
|
||||
|
@ -49,15 +49,24 @@ libc_hidden_proto (__libc_alloca_cutoff)
|
||||
|
||||
#if defined stackinfo_get_sp && defined stackinfo_sub_sp
|
||||
# define alloca_account(size, avar) \
|
||||
({ void *old__ = stackinfo_get_sp (); \
|
||||
void *m__ = __alloca (size); \
|
||||
avar += stackinfo_sub_sp (old__); \
|
||||
({ void *old__ = stackinfo_get_sp (); \
|
||||
void *m__ = __alloca (size); \
|
||||
avar += stackinfo_sub_sp (old__); \
|
||||
m__; })
|
||||
# define extend_alloca_account(buf, len, newlen, avar) \
|
||||
({ void *old__ = stackinfo_get_sp (); \
|
||||
void *m__ = extend_alloca (buf, len, newlen); \
|
||||
avar += stackinfo_sub_sp (old__); \
|
||||
m__; })
|
||||
#else
|
||||
# define alloca_account(size, avar) \
|
||||
({ size_t s__ = (size); \
|
||||
avar += s__; \
|
||||
({ size_t s__ = (size); \
|
||||
avar += s__; \
|
||||
__alloca (s__); })
|
||||
# define extend_alloca_account(buf, len, newlen, avar) \
|
||||
({ size_t s__ = (newlen); \
|
||||
avar += s__; \
|
||||
extend_alloca (buf, len, s__); })
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -278,6 +278,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
bool got_ipv6 = false;
|
||||
const char *canon = NULL;
|
||||
const char *orig_name = name;
|
||||
size_t alloca_used = 0;
|
||||
|
||||
if (req->ai_protocol || req->ai_socktype)
|
||||
{
|
||||
@ -310,7 +311,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if (tp->name[0])
|
||||
{
|
||||
st = (struct gaih_servtuple *)
|
||||
__alloca (sizeof (struct gaih_servtuple));
|
||||
alloca_account (sizeof (struct gaih_servtuple), alloca_used);
|
||||
|
||||
if ((rc = gaih_inet_serv (service->name, tp, req, st)))
|
||||
return rc;
|
||||
@ -334,7 +335,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
continue;
|
||||
|
||||
newp = (struct gaih_servtuple *)
|
||||
__alloca (sizeof (struct gaih_servtuple));
|
||||
alloca_account (sizeof (struct gaih_servtuple),
|
||||
alloca_used);
|
||||
|
||||
if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
|
||||
{
|
||||
@ -362,7 +364,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
if (req->ai_socktype || req->ai_protocol)
|
||||
{
|
||||
st = __alloca (sizeof (struct gaih_servtuple));
|
||||
st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
|
||||
st->next = NULL;
|
||||
st->socktype = tp->socktype;
|
||||
st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
|
||||
@ -379,7 +381,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
{
|
||||
struct gaih_servtuple *newp;
|
||||
|
||||
newp = __alloca (sizeof (struct gaih_servtuple));
|
||||
newp = alloca_account (sizeof (struct gaih_servtuple),
|
||||
alloca_used);
|
||||
newp->next = NULL;
|
||||
newp->socktype = tp->socktype;
|
||||
newp->protocol = tp->protocol;
|
||||
@ -391,10 +394,17 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
}
|
||||
|
||||
bool malloc_name = false;
|
||||
bool malloc_addrmem = false;
|
||||
struct gaih_addrtuple *addrmem = NULL;
|
||||
bool malloc_canonbuf = false;
|
||||
char *canonbuf = NULL;
|
||||
bool malloc_tmpbuf = false;
|
||||
char *tmpbuf = NULL;
|
||||
int result = 0;
|
||||
if (name != NULL)
|
||||
{
|
||||
at = __alloca (sizeof (struct gaih_addrtuple));
|
||||
|
||||
at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
|
||||
at->family = AF_UNSPEC;
|
||||
at->scopeid = 0;
|
||||
at->next = NULL;
|
||||
@ -412,6 +422,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
rc = __idna_to_ascii_lz (name, &p, idn_flags);
|
||||
if (rc != IDNA_SUCCESS)
|
||||
{
|
||||
/* No need to jump to free_and_return here. */
|
||||
if (rc == IDNA_MALLOC_ERROR)
|
||||
return -EAI_MEMORY;
|
||||
if (rc == IDNA_DLOPEN_ERROR)
|
||||
@ -421,10 +432,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
/* In case the output string is the same as the input string
|
||||
no new string has been allocated. */
|
||||
if (p != name)
|
||||
{
|
||||
name = strdupa (p);
|
||||
free (p);
|
||||
}
|
||||
malloc_name = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -441,23 +449,59 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
at->family = AF_INET6;
|
||||
}
|
||||
else
|
||||
return -EAI_ADDRFAMILY;
|
||||
{
|
||||
result = -EAI_ADDRFAMILY;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (req->ai_flags & AI_CANONNAME)
|
||||
canon = name;
|
||||
}
|
||||
else if (at->family == AF_UNSPEC)
|
||||
{
|
||||
char *namebuf = (char *) name;
|
||||
char *scope_delim = strchr (name, SCOPE_DELIMITER);
|
||||
int e;
|
||||
|
||||
if (__builtin_expect (scope_delim != NULL, 0))
|
||||
{
|
||||
namebuf = alloca (scope_delim - name + 1);
|
||||
*((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
|
||||
}
|
||||
{
|
||||
bool malloc_namebuf = false;
|
||||
char *namebuf = (char *) name;
|
||||
|
||||
if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
|
||||
if (__builtin_expect (scope_delim != NULL, 0))
|
||||
{
|
||||
if (malloc_name)
|
||||
*scope_delim = '\0';
|
||||
else
|
||||
{
|
||||
if (__libc_use_alloca (alloca_used
|
||||
+ scope_delim - name + 1))
|
||||
{
|
||||
namebuf = alloca_account (scope_delim - name + 1,
|
||||
alloca_used);
|
||||
*((char *) __mempcpy (namebuf, name,
|
||||
scope_delim - name)) = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
namebuf = strndup (name, scope_delim - name);
|
||||
if (namebuf == NULL)
|
||||
{
|
||||
assert (!malloc_name);
|
||||
return -EAI_MEMORY;
|
||||
}
|
||||
malloc_namebuf = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e = inet_pton (AF_INET6, namebuf, at->addr);
|
||||
|
||||
if (malloc_namebuf)
|
||||
free (namebuf);
|
||||
else if (scope_delim != NULL && malloc_name)
|
||||
/* Undo what we did above. */
|
||||
*scope_delim = SCOPE_DELIMITER;
|
||||
}
|
||||
if (e > 0)
|
||||
{
|
||||
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
|
||||
at->family = AF_INET6;
|
||||
@ -468,7 +512,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
at->family = AF_INET;
|
||||
}
|
||||
else
|
||||
return -EAI_ADDRFAMILY;
|
||||
{
|
||||
result = -EAI_ADDRFAMILY;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (scope_delim != NULL)
|
||||
{
|
||||
@ -490,7 +537,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
|
||||
10);
|
||||
if (*end != '\0')
|
||||
return GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||||
{
|
||||
result = GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,7 +567,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
{
|
||||
int family = req->ai_family;
|
||||
size_t tmpbuflen = 512;
|
||||
char *tmpbuf = alloca (tmpbuflen);
|
||||
assert (tmpbuf == NULL);
|
||||
tmpbuf = alloca_account (tmpbuflen, alloca_used);
|
||||
int rc;
|
||||
struct hostent th;
|
||||
struct hostent *h;
|
||||
@ -529,50 +580,95 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
tmpbuflen, &h, &herrno);
|
||||
if (rc != ERANGE || herrno != NETDB_INTERNAL)
|
||||
break;
|
||||
tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
|
||||
|
||||
if (!malloc_tmpbuf
|
||||
&& __libc_use_alloca (alloca_used + 2 * tmpbuflen))
|
||||
tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
|
||||
2 * tmpbuflen,
|
||||
alloca_used);
|
||||
else
|
||||
{
|
||||
char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
|
||||
2 * tmpbuflen);
|
||||
if (newp == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
tmpbuf = newp;
|
||||
malloc_tmpbuf = true;
|
||||
tmpbuflen = 2 * tmpbuflen;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
if (h != NULL)
|
||||
/* We found data, now convert it into the list. */
|
||||
for (int i = 0; h->h_addr_list[i]; ++i)
|
||||
{
|
||||
if (*pat == NULL)
|
||||
{
|
||||
*pat = __alloca (sizeof (struct gaih_addrtuple));
|
||||
(*pat)->scopeid = 0;
|
||||
}
|
||||
(*pat)->next = NULL;
|
||||
(*pat)->family = req->ai_family;
|
||||
if (family == req->ai_family)
|
||||
memcpy ((*pat)->addr, h->h_addr_list[i],
|
||||
h->h_length);
|
||||
else
|
||||
{
|
||||
uint32_t *addr = (uint32_t *) (*pat)->addr;
|
||||
addr[3] = *(uint32_t *) h->h_addr_list[i];
|
||||
addr[2] = htonl (0xffff);
|
||||
addr[1] = 0;
|
||||
addr[0] = 0;
|
||||
}
|
||||
pat = &((*pat)->next);
|
||||
}
|
||||
{
|
||||
int i;
|
||||
/* We found data, count the number of addresses. */
|
||||
for (i = 0; h->h_addr_list[i]; ++i)
|
||||
;
|
||||
if (i > 0 && *pat != NULL)
|
||||
--i;
|
||||
|
||||
if (__libc_use_alloca (alloca_used
|
||||
+ i * sizeof (struct gaih_addrtuple)))
|
||||
addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
|
||||
alloca_used);
|
||||
else
|
||||
{
|
||||
addrmem = malloc (i
|
||||
* sizeof (struct gaih_addrtuple));
|
||||
if (addrmem == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
malloc_addrmem = true;
|
||||
}
|
||||
|
||||
/* Now convert it into the list. */
|
||||
struct gaih_addrtuple *addrfree = addrmem;
|
||||
for (i = 0; h->h_addr_list[i]; ++i)
|
||||
{
|
||||
if (*pat == NULL)
|
||||
{
|
||||
*pat = addrfree++;
|
||||
(*pat)->scopeid = 0;
|
||||
}
|
||||
(*pat)->next = NULL;
|
||||
(*pat)->family = req->ai_family;
|
||||
if (family == req->ai_family)
|
||||
memcpy ((*pat)->addr, h->h_addr_list[i],
|
||||
h->h_length);
|
||||
else
|
||||
{
|
||||
uint32_t *addr = (uint32_t *) (*pat)->addr;
|
||||
addr[3] = *(uint32_t *) h->h_addr_list[i];
|
||||
addr[2] = htonl (0xffff);
|
||||
addr[1] = 0;
|
||||
addr[0] = 0;
|
||||
}
|
||||
pat = &((*pat)->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (herrno == NETDB_INTERNAL)
|
||||
{
|
||||
__set_h_errno (herrno);
|
||||
return -EAI_SYSTEM;
|
||||
result = -EAI_SYSTEM;
|
||||
}
|
||||
if (herrno == TRY_AGAIN)
|
||||
{
|
||||
return -EAI_AGAIN;
|
||||
}
|
||||
/* We made requests but they turned out no data.
|
||||
The name is known, though. */
|
||||
return GAIH_OKIFUNSPEC | -EAI_NODATA;
|
||||
else if (herrno == TRY_AGAIN)
|
||||
result = -EAI_AGAIN;
|
||||
else
|
||||
/* We made requests but they turned out no data.
|
||||
The name is known, though. */
|
||||
result = GAIH_OKIFUNSPEC | -EAI_NODATA;
|
||||
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
goto process_list;
|
||||
@ -596,21 +692,56 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
|
||||
char *addrs = air->addrs;
|
||||
|
||||
if (__libc_use_alloca (alloca_used
|
||||
+ air->naddrs * sizeof (struct gaih_addrtuple)))
|
||||
addrmem = alloca_account (air->naddrs
|
||||
* sizeof (struct gaih_addrtuple),
|
||||
alloca_used);
|
||||
else
|
||||
{
|
||||
addrmem = malloc (air->naddrs
|
||||
* sizeof (struct gaih_addrtuple));
|
||||
if (addrmem == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
malloc_addrmem = true;
|
||||
}
|
||||
|
||||
struct gaih_addrtuple *addrfree = addrmem;
|
||||
for (int i = 0; i < air->naddrs; ++i)
|
||||
{
|
||||
socklen_t size = (air->family[i] == AF_INET
|
||||
? INADDRSZ : IN6ADDRSZ);
|
||||
if (*pat == NULL)
|
||||
{
|
||||
*pat = __alloca (sizeof (struct gaih_addrtuple));
|
||||
*pat = addrfree++;
|
||||
(*pat)->scopeid = 0;
|
||||
}
|
||||
uint32_t *pataddr = (*pat)->addr;
|
||||
(*pat)->next = NULL;
|
||||
if (added_canon || air->canon == NULL)
|
||||
(*pat)->name = NULL;
|
||||
else
|
||||
canon = (*pat)->name = strdupa (air->canon);
|
||||
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 = malloc (canonlen);
|
||||
if (canonbuf == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
malloc_canonbuf = true;
|
||||
}
|
||||
canon = (*pat)->name = memcpy (canonbuf, air->canon,
|
||||
canonlen);
|
||||
}
|
||||
|
||||
if (air->family[i] == AF_INET
|
||||
&& req->ai_family == AF_INET6
|
||||
@ -640,20 +771,26 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
free (air);
|
||||
|
||||
if (at->family == AF_UNSPEC)
|
||||
return GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||||
{
|
||||
result = GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
goto process_list;
|
||||
}
|
||||
else if (err == 0)
|
||||
/* The database contains a negative entry. */
|
||||
return 0;
|
||||
goto free_and_return;
|
||||
else if (__nss_not_use_nscd_hosts == 0)
|
||||
{
|
||||
if (herrno == NETDB_INTERNAL && errno == ENOMEM)
|
||||
return -EAI_MEMORY;
|
||||
if (herrno == TRY_AGAIN)
|
||||
return -EAI_AGAIN;
|
||||
return -EAI_SYSTEM;
|
||||
result = -EAI_MEMORY;
|
||||
else if (herrno == TRY_AGAIN)
|
||||
result = -EAI_AGAIN;
|
||||
else
|
||||
result = -EAI_SYSTEM;
|
||||
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -682,7 +819,19 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
_res.options &= ~RES_USE_INET6;
|
||||
|
||||
size_t tmpbuflen = 1024;
|
||||
char *tmpbuf = alloca (tmpbuflen);
|
||||
malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
|
||||
assert (tmpbuf == NULL);
|
||||
if (malloc_tmpbuf)
|
||||
tmpbuf = alloca_account (tmpbuflen, alloca_used);
|
||||
else
|
||||
{
|
||||
tmpbuf = malloc (tmpbuflen);
|
||||
if (tmpbuf == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
while (!no_more)
|
||||
{
|
||||
@ -711,8 +860,25 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
no_data = herrno == NO_DATA;
|
||||
break;
|
||||
}
|
||||
tmpbuf = extend_alloca (tmpbuf,
|
||||
tmpbuflen, 2 * tmpbuflen);
|
||||
|
||||
if (!malloc_tmpbuf
|
||||
&& __libc_use_alloca (alloca_used + 2 * tmpbuflen))
|
||||
tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
|
||||
2 * tmpbuflen,
|
||||
alloca_used);
|
||||
else
|
||||
{
|
||||
char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
|
||||
2 * tmpbuflen);
|
||||
if (newp == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
tmpbuf = newp;
|
||||
malloc_tmpbuf = true;
|
||||
tmpbuflen = 2 * tmpbuflen;
|
||||
}
|
||||
}
|
||||
|
||||
no_inet6_data = no_data;
|
||||
@ -787,18 +953,40 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if (cfct != NULL)
|
||||
{
|
||||
const size_t max_fqdn_len = 256;
|
||||
char *buf = alloca (max_fqdn_len);
|
||||
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)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
malloc_canonbuf = true;
|
||||
}
|
||||
char *s;
|
||||
|
||||
if (DL_CALL_FCT (cfct, (at->name ?: name,
|
||||
buf, max_fqdn_len,
|
||||
canonbuf,
|
||||
max_fqdn_len,
|
||||
&s, &rc, &herrno))
|
||||
== NSS_STATUS_SUCCESS)
|
||||
canon = s;
|
||||
else
|
||||
/* Set to name now to avoid using
|
||||
gethostbyaddr. */
|
||||
canon = name;
|
||||
{
|
||||
/* Set to name now to avoid using
|
||||
gethostbyaddr. */
|
||||
if (malloc_canonbuf)
|
||||
{
|
||||
free (canonbuf);
|
||||
malloc_canonbuf = false;
|
||||
}
|
||||
canon = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
status = NSS_STATUS_SUCCESS;
|
||||
@ -833,22 +1021,27 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
{
|
||||
/* If both requests timed out report this. */
|
||||
if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
|
||||
return -EAI_AGAIN;
|
||||
result = -EAI_AGAIN;
|
||||
else
|
||||
/* We made requests but they turned out no data. The name
|
||||
is known, though. */
|
||||
result = GAIH_OKIFUNSPEC | -EAI_NODATA;
|
||||
|
||||
/* We made requests but they turned out no data. The name
|
||||
is known, though. */
|
||||
return GAIH_OKIFUNSPEC | -EAI_NODATA;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
process_list:
|
||||
if (at->family == AF_UNSPEC)
|
||||
return GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||||
{
|
||||
result = GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct gaih_addrtuple *atr;
|
||||
atr = at = __alloca (sizeof (struct gaih_addrtuple));
|
||||
atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
|
||||
memset (at, '\0', sizeof (struct gaih_addrtuple));
|
||||
|
||||
if (req->ai_family == AF_UNSPEC)
|
||||
@ -887,30 +1080,56 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
/* Only the first entry gets the canonical name. */
|
||||
if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
|
||||
{
|
||||
char *tmpbuf2 = NULL;
|
||||
bool malloc_tmpbuf2 = false;
|
||||
|
||||
if (canon == NULL)
|
||||
{
|
||||
struct hostent *h = NULL;
|
||||
int herrno;
|
||||
struct hostent th;
|
||||
size_t tmpbuflen = 512;
|
||||
char *tmpbuf = NULL;
|
||||
size_t tmpbuf2len = 512;
|
||||
|
||||
do
|
||||
{
|
||||
tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
|
||||
if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
|
||||
tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
|
||||
tmpbuf2len * 2,
|
||||
alloca_used);
|
||||
else
|
||||
{
|
||||
char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
|
||||
2 * tmpbuf2len);
|
||||
if (newp == NULL)
|
||||
{
|
||||
if (malloc_tmpbuf2)
|
||||
free (tmpbuf2);
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
tmpbuf2 = newp;
|
||||
tmpbuf2len = 2 * tmpbuf2len;
|
||||
malloc_tmpbuf2 = true;
|
||||
}
|
||||
|
||||
rc = __gethostbyaddr_r (at2->addr,
|
||||
((at2->family == AF_INET6)
|
||||
? sizeof (struct in6_addr)
|
||||
: sizeof (struct in_addr)),
|
||||
at2->family, &th, tmpbuf,
|
||||
tmpbuflen, &h, &herrno);
|
||||
at2->family, &th, tmpbuf2,
|
||||
tmpbuf2len, &h, &herrno);
|
||||
}
|
||||
while (rc == ERANGE && herrno == NETDB_INTERNAL);
|
||||
|
||||
if (rc != 0 && herrno == NETDB_INTERNAL)
|
||||
{
|
||||
if (malloc_tmpbuf2)
|
||||
free (tmpbuf2);
|
||||
|
||||
__set_h_errno (herrno);
|
||||
return -EAI_SYSTEM;
|
||||
result = -EAI_SYSTEM;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (h != NULL)
|
||||
@ -937,11 +1156,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
|
||||
if (rc != IDNA_SUCCESS)
|
||||
{
|
||||
if (malloc_tmpbuf2)
|
||||
free (tmpbuf2);
|
||||
|
||||
if (rc == IDNA_MALLOC_ERROR)
|
||||
return -EAI_MEMORY;
|
||||
if (rc == IDNA_DLOPEN_ERROR)
|
||||
return -EAI_SYSTEM;
|
||||
return -EAI_IDN_ENCODE;
|
||||
result = -EAI_MEMORY;
|
||||
else if (rc == IDNA_DLOPEN_ERROR)
|
||||
result = -EAI_SYSTEM;
|
||||
else
|
||||
result = -EAI_IDN_ENCODE;
|
||||
goto free_and_return;
|
||||
}
|
||||
/* In case the output string is the same as the input
|
||||
string no new string has been allocated and we
|
||||
@ -956,10 +1180,25 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
#ifdef HAVE_LIBIDN
|
||||
make_copy:
|
||||
#endif
|
||||
canon = strdup (canon);
|
||||
if (canon == NULL)
|
||||
return -EAI_MEMORY;
|
||||
if (malloc_canonbuf)
|
||||
/* We already allocated the string using malloc. */
|
||||
malloc_canonbuf = false;
|
||||
else
|
||||
{
|
||||
canon = strdup (canon);
|
||||
if (canon == NULL)
|
||||
{
|
||||
if (malloc_tmpbuf2)
|
||||
free (tmpbuf2);
|
||||
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (malloc_tmpbuf2)
|
||||
free (tmpbuf2);
|
||||
}
|
||||
|
||||
family = at2->family;
|
||||
@ -985,7 +1224,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if (ai == NULL)
|
||||
{
|
||||
free ((char *) canon);
|
||||
return -EAI_MEMORY;
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
ai->ai_flags = req->ai_flags;
|
||||
@ -1038,7 +1278,18 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
at2 = at2->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
free_and_return:
|
||||
if (malloc_name)
|
||||
free ((char *) name);
|
||||
if (malloc_addrmem)
|
||||
free (addrmem);
|
||||
if (malloc_canonbuf)
|
||||
free (canonbuf);
|
||||
if (malloc_tmpbuf)
|
||||
free (tmpbuf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user