1 diff -rup a/include/alloca.h b/include/alloca.h
2 --- a/include/alloca.h 2012-02-29 13:11:19.439693476 -0700
3 +++ b/include/alloca.h 2012-02-29 13:11:49.832530623 -0700
4 @@ -49,15 +49,24 @@ libc_hidden_proto (__libc_alloca_cutoff)
6 #if defined stackinfo_get_sp && defined stackinfo_sub_sp
7 # define alloca_account(size, avar) \
8 - ({ void *old__ = stackinfo_get_sp (); \
9 - void *m__ = __alloca (size); \
10 - avar += stackinfo_sub_sp (old__); \
11 + ({ void *old__ = stackinfo_get_sp (); \
12 + void *m__ = __alloca (size); \
13 + avar += stackinfo_sub_sp (old__); \
15 +# define extend_alloca_account(buf, len, newlen, avar) \
16 + ({ void *old__ = stackinfo_get_sp (); \
17 + void *m__ = extend_alloca (buf, len, newlen); \
18 + avar += stackinfo_sub_sp (old__); \
21 # define alloca_account(size, avar) \
22 - ({ size_t s__ = (size); \
24 + ({ size_t s__ = (size); \
27 +# define extend_alloca_account(buf, len, newlen, avar) \
28 + ({ size_t s__ = (newlen); \
30 + extend_alloca (buf, len, s__); })
34 diff -rup a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
35 --- a/sysdeps/posix/getaddrinfo.c 2012-02-29 13:11:19.588692676 -0700
36 +++ b/sysdeps/posix/getaddrinfo.c 2012-02-29 13:12:42.972245862 -0700
37 @@ -278,6 +278,7 @@ gaih_inet (const char *name, const struc
38 bool got_ipv6 = false;
39 const char *canon = NULL;
40 const char *orig_name = name;
41 + size_t alloca_used = 0;
43 if (req->ai_protocol || req->ai_socktype)
45 @@ -310,7 +311,7 @@ gaih_inet (const char *name, const struc
48 st = (struct gaih_servtuple *)
49 - __alloca (sizeof (struct gaih_servtuple));
50 + alloca_account (sizeof (struct gaih_servtuple), alloca_used);
52 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
54 @@ -334,7 +335,8 @@ gaih_inet (const char *name, const struc
57 newp = (struct gaih_servtuple *)
58 - __alloca (sizeof (struct gaih_servtuple));
59 + alloca_account (sizeof (struct gaih_servtuple),
62 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
64 @@ -362,7 +364,7 @@ gaih_inet (const char *name, const struc
66 if (req->ai_socktype || req->ai_protocol)
68 - st = __alloca (sizeof (struct gaih_servtuple));
69 + st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
71 st->socktype = tp->socktype;
72 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
73 @@ -379,7 +381,8 @@ gaih_inet (const char *name, const struc
75 struct gaih_servtuple *newp;
77 - newp = __alloca (sizeof (struct gaih_servtuple));
78 + newp = alloca_account (sizeof (struct gaih_servtuple),
81 newp->socktype = tp->socktype;
82 newp->protocol = tp->protocol;
83 @@ -391,10 +394,17 @@ gaih_inet (const char *name, const struc
87 + bool malloc_name = false;
88 + bool malloc_addrmem = false;
89 + struct gaih_addrtuple *addrmem = NULL;
90 + bool malloc_canonbuf = false;
91 + char *canonbuf = NULL;
92 + bool malloc_tmpbuf = false;
93 + char *tmpbuf = NULL;
97 - at = __alloca (sizeof (struct gaih_addrtuple));
99 + at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
100 at->family = AF_UNSPEC;
103 @@ -412,6 +422,7 @@ gaih_inet (const char *name, const struc
104 rc = __idna_to_ascii_lz (name, &p, idn_flags);
105 if (rc != IDNA_SUCCESS)
107 + /* No need to jump to free_and_return here. */
108 if (rc == IDNA_MALLOC_ERROR)
110 if (rc == IDNA_DLOPEN_ERROR)
111 @@ -421,10 +432,7 @@ gaih_inet (const char *name, const struc
112 /* In case the output string is the same as the input string
113 no new string has been allocated. */
116 - name = strdupa (p);
119 + malloc_name = true;
123 @@ -441,23 +449,59 @@ gaih_inet (const char *name, const struc
124 at->family = AF_INET6;
127 - return -EAI_ADDRFAMILY;
129 + result = -EAI_ADDRFAMILY;
130 + goto free_and_return;
133 if (req->ai_flags & AI_CANONNAME)
136 else if (at->family == AF_UNSPEC)
138 - char *namebuf = (char *) name;
139 char *scope_delim = strchr (name, SCOPE_DELIMITER);
142 - if (__builtin_expect (scope_delim != NULL, 0))
144 - namebuf = alloca (scope_delim - name + 1);
145 - *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
148 + bool malloc_namebuf = false;
149 + char *namebuf = (char *) name;
151 + if (__builtin_expect (scope_delim != NULL, 0))
154 + *scope_delim = '\0';
157 + if (__libc_use_alloca (alloca_used
158 + + scope_delim - name + 1))
160 + namebuf = alloca_account (scope_delim - name + 1,
162 + *((char *) __mempcpy (namebuf, name,
163 + scope_delim - name)) = '\0';
167 + namebuf = strndup (name, scope_delim - name);
168 + if (namebuf == NULL)
170 + assert (!malloc_name);
171 + return -EAI_MEMORY;
173 + malloc_namebuf = true;
178 - if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
179 + e = inet_pton (AF_INET6, namebuf, at->addr);
181 + if (malloc_namebuf)
183 + else if (scope_delim != NULL && malloc_name)
184 + /* Undo what we did above. */
185 + *scope_delim = SCOPE_DELIMITER;
189 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
190 at->family = AF_INET6;
191 @@ -468,7 +512,10 @@ gaih_inet (const char *name, const struc
192 at->family = AF_INET;
195 - return -EAI_ADDRFAMILY;
197 + result = -EAI_ADDRFAMILY;
198 + goto free_and_return;
201 if (scope_delim != NULL)
203 @@ -490,7 +537,10 @@ gaih_inet (const char *name, const struc
204 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
207 - return GAIH_OKIFUNSPEC | -EAI_NONAME;
209 + result = GAIH_OKIFUNSPEC | -EAI_NONAME;
210 + goto free_and_return;
215 @@ -520,59 +570,80 @@ gaih_inet (const char *name, const struc
217 int family = req->ai_family;
218 size_t tmpbuflen = 512;
219 - char *tmpbuf = alloca (tmpbuflen);
220 + assert (tmpbuf == NULL);
221 + tmpbuf = alloca_account (tmpbuflen, alloca_used);
230 - rc = __gethostbyname2_r (name, family, &th, tmpbuf,
231 + rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
232 tmpbuflen, &h, &herrno);
233 if (rc != ERANGE || herrno != NETDB_INTERNAL)
235 - tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
238 + && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
239 + tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
244 + char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
248 + result = -EAI_MEMORY;
249 + goto free_and_return;
252 + malloc_tmpbuf = true;
253 + tmpbuflen = 2 * tmpbuflen;
262 - if (req->ai_family == AF_INET6
263 - && (req->ai_flags & AI_V4MAPPED)
264 - && family == AF_INET6)
266 + /* We found data, count the number of addresses. */
267 + for (i = 0; h->h_addr_list[i]; ++i)
269 + if (i > 0 && *pat != NULL)
272 + if (__libc_use_alloca (alloca_used
273 + + i * sizeof (struct gaih_addrtuple)))
274 + addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
278 - /* Try again, this time looking for IPv4
282 + addrmem = malloc (i
283 + * sizeof (struct gaih_addrtuple));
284 + if (addrmem == NULL)
286 + result = -EAI_MEMORY;
287 + goto free_and_return;
289 + malloc_addrmem = true;
293 - /* We found data, now convert it into the list. */
294 - for (int i = 0; h->h_addr_list[i]; ++i)
296 + /* Now convert it into the list. */
297 + struct gaih_addrtuple *addrfree = addrmem;
298 + for (i = 0; h->h_addr_list[i]; ++i)
302 - *pat = __alloca (sizeof (struct gaih_addrtuple));
307 - (*pat)->family = req->ai_family;
308 - if (family == req->ai_family)
309 + (*pat)->family = AF_INET;
310 memcpy ((*pat)->addr, h->h_addr_list[i],
314 - uint32_t *addr = (uint32_t *) (*pat)->addr;
315 - addr[3] = *(uint32_t *) h->h_addr_list[i];
316 - addr[2] = htonl (0xffff);
320 pat = &((*pat)->next);
323 @@ -582,15 +653,16 @@ gaih_inet (const char *name, const struc
324 if (herrno == NETDB_INTERNAL)
326 __set_h_errno (herrno);
327 - return -EAI_SYSTEM;
329 - if (herrno == TRY_AGAIN)
332 + result = -EAI_SYSTEM;
334 + else if (herrno == TRY_AGAIN)
335 + result = -EAI_AGAIN;
337 /* We made requests but they turned out no data.
338 The name is known, though. */
339 - return GAIH_OKIFUNSPEC | -EAI_NODATA;
340 + result = GAIH_OKIFUNSPEC | -EAI_NODATA;
342 + goto free_and_return;
346 @@ -613,21 +685,56 @@ gaih_inet (const char *name, const struc
347 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
348 char *addrs = air->addrs;
350 + if (__libc_use_alloca (alloca_used
351 + + air->naddrs * sizeof (struct gaih_addrtuple)))
352 + addrmem = alloca_account (air->naddrs
353 + * sizeof (struct gaih_addrtuple),
357 + addrmem = malloc (air->naddrs
358 + * sizeof (struct gaih_addrtuple));
359 + if (addrmem == NULL)
361 + result = -EAI_MEMORY;
362 + goto free_and_return;
364 + malloc_addrmem = true;
367 + struct gaih_addrtuple *addrfree = addrmem;
368 for (int i = 0; i < air->naddrs; ++i)
370 socklen_t size = (air->family[i] == AF_INET
371 ? INADDRSZ : IN6ADDRSZ);
374 - *pat = __alloca (sizeof (struct gaih_addrtuple));
378 uint32_t *pataddr = (*pat)->addr;
380 if (added_canon || air->canon == NULL)
383 - canon = (*pat)->name = strdupa (air->canon);
384 + else if (canonbuf == NULL)
386 + size_t canonlen = strlen (air->canon) + 1;
387 + if ((req->ai_flags & AI_CANONIDN) != 0
388 + && __libc_use_alloca (alloca_used + canonlen))
389 + canonbuf = alloca_account (canonlen, alloca_used);
392 + canonbuf = malloc (canonlen);
393 + if (canonbuf == NULL)
395 + result = -EAI_MEMORY;
396 + goto free_and_return;
398 + malloc_canonbuf = true;
400 + canon = (*pat)->name = memcpy (canonbuf, air->canon,
404 if (air->family[i] == AF_INET
405 && req->ai_family == AF_INET6
406 @@ -657,20 +764,26 @@ gaih_inet (const char *name, const struc
409 if (at->family == AF_UNSPEC)
410 - return GAIH_OKIFUNSPEC | -EAI_NONAME;
412 + result = GAIH_OKIFUNSPEC | -EAI_NONAME;
413 + goto free_and_return;
419 /* The database contains a negative entry. */
421 + goto free_and_return;
422 else if (__nss_not_use_nscd_hosts == 0)
424 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
425 - return -EAI_MEMORY;
426 - if (herrno == TRY_AGAIN)
428 - return -EAI_SYSTEM;
429 + result = -EAI_MEMORY;
430 + else if (herrno == TRY_AGAIN)
431 + result = -EAI_AGAIN;
433 + result = -EAI_SYSTEM;
435 + goto free_and_return;
439 @@ -699,7 +812,19 @@ gaih_inet (const char *name, const struc
440 _res.options &= ~RES_USE_INET6;
442 size_t tmpbuflen = 1024;
443 - char *tmpbuf = alloca (tmpbuflen);
444 + malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
445 + assert (tmpbuf == NULL);
446 + if (!malloc_tmpbuf)
447 + tmpbuf = alloca_account (tmpbuflen, alloca_used);
450 + tmpbuf = malloc (tmpbuflen);
451 + if (tmpbuf == NULL)
453 + result = -EAI_MEMORY;
454 + goto free_and_return;
460 @@ -728,8 +853,25 @@ gaih_inet (const char *name, const struc
461 no_data = herrno == NO_DATA;
464 - tmpbuf = extend_alloca (tmpbuf,
465 - tmpbuflen, 2 * tmpbuflen);
468 + && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
469 + tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
474 + char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
478 + result = -EAI_MEMORY;
479 + goto free_and_return;
482 + malloc_tmpbuf = true;
483 + tmpbuflen = 2 * tmpbuflen;
487 if (status == NSS_STATUS_SUCCESS)
488 @@ -832,18 +974,40 @@ gaih_inet (const char *name, const struc
491 const size_t max_fqdn_len = 256;
492 - char *buf = alloca (max_fqdn_len);
493 + if ((req->ai_flags & AI_CANONIDN) != 0
494 + && __libc_use_alloca (alloca_used
496 + canonbuf = alloca_account (max_fqdn_len,
500 + canonbuf = malloc (max_fqdn_len);
501 + if (canonbuf == NULL)
503 + result = -EAI_MEMORY;
504 + goto free_and_return;
506 + malloc_canonbuf = true;
510 if (DL_CALL_FCT (cfct, (at->name ?: name,
515 == NSS_STATUS_SUCCESS)
518 - /* Set to name now to avoid using
522 + /* Set to name now to avoid using
524 + if (malloc_canonbuf)
527 + malloc_canonbuf = false;
533 status = NSS_STATUS_SUCCESS;
534 @@ -878,22 +1042,27 @@ gaih_inet (const char *name, const struc
536 /* If both requests timed out report this. */
537 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
539 + result = -EAI_AGAIN;
541 + /* We made requests but they turned out no data. The name
542 + is known, though. */
543 + result = GAIH_OKIFUNSPEC | -EAI_NODATA;
545 - /* We made requests but they turned out no data. The name
546 - is known, though. */
547 - return GAIH_OKIFUNSPEC | -EAI_NODATA;
548 + goto free_and_return;
553 if (at->family == AF_UNSPEC)
554 - return GAIH_OKIFUNSPEC | -EAI_NONAME;
556 + result = GAIH_OKIFUNSPEC | -EAI_NONAME;
557 + goto free_and_return;
562 struct gaih_addrtuple *atr;
563 - atr = at = __alloca (sizeof (struct gaih_addrtuple));
564 + atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
565 memset (at, '\0', sizeof (struct gaih_addrtuple));
567 if (req->ai_family == AF_UNSPEC)
568 @@ -932,6 +1101,9 @@ gaih_inet (const char *name, const struc
569 /* Only the first entry gets the canonical name. */
570 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
572 + char *tmpbuf2 = NULL;
573 + bool malloc_tmpbuf2 = false;
577 /* If the canonical name cannot be determined, use
578 @@ -952,11 +1124,16 @@ gaih_inet (const char *name, const struc
579 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
580 if (rc != IDNA_SUCCESS)
582 + if (malloc_tmpbuf2)
585 if (rc == IDNA_MALLOC_ERROR)
586 - return -EAI_MEMORY;
587 - if (rc == IDNA_DLOPEN_ERROR)
588 - return -EAI_SYSTEM;
589 - return -EAI_IDN_ENCODE;
590 + result = -EAI_MEMORY;
591 + else if (rc == IDNA_DLOPEN_ERROR)
592 + result = -EAI_SYSTEM;
594 + result = -EAI_IDN_ENCODE;
595 + goto free_and_return;
597 /* In case the output string is the same as the input
598 string no new string has been allocated and we
599 @@ -970,10 +1147,25 @@ gaih_inet (const char *name, const struc
603 - canon = strdup (canon);
605 - return -EAI_MEMORY;
606 + if (malloc_canonbuf)
607 + /* We already allocated the string using malloc. */
608 + malloc_canonbuf = false;
611 + canon = strdup (canon);
614 + if (malloc_tmpbuf2)
617 + result = -EAI_MEMORY;
618 + goto free_and_return;
623 + if (malloc_tmpbuf2)
627 family = at2->family;
628 @@ -999,7 +1191,8 @@ gaih_inet (const char *name, const struc
631 free ((char *) canon);
632 - return -EAI_MEMORY;
633 + result = -EAI_MEMORY;
634 + goto free_and_return;
637 ai->ai_flags = req->ai_flags;
638 @@ -1052,7 +1245,18 @@ gaih_inet (const char *name, const struc
646 + free ((char *) name);
647 + if (malloc_addrmem)
649 + if (malloc_canonbuf)