]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/glibc/glibc-rh797094-1.patch
Merge remote-tracking branch 'origin/next' into thirteen
[people/teissler/ipfire-2.x.git] / src / patches / glibc / glibc-rh797094-1.patch
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)
5
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__); \
14 + m__; })
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__); \
19 m__; })
20 #else
21 # define alloca_account(size, avar) \
22 - ({ size_t s__ = (size); \
23 - avar += s__; \
24 + ({ size_t s__ = (size); \
25 + avar += s__; \
26 __alloca (s__); })
27 +# define extend_alloca_account(buf, len, newlen, avar) \
28 + ({ size_t s__ = (newlen); \
29 + avar += s__; \
30 + extend_alloca (buf, len, s__); })
31 #endif
32
33 #endif
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;
42
43 if (req->ai_protocol || req->ai_socktype)
44 {
45 @@ -310,7 +311,7 @@ gaih_inet (const char *name, const struc
46 if (tp->name[0])
47 {
48 st = (struct gaih_servtuple *)
49 - __alloca (sizeof (struct gaih_servtuple));
50 + alloca_account (sizeof (struct gaih_servtuple), alloca_used);
51
52 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
53 return rc;
54 @@ -334,7 +335,8 @@ gaih_inet (const char *name, const struc
55 continue;
56
57 newp = (struct gaih_servtuple *)
58 - __alloca (sizeof (struct gaih_servtuple));
59 + alloca_account (sizeof (struct gaih_servtuple),
60 + alloca_used);
61
62 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
63 {
64 @@ -362,7 +364,7 @@ gaih_inet (const char *name, const struc
65
66 if (req->ai_socktype || req->ai_protocol)
67 {
68 - st = __alloca (sizeof (struct gaih_servtuple));
69 + st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
70 st->next = NULL;
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
74 {
75 struct gaih_servtuple *newp;
76
77 - newp = __alloca (sizeof (struct gaih_servtuple));
78 + newp = alloca_account (sizeof (struct gaih_servtuple),
79 + alloca_used);
80 newp->next = NULL;
81 newp->socktype = tp->socktype;
82 newp->protocol = tp->protocol;
83 @@ -391,10 +394,17 @@ gaih_inet (const char *name, const struc
84 }
85 }
86
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;
94 + int result = 0;
95 if (name != NULL)
96 {
97 - at = __alloca (sizeof (struct gaih_addrtuple));
98 -
99 + at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
100 at->family = AF_UNSPEC;
101 at->scopeid = 0;
102 at->next = NULL;
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)
106 {
107 + /* No need to jump to free_and_return here. */
108 if (rc == IDNA_MALLOC_ERROR)
109 return -EAI_MEMORY;
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. */
114 if (p != name)
115 - {
116 - name = strdupa (p);
117 - free (p);
118 - }
119 + malloc_name = true;
120 }
121 #endif
122
123 @@ -441,23 +449,59 @@ gaih_inet (const char *name, const struc
124 at->family = AF_INET6;
125 }
126 else
127 - return -EAI_ADDRFAMILY;
128 + {
129 + result = -EAI_ADDRFAMILY;
130 + goto free_and_return;
131 + }
132
133 if (req->ai_flags & AI_CANONNAME)
134 canon = name;
135 }
136 else if (at->family == AF_UNSPEC)
137 {
138 - char *namebuf = (char *) name;
139 char *scope_delim = strchr (name, SCOPE_DELIMITER);
140 + int e;
141
142 - if (__builtin_expect (scope_delim != NULL, 0))
143 - {
144 - namebuf = alloca (scope_delim - name + 1);
145 - *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
146 - }
147 + {
148 + bool malloc_namebuf = false;
149 + char *namebuf = (char *) name;
150 +
151 + if (__builtin_expect (scope_delim != NULL, 0))
152 + {
153 + if (malloc_name)
154 + *scope_delim = '\0';
155 + else
156 + {
157 + if (__libc_use_alloca (alloca_used
158 + + scope_delim - name + 1))
159 + {
160 + namebuf = alloca_account (scope_delim - name + 1,
161 + alloca_used);
162 + *((char *) __mempcpy (namebuf, name,
163 + scope_delim - name)) = '\0';
164 + }
165 + else
166 + {
167 + namebuf = strndup (name, scope_delim - name);
168 + if (namebuf == NULL)
169 + {
170 + assert (!malloc_name);
171 + return -EAI_MEMORY;
172 + }
173 + malloc_namebuf = true;
174 + }
175 + }
176 + }
177
178 - if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
179 + e = inet_pton (AF_INET6, namebuf, at->addr);
180 +
181 + if (malloc_namebuf)
182 + free (namebuf);
183 + else if (scope_delim != NULL && malloc_name)
184 + /* Undo what we did above. */
185 + *scope_delim = SCOPE_DELIMITER;
186 + }
187 + if (e > 0)
188 {
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;
193 }
194 else
195 - return -EAI_ADDRFAMILY;
196 + {
197 + result = -EAI_ADDRFAMILY;
198 + goto free_and_return;
199 + }
200
201 if (scope_delim != NULL)
202 {
203 @@ -490,7 +537,10 @@ gaih_inet (const char *name, const struc
204 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
205 10);
206 if (*end != '\0')
207 - return GAIH_OKIFUNSPEC | -EAI_NONAME;
208 + {
209 + result = GAIH_OKIFUNSPEC | -EAI_NONAME;
210 + goto free_and_return;
211 + }
212 }
213 }
214
215 @@ -520,59 +570,80 @@ gaih_inet (const char *name, const struc
216 {
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);
222 int rc;
223 struct hostent th;
224 struct hostent *h;
225 int herrno;
226
227 - simple_again:
228 while (1)
229 {
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)
234 break;
235 - tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
236 +
237 + if (!malloc_tmpbuf
238 + && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
239 + tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
240 + 2 * tmpbuflen,
241 + alloca_used);
242 + else
243 + {
244 + char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
245 + 2 * tmpbuflen);
246 + if (newp == NULL)
247 + {
248 + result = -EAI_MEMORY;
249 + goto free_and_return;
250 + }
251 + tmpbuf = newp;
252 + malloc_tmpbuf = true;
253 + tmpbuflen = 2 * tmpbuflen;
254 + }
255 }
256
257 if (rc == 0)
258 {
259 - if (h == NULL)
260 + if (h != NULL)
261 {
262 - if (req->ai_family == AF_INET6
263 - && (req->ai_flags & AI_V4MAPPED)
264 - && family == AF_INET6)
265 + int i;
266 + /* We found data, count the number of addresses. */
267 + for (i = 0; h->h_addr_list[i]; ++i)
268 + ;
269 + if (i > 0 && *pat != NULL)
270 + --i;
271 +
272 + if (__libc_use_alloca (alloca_used
273 + + i * sizeof (struct gaih_addrtuple)))
274 + addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
275 + alloca_used);
276 + else
277 {
278 - /* Try again, this time looking for IPv4
279 - addresses. */
280 - family = AF_INET;
281 - goto simple_again;
282 + addrmem = malloc (i
283 + * sizeof (struct gaih_addrtuple));
284 + if (addrmem == NULL)
285 + {
286 + result = -EAI_MEMORY;
287 + goto free_and_return;
288 }
289 + malloc_addrmem = true;
290 }
291 - else
292 - {
293 - /* We found data, now convert it into the list. */
294 - for (int i = 0; h->h_addr_list[i]; ++i)
295 +
296 + /* Now convert it into the list. */
297 + struct gaih_addrtuple *addrfree = addrmem;
298 + for (i = 0; h->h_addr_list[i]; ++i)
299 {
300 if (*pat == NULL)
301 {
302 - *pat = __alloca (sizeof (struct gaih_addrtuple));
303 + *pat = addrfree++;
304 (*pat)->scopeid = 0;
305 }
306 (*pat)->next = NULL;
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],
311 h->h_length);
312 - else
313 - {
314 - uint32_t *addr = (uint32_t *) (*pat)->addr;
315 - addr[3] = *(uint32_t *) h->h_addr_list[i];
316 - addr[2] = htonl (0xffff);
317 - addr[1] = 0;
318 - addr[0] = 0;
319 - }
320 pat = &((*pat)->next);
321 }
322 }
323 @@ -582,15 +653,16 @@ gaih_inet (const char *name, const struc
324 if (herrno == NETDB_INTERNAL)
325 {
326 __set_h_errno (herrno);
327 - return -EAI_SYSTEM;
328 - }
329 - if (herrno == TRY_AGAIN)
330 - {
331 - return -EAI_AGAIN;
332 + result = -EAI_SYSTEM;
333 }
334 + else if (herrno == TRY_AGAIN)
335 + result = -EAI_AGAIN;
336 + else
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;
341 +
342 + goto free_and_return;
343 }
344
345 goto process_list;
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;
349
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),
354 + alloca_used);
355 + else
356 + {
357 + addrmem = malloc (air->naddrs
358 + * sizeof (struct gaih_addrtuple));
359 + if (addrmem == NULL)
360 + {
361 + result = -EAI_MEMORY;
362 + goto free_and_return;
363 + }
364 + malloc_addrmem = true;
365 + }
366 +
367 + struct gaih_addrtuple *addrfree = addrmem;
368 for (int i = 0; i < air->naddrs; ++i)
369 {
370 socklen_t size = (air->family[i] == AF_INET
371 ? INADDRSZ : IN6ADDRSZ);
372 if (*pat == NULL)
373 {
374 - *pat = __alloca (sizeof (struct gaih_addrtuple));
375 + *pat = addrfree++;
376 (*pat)->scopeid = 0;
377 }
378 uint32_t *pataddr = (*pat)->addr;
379 (*pat)->next = NULL;
380 if (added_canon || air->canon == NULL)
381 (*pat)->name = NULL;
382 - else
383 - canon = (*pat)->name = strdupa (air->canon);
384 + else if (canonbuf == NULL)
385 + {
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);
390 + else
391 + {
392 + canonbuf = malloc (canonlen);
393 + if (canonbuf == NULL)
394 + {
395 + result = -EAI_MEMORY;
396 + goto free_and_return;
397 + }
398 + malloc_canonbuf = true;
399 + }
400 + canon = (*pat)->name = memcpy (canonbuf, air->canon,
401 + canonlen);
402 + }
403
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
407 free (air);
408
409 if (at->family == AF_UNSPEC)
410 - return GAIH_OKIFUNSPEC | -EAI_NONAME;
411 + {
412 + result = GAIH_OKIFUNSPEC | -EAI_NONAME;
413 + goto free_and_return;
414 + }
415
416 goto process_list;
417 }
418 else if (err == 0)
419 /* The database contains a negative entry. */
420 - return 0;
421 + goto free_and_return;
422 else if (__nss_not_use_nscd_hosts == 0)
423 {
424 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
425 - return -EAI_MEMORY;
426 - if (herrno == TRY_AGAIN)
427 - return -EAI_AGAIN;
428 - return -EAI_SYSTEM;
429 + result = -EAI_MEMORY;
430 + else if (herrno == TRY_AGAIN)
431 + result = -EAI_AGAIN;
432 + else
433 + result = -EAI_SYSTEM;
434 +
435 + goto free_and_return;
436 }
437 }
438 #endif
439 @@ -699,7 +812,19 @@ gaih_inet (const char *name, const struc
440 _res.options &= ~RES_USE_INET6;
441
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);
448 + else
449 + {
450 + tmpbuf = malloc (tmpbuflen);
451 + if (tmpbuf == NULL)
452 + {
453 + result = -EAI_MEMORY;
454 + goto free_and_return;
455 + }
456 + }
457
458 while (!no_more)
459 {
460 @@ -728,8 +853,25 @@ gaih_inet (const char *name, const struc
461 no_data = herrno == NO_DATA;
462 break;
463 }
464 - tmpbuf = extend_alloca (tmpbuf,
465 - tmpbuflen, 2 * tmpbuflen);
466 +
467 + if (!malloc_tmpbuf
468 + && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
469 + tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
470 + 2 * tmpbuflen,
471 + alloca_used);
472 + else
473 + {
474 + char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
475 + 2 * tmpbuflen);
476 + if (newp == NULL)
477 + {
478 + result = -EAI_MEMORY;
479 + goto free_and_return;
480 + }
481 + tmpbuf = newp;
482 + malloc_tmpbuf = true;
483 + tmpbuflen = 2 * tmpbuflen;
484 + }
485 }
486
487 if (status == NSS_STATUS_SUCCESS)
488 @@ -832,18 +974,40 @@ gaih_inet (const char *name, const struc
489 if (cfct != NULL)
490 {
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
495 + + max_fqdn_len))
496 + canonbuf = alloca_account (max_fqdn_len,
497 + alloca_used);
498 + else
499 + {
500 + canonbuf = malloc (max_fqdn_len);
501 + if (canonbuf == NULL)
502 + {
503 + result = -EAI_MEMORY;
504 + goto free_and_return;
505 + }
506 + malloc_canonbuf = true;
507 + }
508 char *s;
509
510 if (DL_CALL_FCT (cfct, (at->name ?: name,
511 - buf, max_fqdn_len,
512 + canonbuf,
513 + max_fqdn_len,
514 &s, &rc, &herrno))
515 == NSS_STATUS_SUCCESS)
516 canon = s;
517 else
518 - /* Set to name now to avoid using
519 - gethostbyaddr. */
520 - canon = name;
521 + {
522 + /* Set to name now to avoid using
523 + gethostbyaddr. */
524 + if (malloc_canonbuf)
525 + {
526 + free (canonbuf);
527 + malloc_canonbuf = false;
528 + }
529 + canon = name;
530 + }
531 }
532 }
533 status = NSS_STATUS_SUCCESS;
534 @@ -878,22 +1042,27 @@ gaih_inet (const char *name, const struc
535 {
536 /* If both requests timed out report this. */
537 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
538 - return -EAI_AGAIN;
539 + result = -EAI_AGAIN;
540 + else
541 + /* We made requests but they turned out no data. The name
542 + is known, though. */
543 + result = GAIH_OKIFUNSPEC | -EAI_NODATA;
544
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;
549 }
550 }
551
552 process_list:
553 if (at->family == AF_UNSPEC)
554 - return GAIH_OKIFUNSPEC | -EAI_NONAME;
555 + {
556 + result = GAIH_OKIFUNSPEC | -EAI_NONAME;
557 + goto free_and_return;
558 + }
559 }
560 else
561 {
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));
566
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)
571 {
572 + char *tmpbuf2 = NULL;
573 + bool malloc_tmpbuf2 = false;
574 +
575 if (canon == NULL)
576 {
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)
581 {
582 + if (malloc_tmpbuf2)
583 + free (tmpbuf2);
584 +
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;
593 + else
594 + result = -EAI_IDN_ENCODE;
595 + goto free_and_return;
596 }
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
600 #ifdef HAVE_LIBIDN
601 make_copy:
602 #endif
603 - canon = strdup (canon);
604 - if (canon == NULL)
605 - return -EAI_MEMORY;
606 + if (malloc_canonbuf)
607 + /* We already allocated the string using malloc. */
608 + malloc_canonbuf = false;
609 + else
610 + {
611 + canon = strdup (canon);
612 + if (canon == NULL)
613 + {
614 + if (malloc_tmpbuf2)
615 + free (tmpbuf2);
616 +
617 + result = -EAI_MEMORY;
618 + goto free_and_return;
619 + }
620 + }
621 }
622 +
623 + if (malloc_tmpbuf2)
624 + free (tmpbuf2);
625 }
626
627 family = at2->family;
628 @@ -999,7 +1191,8 @@ gaih_inet (const char *name, const struc
629 if (ai == NULL)
630 {
631 free ((char *) canon);
632 - return -EAI_MEMORY;
633 + result = -EAI_MEMORY;
634 + goto free_and_return;
635 }
636
637 ai->ai_flags = req->ai_flags;
638 @@ -1052,7 +1245,18 @@ gaih_inet (const char *name, const struc
639 at2 = at2->next;
640 }
641 }
642 - return 0;
643 +
644 + free_and_return:
645 + if (malloc_name)
646 + free ((char *) name);
647 + if (malloc_addrmem)
648 + free (addrmem);
649 + if (malloc_canonbuf)
650 + free (canonbuf);
651 + if (malloc_tmpbuf)
652 + free (tmpbuf);
653 +
654 + return result;
655 }
656
657