~ubuntu-branches/ubuntu/lucid/eglibc/lucid-security

« back to all changes in this revision

Viewing changes to debian/patches/any/CVE-2013-4357.diff

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2014-07-28 11:23:55 UTC
  • Revision ID: package-import@ubuntu.com-20140728112355-d1m3idnt2n38dzj1
Tags: 2.11.1-0ubuntu7.14
* SECURITY UPDATE: denial of service via buffer overflow in getaddrinfo
  - debian/patches/CVE-2013-4357.patch: fix overflow in include/alloca.h,
    nis/nss_nis/nis-alias.c, nscd/nscd_getserv_r.c, posix/glob.c,
    sysdeps/posix/getaddrinfo.c.
  - CVE-2013-4357
* SECURITY UPDATE: denial of service via buffer overflow in getaddrinfo
  - debian/patches/any/CVE-2013-4458.patch: fix overflow in
    sysdeps/posix/getaddrinfo.c.
  - CVE-2013-4458
* SECURITY UPDATE: Directory traversal in locale environment handling
  - debian/patches/any/CVE-2014-0475.diff: validate locale names in
    locale/findlocale.c, locale/setlocale.c, added test to
    localedata/tst-setlocale3.c, localedata/Makefile.
  - CVE-2014-0475
* SECURITY UPDATE: use-after-free via posix_spawn_file_actions_addopen
  failing to copy the path argument
  - debian/patches/any/CVE-2014-4043.diff: properly copy path in
    posix/spawn_faction_addopen.c, posix/spawn_faction_destroy.c,
    posix/spawn_int.h, added test to posix/tst-spawn.c.
  - CVE-2014-4043
* debian/patches/any/CVE-2013-4237-part2.diff: fix alignment issue
  causing a readdir regression on sparc.
* debian/patches/any/CVE-2013-4332-part2.diff: added a couple of extra
  commits to fix another overflow and an infinite loop.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Description: fix denial of service via buffer overflow in getaddrinfo
 
2
Origin: backport, https://sourceware.org/git/?p=glibc.git;h=f2962a71959fd254a7a223437ca4b63b9e81130c
 
3
Origin: backport, https://sourceware.org/git/?p=glibc.git;h=34a9094f49241ebb72084c536cf468fd51ebe3ec
 
4
Bug: http://sourceware.org/bugzilla/show_bug.cgi?id=12671
 
5
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=742925
 
6
 
 
7
Index: eglibc-2.11.1/include/alloca.h
 
8
===================================================================
 
9
--- eglibc-2.11.1.orig/include/alloca.h 2014-07-28 11:18:56.773591507 -0400
 
10
+++ eglibc-2.11.1/include/alloca.h      2014-07-28 11:18:56.765591507 -0400
 
11
@@ -49,15 +49,24 @@
 
12
 
 
13
 #if defined stackinfo_get_sp && defined stackinfo_sub_sp
 
14
 # define alloca_account(size, avar) \
 
15
-  ({ void *old__ = stackinfo_get_sp ();                        \
 
16
-     void *m__ = __alloca (size);                      \
 
17
-     avar += stackinfo_sub_sp (old__);                 \
 
18
+  ({ void *old__ = stackinfo_get_sp ();                                              \
 
19
+     void *m__ = __alloca (size);                                            \
 
20
+     avar += stackinfo_sub_sp (old__);                                       \
 
21
+     m__; })
 
22
+# define extend_alloca_account(buf, len, newlen, avar) \
 
23
+  ({ void *old__ = stackinfo_get_sp ();                                              \
 
24
+     void *m__ = extend_alloca (buf, len, newlen);                           \
 
25
+     avar += stackinfo_sub_sp (old__);                                       \
 
26
      m__; })
 
27
 #else
 
28
 # define alloca_account(size, avar) \
 
29
-  ({ size_t s__ = (size);                  \
 
30
-     avar += s__;                          \
 
31
+  ({ size_t s__ = (size);                                                    \
 
32
+     avar += s__;                                                            \
 
33
      __alloca (s__); })
 
34
+# define extend_alloca_account(buf, len, newlen, avar) \
 
35
+  ({ size_t s__ = (newlen);                                                  \
 
36
+     avar += s__;                                                            \
 
37
+     extend_alloca (buf, len, s__); })
 
38
 #endif
 
39
 
 
40
 #endif
 
41
Index: eglibc-2.11.1/nis/nss_nis/nis-alias.c
 
42
===================================================================
 
43
--- eglibc-2.11.1.orig/nis/nss_nis/nis-alias.c  2014-07-28 11:18:56.773591507 -0400
 
44
+++ eglibc-2.11.1/nis/nss_nis/nis-alias.c       2014-07-28 11:18:56.765591507 -0400
 
45
@@ -142,10 +142,10 @@
 
46
       int yperr;
 
47
 
 
48
       if (new_start)
 
49
-        yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
 
50
+       yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
 
51
                          &len);
 
52
       else
 
53
-        yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
 
54
+       yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
 
55
                         &keylen, &result, &len);
 
56
 
 
57
       if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
 
58
@@ -153,20 +153,20 @@
 
59
          enum nss_status retval = yperr2nss (yperr);
 
60
 
 
61
          if (retval == NSS_STATUS_TRYAGAIN)
 
62
-            *errnop = errno;
 
63
-          return retval;
 
64
-        }
 
65
+           *errnop = errno;
 
66
+         return retval;
 
67
+       }
 
68
 
 
69
       if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
 
70
-        {
 
71
+       {
 
72
          free (result);
 
73
-          *errnop = ERANGE;
 
74
-          return NSS_STATUS_TRYAGAIN;
 
75
-        }
 
76
+         *errnop = ERANGE;
 
77
+         return NSS_STATUS_TRYAGAIN;
 
78
+       }
 
79
       char *p = strncpy (buffer, result, len);
 
80
       buffer[len] = '\0';
 
81
       while (isspace (*p))
 
82
-        ++p;
 
83
+       ++p;
 
84
       free (result);
 
85
 
 
86
       parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer,
 
87
@@ -213,13 +213,25 @@
 
88
       return NSS_STATUS_UNAVAIL;
 
89
     }
 
90
 
 
91
-  size_t namlen = strlen (name);
 
92
-  char name2[namlen + 1];
 
93
-
 
94
   char *domain;
 
95
   if (__builtin_expect (yp_get_default_domain (&domain), 0))
 
96
     return NSS_STATUS_UNAVAIL;
 
97
 
 
98
+  size_t namlen = strlen (name);
 
99
+  char *name2;
 
100
+  int use_alloca = __libc_use_alloca (namlen + 1);
 
101
+  if (use_alloca)
 
102
+    name2 = __alloca (namlen + 1);
 
103
+  else
 
104
+    {
 
105
+      name2 = malloc (namlen + 1);
 
106
+      if (name2 == NULL)
 
107
+       {
 
108
+         *errnop = ENOMEM;
 
109
+         return NSS_STATUS_TRYAGAIN;
 
110
+       }
 
111
+    }
 
112
+
 
113
   /* Convert name to lowercase.  */
 
114
   size_t i;
 
115
   for (i = 0; i < namlen; ++i)
 
116
@@ -230,6 +242,9 @@
 
117
   int len;
 
118
   int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len);
 
119
 
 
120
+  if (!use_alloca)
 
121
+    free (name2);
 
122
+
 
123
   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
 
124
     {
 
125
       enum nss_status retval = yperr2nss (yperr);
 
126
Index: eglibc-2.11.1/nscd/nscd_getserv_r.c
 
127
===================================================================
 
128
--- eglibc-2.11.1.orig/nscd/nscd_getserv_r.c    2014-07-28 11:18:56.773591507 -0400
 
129
+++ eglibc-2.11.1/nscd/nscd_getserv_r.c 2014-07-28 11:18:56.765591507 -0400
 
130
@@ -17,6 +17,7 @@
 
131
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
132
    02111-1307 USA.  */
 
133
 
 
134
+#include <assert.h>
 
135
 #include <errno.h>
 
136
 #include <string.h>
 
137
 #include <not-cancel.h>
 
138
@@ -80,6 +81,7 @@
 
139
 {
 
140
   int gc_cycle;
 
141
   int nretries = 0;
 
142
+  size_t alloca_used = 0;
 
143
 
 
144
   /* If the mapping is available, try to search there instead of
 
145
      communicating with the nscd.  */
 
146
@@ -88,13 +90,23 @@
 
147
                               &gc_cycle);
 
148
   size_t protolen = proto == NULL ? 0 : strlen (proto);
 
149
   size_t keylen = critlen + 1 + protolen + 1;
 
150
-  char *key = alloca (keylen);
 
151
+  int alloca_key = __libc_use_alloca (keylen);
 
152
+  char *key;
 
153
+  if (alloca_key)
 
154
+    key = alloca_account (keylen, alloca_used);
 
155
+  else
 
156
+    {
 
157
+      key = malloc (keylen);
 
158
+      if (key == NULL)
 
159
+       return -1;
 
160
+    }
 
161
   memcpy (__mempcpy (__mempcpy (key, crit, critlen),
 
162
                     "/", 1), proto ?: "", protolen + 1);
 
163
 
 
164
  retry:;
 
165
   const char *s_name = NULL;
 
166
   const char *s_proto = NULL;
 
167
+  int alloca_aliases_len = 0;
 
168
   const uint32_t *aliases_len = NULL;
 
169
   const char *aliases_list = NULL;
 
170
   int retval = -1;
 
171
@@ -136,8 +148,22 @@
 
172
          if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
 
173
              != 0)
 
174
            {
 
175
-             uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
 
176
-                                     * sizeof (uint32_t));
 
177
+             uint32_t *tmp;
 
178
+             alloca_aliases_len
 
179
+               = __libc_use_alloca (alloca_used
 
180
+                                    + (serv_resp.s_aliases_cnt
 
181
+                                       * sizeof (uint32_t)));
 
182
+             if (alloca_aliases_len)
 
183
+               tmp = __alloca (serv_resp.s_aliases_cnt * sizeof (uint32_t));
 
184
+             else
 
185
+               {
 
186
+                 tmp = malloc (serv_resp.s_aliases_cnt * sizeof (uint32_t));
 
187
+                 if (tmp == NULL)
 
188
+                   {
 
189
+                     retval = ENOMEM;
 
190
+                     goto out;
 
191
+                   }
 
192
+               }
 
193
              aliases_len = memcpy (tmp, aliases_len,
 
194
                                    serv_resp.s_aliases_cnt
 
195
                                    * sizeof (uint32_t));
 
196
@@ -217,8 +243,24 @@
 
197
 
 
198
          if (serv_resp.s_aliases_cnt > 0)
 
199
            {
 
200
-             aliases_len = alloca (serv_resp.s_aliases_cnt
 
201
-                                   * sizeof (uint32_t));
 
202
+             assert (alloca_aliases_len == 0);
 
203
+             alloca_aliases_len
 
204
+               = __libc_use_alloca (alloca_used
 
205
+                                    + (serv_resp.s_aliases_cnt
 
206
+                                       * sizeof (uint32_t)));
 
207
+             if (alloca_aliases_len)
 
208
+               aliases_len = alloca (serv_resp.s_aliases_cnt
 
209
+                                     * sizeof (uint32_t));
 
210
+             else
 
211
+               {
 
212
+                 aliases_len = malloc (serv_resp.s_aliases_cnt
 
213
+                                       * sizeof (uint32_t));
 
214
+                 if (aliases_len == NULL)
 
215
+                   {
 
216
+                     retval = ENOMEM;
 
217
+                     goto out_close;
 
218
+                   }
 
219
+               }
 
220
              vec[n].iov_base = (void *) aliases_len;
 
221
              vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
 
222
 
 
223
@@ -329,5 +371,10 @@
 
224
        goto retry;
 
225
     }
 
226
 
 
227
+  if (!alloca_aliases_len)
 
228
+    free ((void *) aliases_len);
 
229
+  if (!alloca_key)
 
230
+    free (key);
 
231
+
 
232
   return retval;
 
233
 }
 
234
Index: eglibc-2.11.1/posix/glob.c
 
235
===================================================================
 
236
--- eglibc-2.11.1.orig/posix/glob.c     2014-07-28 11:18:56.773591507 -0400
 
237
+++ eglibc-2.11.1/posix/glob.c  2014-07-28 11:18:56.769591507 -0400
 
238
@@ -202,7 +202,7 @@
 
239
 
 
240
 static int glob_in_dir (const char *pattern, const char *directory,
 
241
                        int flags, int (*errfunc) (const char *, int),
 
242
-                       glob_t *pglob);
 
243
+                       glob_t *pglob, size_t alloca_used);
 
244
 extern int __glob_pattern_type (const char *pattern, int quote)
 
245
     attribute_hidden;
 
246
 
 
247
@@ -256,13 +256,18 @@
 
248
      glob_t *pglob;
 
249
 {
 
250
   const char *filename;
 
251
-  const char *dirname;
 
252
+  char *dirname = NULL;
 
253
   size_t dirlen;
 
254
   int status;
 
255
   size_t oldcount;
 
256
   int meta;
 
257
   int dirname_modified;
 
258
+  int malloc_dirname = 0;
 
259
   glob_t dirs;
 
260
+  int retval = 0;
 
261
+#ifdef _LIBC
 
262
+  size_t alloca_used = 0;
 
263
+#endif
 
264
 
 
265
   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
 
266
     {
 
267
@@ -311,20 +316,26 @@
 
268
          const char *next;
 
269
          const char *rest;
 
270
          size_t rest_len;
 
271
-#ifdef __GNUC__
 
272
-         char onealt[strlen (pattern) - 1];
 
273
-#else
 
274
-         char *onealt = (char *) malloc (strlen (pattern) - 1);
 
275
-         if (onealt == NULL)
 
276
+         char *onealt;
 
277
+         size_t pattern_len = strlen (pattern) - 1;
 
278
+#ifdef _LIBC
 
279
+         int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len);
 
280
+         if (alloca_onealt)
 
281
+           onealt = alloca_account (pattern_len, alloca_used);
 
282
+         else
 
283
+#endif
 
284
            {
 
285
-             if (!(flags & GLOB_APPEND))
 
286
+             onealt = (char *) malloc (pattern_len);
 
287
+             if (onealt == NULL)
 
288
                {
 
289
-                 pglob->gl_pathc = 0;
 
290
-                 pglob->gl_pathv = NULL;
 
291
+                 if (!(flags & GLOB_APPEND))
 
292
+                   {
 
293
+                     pglob->gl_pathc = 0;
 
294
+                     pglob->gl_pathv = NULL;
 
295
+                   }
 
296
+                 return GLOB_NOSPACE;
 
297
                }
 
298
-             return GLOB_NOSPACE;
 
299
            }
 
300
-#endif
 
301
 
 
302
          /* We know the prefix for all sub-patterns.  */
 
303
          alt_start = mempcpy (onealt, pattern, begin - pattern);
 
304
@@ -335,9 +346,11 @@
 
305
          if (next == NULL)
 
306
            {
 
307
              /* It is an illegal expression.  */
 
308
-#ifndef __GNUC__
 
309
-             free (onealt);
 
310
+           illegal_brace:
 
311
+#ifdef _LIBC
 
312
+             if (__builtin_expect (!alloca_onealt, 0))
 
313
 #endif
 
314
+               free (onealt);
 
315
              return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
 
316
            }
 
317
 
 
318
@@ -347,13 +360,8 @@
 
319
            {
 
320
              rest = next_brace_sub (rest + 1, flags);
 
321
              if (rest == NULL)
 
322
-               {
 
323
-                 /* It is an illegal expression.  */
 
324
-#ifndef __GNUC__
 
325
-                 free (onealt);
 
326
-#endif
 
327
-                 return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
 
328
-               }
 
329
+               /* It is an illegal expression.  */
 
330
+               goto illegal_brace;
 
331
            }
 
332
          /* Please note that we now can be sure the brace expression
 
333
             is well-formed.  */
 
334
@@ -389,9 +397,10 @@
 
335
              /* If we got an error, return it.  */
 
336
              if (result && result != GLOB_NOMATCH)
 
337
                {
 
338
-#ifndef __GNUC__
 
339
-                 free (onealt);
 
340
+#ifdef _LIBC
 
341
+                 if (__builtin_expect (!alloca_onealt, 0))
 
342
 #endif
 
343
+                   free (onealt);
 
344
                  if (!(flags & GLOB_APPEND))
 
345
                    {
 
346
                      globfree (pglob);
 
347
@@ -409,9 +418,10 @@
 
348
              assert (next != NULL);
 
349
            }
 
350
 
 
351
-#ifndef __GNUC__
 
352
-         free (onealt);
 
353
+#ifdef _LIBC
 
354
+         if (__builtin_expect (!alloca_onealt, 0))
 
355
 #endif
 
356
+           free (onealt);
 
357
 
 
358
          if (pglob->gl_pathc != firstc)
 
359
            /* We found some entries.  */
 
360
@@ -438,7 +448,7 @@
 
361
         case is nothing but a notation for a directory.  */
 
362
       if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~')
 
363
        {
 
364
-         dirname = pattern;
 
365
+         dirname = (char *) pattern;
 
366
          dirlen = strlen (pattern);
 
367
 
 
368
          /* Set FILENAME to NULL as a special flag.  This is ugly but
 
369
@@ -450,9 +460,9 @@
 
370
        {
 
371
          filename = pattern;
 
372
 #ifdef _AMIGA
 
373
-         dirname = "";
 
374
+         dirname = (char *) "";
 
375
 #else
 
376
-         dirname = ".";
 
377
+         dirname = (char *) ".";
 
378
 #endif
 
379
          dirlen = 0;
 
380
        }
 
381
@@ -462,7 +472,7 @@
 
382
               && (flags & GLOB_NOESCAPE) == 0))
 
383
     {
 
384
       /* "/pattern" or "\\/pattern".  */
 
385
-      dirname = "/";
 
386
+      dirname = (char *) "/";
 
387
       dirlen = 1;
 
388
       ++filename;
 
389
     }
 
390
@@ -488,7 +498,17 @@
 
391
             from "d:/", since "d:" and "d:/" are not the same.*/
 
392
        }
 
393
 #endif
 
394
-      newp = (char *) __alloca (dirlen + 1);
 
395
+#ifdef _LIBC
 
396
+      if (__libc_use_alloca (alloca_used + dirlen + 1))
 
397
+       newp = alloca_account (dirlen + 1, alloca_used);
 
398
+      else
 
399
+#endif
 
400
+       {
 
401
+         newp = malloc (dirlen + 1);
 
402
+         if (newp == NULL)
 
403
+           return GLOB_NOSPACE;
 
404
+         malloc_dirname = 1;
 
405
+       }
 
406
       *((char *) mempcpy (newp, pattern, dirlen)) = '\0';
 
407
       dirname = newp;
 
408
       ++filename;
 
409
@@ -528,7 +548,8 @@
 
410
              oldcount = pglob->gl_pathc + pglob->gl_offs;
 
411
              goto no_matches;
 
412
            }
 
413
-         return val;
 
414
+         retval = val;
 
415
+         goto out;
 
416
        }
 
417
     }
 
418
 
 
419
@@ -560,7 +581,8 @@
 
420
              && (dirname[2] == '\0' || dirname[2] == '/')))
 
421
        {
 
422
          /* Look up home directory.  */
 
423
-         const char *home_dir = getenv ("HOME");
 
424
+         char *home_dir = getenv ("HOME");
 
425
+         int malloc_home_dir = 0;
 
426
 # ifdef _AMIGA
 
427
          if (home_dir == NULL || home_dir[0] == '\0')
 
428
            home_dir = "SYS:";
 
429
@@ -580,7 +602,7 @@
 
430
                /* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
 
431
                   a moderate value.  */
 
432
                buflen = 20;
 
433
-             name = (char *) __alloca (buflen);
 
434
+             name = alloca_account (buflen, alloca_used);
 
435
 
 
436
              success = getlogin_r (name, buflen) == 0;
 
437
              if (success)
 
438
@@ -590,6 +612,7 @@
 
439
                  long int pwbuflen = GETPW_R_SIZE_MAX ();
 
440
                  char *pwtmpbuf;
 
441
                  struct passwd pwbuf;
 
442
+                 int malloc_pwtmpbuf = 0;
 
443
                  int save = errno;
 
444
 
 
445
 #     ifndef _LIBC
 
446
@@ -598,7 +621,18 @@
 
447
                       Try a moderate value.  */
 
448
                    pwbuflen = 1024;
 
449
 #     endif
 
450
-                 pwtmpbuf = (char *) __alloca (pwbuflen);
 
451
+                 if (__libc_use_alloca (alloca_used + pwbuflen))
 
452
+                   pwtmpbuf = alloca_account (pwbuflen, alloca_used);
 
453
+                 else
 
454
+                   {
 
455
+                     pwtmpbuf = malloc (pwbuflen);
 
456
+                     if (pwtmpbuf == NULL)
 
457
+                       {
 
458
+                         retval = GLOB_NOSPACE;
 
459
+                         goto out;
 
460
+                       }
 
461
+                     malloc_pwtmpbuf = 1;
 
462
+                   }
 
463
 
 
464
                  while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p)
 
465
                         != 0)
 
466
@@ -608,47 +642,116 @@
 
467
                          p = NULL;
 
468
                          break;
 
469
                        }
 
470
-#     ifdef _LIBC
 
471
-                     pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen,
 
472
+
 
473
+                     if (!malloc_pwtmpbuf
 
474
+                         && __libc_use_alloca (alloca_used
 
475
+                                               + 2 * pwbuflen))
 
476
+                       pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen,
 
477
+                                                         2 * pwbuflen,
 
478
+                                                         alloca_used);
 
479
+                     else
 
480
+                       {
 
481
+                         char *newp = realloc (malloc_pwtmpbuf
 
482
+                                               ? pwtmpbuf : NULL,
 
483
                                                2 * pwbuflen);
 
484
-#     else
 
485
-                     pwbuflen *= 2;
 
486
-                     pwtmpbuf = (char *) __alloca (pwbuflen);
 
487
-#     endif
 
488
+                         if (newp == NULL)
 
489
+                           {
 
490
+                             if (__builtin_expect (malloc_pwtmpbuf, 0))
 
491
+                               free (pwtmpbuf);
 
492
+                             retval = GLOB_NOSPACE;
 
493
+                             goto out;
 
494
+                           }
 
495
+                         pwtmpbuf = newp;
 
496
+                         pwbuflen = 2 * pwbuflen;
 
497
+                         malloc_pwtmpbuf = 1;
 
498
+                       }
 
499
                      __set_errno (save);
 
500
                    }
 
501
 #    else
 
502
                  p = getpwnam (name);
 
503
 #    endif
 
504
                  if (p != NULL)
 
505
-                   home_dir = p->pw_dir;
 
506
+                   {
 
507
+                     if (!malloc_pwtmpbuf)
 
508
+                       home_dir = p->pw_dir;
 
509
+                     else
 
510
+                       {
 
511
+                         size_t home_dir_len = strlen (p->pw_dir) + 1;
 
512
+                         if (__libc_use_alloca (alloca_used + home_dir_len))
 
513
+                           home_dir = alloca_account (home_dir_len,
 
514
+                                                      alloca_used);
 
515
+                         else
 
516
+                           {
 
517
+                             home_dir = malloc (home_dir_len);
 
518
+                             if (home_dir == NULL)
 
519
+                               {
 
520
+                                 free (pwtmpbuf);
 
521
+                                 retval = GLOB_NOSPACE;
 
522
+                                 goto out;
 
523
+                               }
 
524
+                             malloc_home_dir = 1;
 
525
+                           }
 
526
+                         memcpy (home_dir, p->pw_dir, home_dir_len);
 
527
+
 
528
+                         free (pwtmpbuf);
 
529
+                       }
 
530
+                   }
 
531
                }
 
532
            }
 
533
 #   endif /* ! _LIBC || __OPTION_EGLIBC_GETLOGIN */
 
534
          if (home_dir == NULL || home_dir[0] == '\0')
 
535
            {
 
536
              if (flags & GLOB_TILDE_CHECK)
 
537
-               return GLOB_NOMATCH;
 
538
+               {
 
539
+                 if (__builtin_expect (malloc_home_dir, 0))
 
540
+                   free (home_dir);
 
541
+                 retval = GLOB_NOMATCH;
 
542
+                 goto out;
 
543
+               }
 
544
              else
 
545
-               home_dir = "~"; /* No luck.  */
 
546
+               home_dir = (char *) "~"; /* No luck.  */
 
547
            }
 
548
 #  endif /* WINDOWS32 */
 
549
 # endif
 
550
          /* Now construct the full directory.  */
 
551
          if (dirname[1] == '\0')
 
552
            {
 
553
+             if (__builtin_expect (malloc_dirname, 0))
 
554
+               free (dirname);
 
555
+
 
556
              dirname = home_dir;
 
557
              dirlen = strlen (dirname);
 
558
+             malloc_dirname = malloc_home_dir;
 
559
            }
 
560
          else
 
561
            {
 
562
              char *newp;
 
563
              size_t home_len = strlen (home_dir);
 
564
-             newp = (char *) __alloca (home_len + dirlen);
 
565
+             int use_alloca = __libc_use_alloca (alloca_used
 
566
+                                                 + home_len + dirlen);
 
567
+             if (use_alloca)
 
568
+               newp = alloca_account (home_len + dirlen, alloca_used);
 
569
+             else
 
570
+               {
 
571
+                 newp = malloc (home_len + dirlen);
 
572
+                 if (newp == NULL)
 
573
+                   {
 
574
+                     if (__builtin_expect (malloc_home_dir, 0))
 
575
+                       free (home_dir);
 
576
+                     retval = GLOB_NOSPACE;
 
577
+                     goto out;
 
578
+                   }
 
579
+               }
 
580
+
 
581
              mempcpy (mempcpy (newp, home_dir, home_len),
 
582
                       &dirname[1], dirlen);
 
583
+
 
584
+             if (__builtin_expect (malloc_dirname, 0))
 
585
+               free (dirname);
 
586
+
 
587
              dirname = newp;
 
588
              dirlen += home_len - 1;
 
589
+             malloc_dirname = !use_alloca;
 
590
            }
 
591
          dirname_modified = 1;
 
592
        }
 
593
@@ -656,7 +759,8 @@
 
594
       else
 
595
        {
 
596
          char *end_name = strchr (dirname, '/');
 
597
-         const char *user_name;
 
598
+         char *user_name;
 
599
+         int malloc_user_name = 0;
 
600
          const char *home_dir;
 
601
          char *unescape = NULL;
 
602
 
 
603
@@ -676,7 +780,18 @@
 
604
          else
 
605
            {
 
606
              char *newp;
 
607
-             newp = (char *) __alloca (end_name - dirname);
 
608
+             if (__libc_use_alloca (alloca_used + (end_name - dirname)))
 
609
+               newp = alloca_account (end_name - dirname, alloca_used);
 
610
+             else
 
611
+               {
 
612
+                 newp = malloc (end_name - dirname);
 
613
+                 if (newp == NULL)
 
614
+                   {
 
615
+                     retval = GLOB_NOSPACE;
 
616
+                     goto out;
 
617
+                   }
 
618
+                 malloc_user_name = 1;
 
619
+               }
 
620
              if (unescape != NULL)
 
621
                {
 
622
                  char *p = mempcpy (newp, dirname + 1,
 
623
@@ -713,6 +828,7 @@
 
624
 #  if defined HAVE_GETPWNAM_R || defined _LIBC
 
625
            long int buflen = GETPW_R_SIZE_MAX ();
 
626
            char *pwtmpbuf;
 
627
+           int malloc_pwtmpbuf = 0;
 
628
            struct passwd pwbuf;
 
629
            int save = errno;
 
630
 
 
631
@@ -722,7 +838,21 @@
 
632
                 moderate value.  */
 
633
              buflen = 1024;
 
634
 #   endif
 
635
-           pwtmpbuf = (char *) __alloca (buflen);
 
636
+           if (__libc_use_alloca (alloca_used + buflen))
 
637
+             pwtmpbuf = alloca_account (buflen, alloca_used);
 
638
+           else
 
639
+             {
 
640
+               pwtmpbuf = malloc (buflen);
 
641
+               if (pwtmpbuf == NULL)
 
642
+                 {
 
643
+                 nomem_getpw:
 
644
+                   if (__builtin_expect (malloc_user_name, 0))
 
645
+                     free (user_name);
 
646
+                   retval = GLOB_NOSPACE;
 
647
+                   goto out;
 
648
+                 }
 
649
+               malloc_pwtmpbuf = 1;
 
650
+             }
 
651
 
 
652
            while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0)
 
653
              {
 
654
@@ -731,40 +861,77 @@
 
655
                    p = NULL;
 
656
                    break;
 
657
                  }
 
658
-#   ifdef _LIBC
 
659
-               pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen);
 
660
-#   else
 
661
-               buflen *= 2;
 
662
-               pwtmpbuf = __alloca (buflen);
 
663
-#   endif
 
664
+               if (!malloc_pwtmpbuf
 
665
+                   && __libc_use_alloca (alloca_used + 2 * buflen))
 
666
+                 pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen,
 
667
+                                                   2 * buflen, alloca_used);
 
668
+               else
 
669
+                 {
 
670
+                   char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL,
 
671
+                                         2 * buflen);
 
672
+                   if (newp == NULL)
 
673
+                     {
 
674
+                       if (__builtin_expect (malloc_pwtmpbuf, 0))
 
675
+                         free (pwtmpbuf);
 
676
+                       goto nomem_getpw;
 
677
+                     }
 
678
+                   pwtmpbuf = newp;
 
679
+                   malloc_pwtmpbuf = 1;
 
680
+                 }
 
681
                __set_errno (save);
 
682
              }
 
683
 #  else
 
684
            p = getpwnam (user_name);
 
685
 #  endif
 
686
+
 
687
+           if (__builtin_expect (malloc_user_name, 0))
 
688
+             free (user_name);
 
689
+
 
690
+           /* If we found a home directory use this.  */
 
691
            if (p != NULL)
 
692
-             home_dir = p->pw_dir;
 
693
+             {
 
694
+               size_t home_len = strlen (p->pw_dir);
 
695
+               size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
 
696
+
 
697
+               if (__builtin_expect (malloc_dirname, 0))
 
698
+                 free (dirname);
 
699
+               malloc_dirname = 0;
 
700
+
 
701
+               if (__libc_use_alloca (alloca_used + home_len + rest_len + 1))
 
702
+                 dirname = alloca_account (home_len + rest_len + 1,
 
703
+                                           alloca_used);
 
704
+               else
 
705
+                 {
 
706
+                   dirname = malloc (home_len + rest_len + 1);
 
707
+                   if (dirname == NULL)
 
708
+                     {
 
709
+                       if (__builtin_expect (malloc_pwtmpbuf, 0))
 
710
+                         free (pwtmpbuf);
 
711
+                       retval = GLOB_NOSPACE;
 
712
+                       goto out;
 
713
+                     }
 
714
+                   malloc_dirname = 1;
 
715
+                 }
 
716
+               *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len),
 
717
+                                   end_name, rest_len)) = '\0';
 
718
+
 
719
+               dirlen = home_len + rest_len;
 
720
+               dirname_modified = 1;
 
721
+
 
722
+               if (__builtin_expect (malloc_pwtmpbuf, 0))
 
723
+                 free (pwtmpbuf);
 
724
+             }
 
725
            else
 
726
-             home_dir = NULL;
 
727
+             {
 
728
+               if (__builtin_expect (malloc_pwtmpbuf, 0))
 
729
+                 free (pwtmpbuf);
 
730
+
 
731
+               if (flags & GLOB_TILDE_CHECK)
 
732
+                 /* We have to regard it as an error if we cannot find the
 
733
+                    home directory.  */
 
734
+                 return GLOB_NOMATCH;
 
735
+             }
 
736
          }
 
737
-         /* If we found a home directory use this.  */
 
738
-         if (home_dir != NULL)
 
739
-           {
 
740
-             char *newp;
 
741
-             size_t home_len = strlen (home_dir);
 
742
-             size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
 
743
-             newp = (char *) __alloca (home_len + rest_len + 1);
 
744
-             *((char *) mempcpy (mempcpy (newp, home_dir, home_len),
 
745
-                                 end_name, rest_len)) = '\0';
 
746
-             dirname = newp;
 
747
-             dirlen = home_len + rest_len;
 
748
-             dirname_modified = 1;
 
749
-           }
 
750
-         else
 
751
-           if (flags & GLOB_TILDE_CHECK)
 
752
-             /* We have to regard it as an error if we cannot find the
 
753
-                home directory.  */
 
754
-             return GLOB_NOMATCH;
 
755
        }
 
756
 # endif        /* Not Amiga && not WINDOWS32.  */
 
757
     }
 
758
@@ -898,7 +1065,7 @@
 
759
          status = glob_in_dir (filename, dirs.gl_pathv[i],
 
760
                                ((flags | GLOB_APPEND)
 
761
                                 & ~(GLOB_NOCHECK | GLOB_NOMAGIC)),
 
762
-                               errfunc, pglob);
 
763
+                               errfunc, pglob, alloca_used);
 
764
          if (status == GLOB_NOMATCH)
 
765
            /* No matches in this directory.  Try the next.  */
 
766
            continue;
 
767
@@ -999,7 +1166,8 @@
 
768
        }
 
769
       if (dirname_modified)
 
770
        flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC);
 
771
-      status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
 
772
+      status = glob_in_dir (filename, dirname, flags, errfunc, pglob,
 
773
+                           alloca_used);
 
774
       if (status != 0)
 
775
        {
 
776
          if (status == GLOB_NOMATCH && flags != orig_flags
 
777
@@ -1062,7 +1230,11 @@
 
778
             sizeof (char *), collated_compare);
 
779
     }
 
780
 
 
781
-  return 0;
 
782
+ out:
 
783
+  if (__builtin_expect (malloc_dirname, 0))
 
784
+    free (dirname);
 
785
+
 
786
+  return retval;
 
787
 }
 
788
 #if defined _LIBC && !defined glob
 
789
 libc_hidden_def (glob)
 
790
@@ -1272,7 +1444,7 @@
 
791
 static int
 
792
 glob_in_dir (const char *pattern, const char *directory, int flags,
 
793
             int (*errfunc) (const char *, int),
 
794
-            glob_t *pglob)
 
795
+            glob_t *pglob, size_t alloca_used)
 
796
 {
 
797
   size_t dirlen = strlen (directory);
 
798
   void *stream = NULL;
 
799
@@ -1287,11 +1459,12 @@
 
800
   struct globnames *names = &init_names;
 
801
   struct globnames *names_alloca = &init_names;
 
802
   size_t nfound = 0;
 
803
-  size_t allocasize = sizeof (init_names);
 
804
   size_t cur = 0;
 
805
   int meta;
 
806
   int save;
 
807
 
 
808
+  alloca_used += sizeof (init_names);
 
809
+
 
810
   init_names.next = NULL;
 
811
   init_names.count = INITIAL_COUNT;
 
812
 
 
813
@@ -1307,20 +1480,36 @@
 
814
     {
 
815
       /* Since we use the normal file functions we can also use stat()
 
816
         to verify the file is there.  */
 
817
-      struct stat st;
 
818
-      struct_stat64 st64;
 
819
+      union
 
820
+      {
 
821
+       struct stat st;
 
822
+       struct_stat64 st64;
 
823
+      } ust;
 
824
       size_t patlen = strlen (pattern);
 
825
-      char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1);
 
826
+      int alloca_fullname = __libc_use_alloca (alloca_used
 
827
+                                              + dirlen + 1 + patlen + 1);
 
828
+      char *fullname;
 
829
+      if (alloca_fullname)
 
830
+       fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used);
 
831
+      else
 
832
+       {
 
833
+         fullname = malloc (dirlen + 1 + patlen + 1);
 
834
+         if (fullname == NULL)
 
835
+           return GLOB_NOSPACE;
 
836
+       }
 
837
 
 
838
       mempcpy (mempcpy (mempcpy (fullname, directory, dirlen),
 
839
                        "/", 1),
 
840
               pattern, patlen + 1);
 
841
       if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)
 
842
-          ? (*pglob->gl_stat) (fullname, &st)
 
843
-          : __stat64 (fullname, &st64)) == 0)
 
844
+          ? (*pglob->gl_stat) (fullname, &ust.st)
 
845
+          : __stat64 (fullname, &ust.st64)) == 0)
 
846
        /* We found this file to be existing.  Now tell the rest
 
847
           of the function to copy this name into the result.  */
 
848
        flags |= GLOB_NOCHECK;
 
849
+
 
850
+      if (__builtin_expect (!alloca_fullname, 0))
 
851
+       free (fullname);
 
852
     }
 
853
   else
 
854
     {
 
855
@@ -1408,9 +1597,9 @@
 
856
                          size_t size = (sizeof (struct globnames)
 
857
                                         + ((count - INITIAL_COUNT)
 
858
                                            * sizeof (char *)));
 
859
-                         allocasize += size;
 
860
-                         if (__libc_use_alloca (allocasize))
 
861
-                           newnames = names_alloca = __alloca (size);
 
862
+                         if (__libc_use_alloca (alloca_used + size))
 
863
+                           newnames = names_alloca
 
864
+                             = alloca_account (size, alloca_used);
 
865
                          else if ((newnames = malloc (size))
 
866
                                   == NULL)
 
867
                            goto memory_error;
 
868
Index: eglibc-2.11.1/sysdeps/posix/getaddrinfo.c
 
869
===================================================================
 
870
--- eglibc-2.11.1.orig/sysdeps/posix/getaddrinfo.c      2014-07-28 11:18:56.773591507 -0400
 
871
+++ eglibc-2.11.1/sysdeps/posix/getaddrinfo.c   2014-07-28 11:18:56.769591507 -0400
 
872
@@ -278,6 +278,7 @@
 
873
   bool got_ipv6 = false;
 
874
   const char *canon = NULL;
 
875
   const char *orig_name = name;
 
876
+  size_t alloca_used = 0;
 
877
 
 
878
   if (req->ai_protocol || req->ai_socktype)
 
879
     {
 
880
@@ -310,7 +311,7 @@
 
881
          if (tp->name[0])
 
882
            {
 
883
              st = (struct gaih_servtuple *)
 
884
-               __alloca (sizeof (struct gaih_servtuple));
 
885
+               alloca_account (sizeof (struct gaih_servtuple), alloca_used);
 
886
 
 
887
              if ((rc = gaih_inet_serv (service->name, tp, req, st)))
 
888
                return rc;
 
889
@@ -334,7 +335,8 @@
 
890
                    continue;
 
891
 
 
892
                  newp = (struct gaih_servtuple *)
 
893
-                   __alloca (sizeof (struct gaih_servtuple));
 
894
+                   alloca_account (sizeof (struct gaih_servtuple),
 
895
+                                   alloca_used);
 
896
 
 
897
                  if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
 
898
                    {
 
899
@@ -362,7 +364,7 @@
 
900
 
 
901
       if (req->ai_socktype || req->ai_protocol)
 
902
        {
 
903
-         st = __alloca (sizeof (struct gaih_servtuple));
 
904
+         st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
 
905
          st->next = NULL;
 
906
          st->socktype = tp->socktype;
 
907
          st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
 
908
@@ -379,7 +381,8 @@
 
909
              {
 
910
                struct gaih_servtuple *newp;
 
911
 
 
912
-               newp = __alloca (sizeof (struct gaih_servtuple));
 
913
+               newp = alloca_account (sizeof (struct gaih_servtuple),
 
914
+                                      alloca_used);
 
915
                newp->next = NULL;
 
916
                newp->socktype = tp->socktype;
 
917
                newp->protocol = tp->protocol;
 
918
@@ -391,10 +394,17 @@
 
919
        }
 
920
     }
 
921
 
 
922
+  bool malloc_name = false;
 
923
+  bool malloc_addrmem = false;
 
924
+  struct gaih_addrtuple *addrmem = NULL;
 
925
+  bool malloc_canonbuf = false;
 
926
+  char *canonbuf = NULL;
 
927
+  bool malloc_tmpbuf = false;
 
928
+  char *tmpbuf = NULL;
 
929
+  int result = 0;
 
930
   if (name != NULL)
 
931
     {
 
932
-      at = __alloca (sizeof (struct gaih_addrtuple));
 
933
-
 
934
+      at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
 
935
       at->family = AF_UNSPEC;
 
936
       at->scopeid = 0;
 
937
       at->next = NULL;
 
938
@@ -412,6 +422,7 @@
 
939
          rc = __idna_to_ascii_lz (name, &p, idn_flags);
 
940
          if (rc != IDNA_SUCCESS)
 
941
            {
 
942
+             /* No need to jump to free_and_return here.  */
 
943
              if (rc == IDNA_MALLOC_ERROR)
 
944
                return -EAI_MEMORY;
 
945
              if (rc == IDNA_DLOPEN_ERROR)
 
946
@@ -421,10 +432,7 @@
 
947
          /* In case the output string is the same as the input string
 
948
             no new string has been allocated.  */
 
949
          if (p != name)
 
950
-           {
 
951
-             name = strdupa (p);
 
952
-             free (p);
 
953
-           }
 
954
+           malloc_name = true;
 
955
        }
 
956
 #endif
 
957
 
 
958
@@ -441,23 +449,59 @@
 
959
              at->family = AF_INET6;
 
960
            }
 
961
          else
 
962
-           return -EAI_ADDRFAMILY;
 
963
+           {
 
964
+             result = -EAI_ADDRFAMILY;
 
965
+             goto free_and_return;
 
966
+           }
 
967
 
 
968
          if (req->ai_flags & AI_CANONNAME)
 
969
            canon = name;
 
970
        }
 
971
       else if (at->family == AF_UNSPEC)
 
972
        {
 
973
-         char *namebuf = (char *) name;
 
974
          char *scope_delim = strchr (name, SCOPE_DELIMITER);
 
975
+         int e;
 
976
 
 
977
-         if (__builtin_expect (scope_delim != NULL, 0))
 
978
-           {
 
979
-             namebuf = alloca (scope_delim - name + 1);
 
980
-             *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
 
981
-           }
 
982
+         {
 
983
+           bool malloc_namebuf = false;
 
984
+           char *namebuf = (char *) name;
 
985
+
 
986
+           if (__builtin_expect (scope_delim != NULL, 0))
 
987
+             {
 
988
+               if (malloc_name)
 
989
+                 *scope_delim = '\0';
 
990
+               else
 
991
+                 {
 
992
+                   if (__libc_use_alloca (alloca_used
 
993
+                                          + scope_delim - name + 1))
 
994
+                     {
 
995
+                       namebuf = alloca_account (scope_delim - name + 1,
 
996
+                                                 alloca_used);
 
997
+                       *((char *) __mempcpy (namebuf, name,
 
998
+                                             scope_delim - name)) = '\0';
 
999
+                     }
 
1000
+                   else
 
1001
+                     {
 
1002
+                       namebuf = strndup (name, scope_delim - name);
 
1003
+                       if (namebuf == NULL)
 
1004
+                         {
 
1005
+                           assert (!malloc_name);
 
1006
+                           return -EAI_MEMORY;
 
1007
+                         }
 
1008
+                       malloc_namebuf = true;
 
1009
+                     }
 
1010
+                 }
 
1011
+             }
 
1012
+
 
1013
+           e = inet_pton (AF_INET6, namebuf, at->addr);
 
1014
 
 
1015
-         if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
 
1016
+           if (malloc_namebuf)
 
1017
+             free (namebuf);
 
1018
+           else if (scope_delim != NULL && malloc_name)
 
1019
+             /* Undo what we did above.  */
 
1020
+             *scope_delim = SCOPE_DELIMITER;
 
1021
+         }
 
1022
+         if (e > 0)
 
1023
            {
 
1024
              if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
 
1025
                at->family = AF_INET6;
 
1026
@@ -468,7 +512,10 @@
 
1027
                  at->family = AF_INET;
 
1028
                }
 
1029
              else
 
1030
-               return -EAI_ADDRFAMILY;
 
1031
+               {
 
1032
+                 result = -EAI_ADDRFAMILY;
 
1033
+                 goto free_and_return;
 
1034
+               }
 
1035
 
 
1036
              if (scope_delim != NULL)
 
1037
                {
 
1038
@@ -490,7 +537,10 @@
 
1039
                      at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
 
1040
                                                        10);
 
1041
                      if (*end != '\0')
 
1042
-                       return GAIH_OKIFUNSPEC | -EAI_NONAME;
 
1043
+                       {
 
1044
+                         result = GAIH_OKIFUNSPEC | -EAI_NONAME;
 
1045
+                         goto free_and_return;
 
1046
+                       }
 
1047
                    }
 
1048
                }
 
1049
 
 
1050
@@ -519,7 +569,8 @@
 
1051
            {
 
1052
              int family = req->ai_family;
 
1053
              size_t tmpbuflen = 512;
 
1054
-             char *tmpbuf = alloca (tmpbuflen);
 
1055
+             assert (tmpbuf == NULL);
 
1056
+             tmpbuf = alloca_account (tmpbuflen, alloca_used);
 
1057
              int rc;
 
1058
              struct hostent th;
 
1059
              struct hostent *h;
 
1060
@@ -532,7 +583,25 @@
 
1061
                                           tmpbuflen, &h, &herrno);
 
1062
                  if (rc != ERANGE || herrno != NETDB_INTERNAL)
 
1063
                    break;
 
1064
-                 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
 
1065
+
 
1066
+                 if (!malloc_tmpbuf
 
1067
+                     && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
 
1068
+                   tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
 
1069
+                                                   2 * tmpbuflen,
 
1070
+                                                   alloca_used);
 
1071
+                 else
 
1072
+                   {
 
1073
+                     char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
 
1074
+                                           2 * tmpbuflen);
 
1075
+                     if (newp == NULL)
 
1076
+                       {
 
1077
+                         result = -EAI_MEMORY;
 
1078
+                         goto free_and_return;
 
1079
+                       }
 
1080
+                     tmpbuf = newp;
 
1081
+                     malloc_tmpbuf = true;
 
1082
+                     tmpbuflen = 2 * tmpbuflen;
 
1083
+                   }
 
1084
                }
 
1085
 
 
1086
              if (rc == 0)
 
1087
@@ -551,12 +620,36 @@
 
1088
                    }
 
1089
                  else
 
1090
                    {
 
1091
-                     /* We found data, now convert it into the list.  */
 
1092
-                     for (int i = 0; h->h_addr_list[i]; ++i)
 
1093
+                     int i;
 
1094
+                     /* We found data, count the number of addresses.  */
 
1095
+                     for (i = 0; h->h_addr_list[i]; ++i)
 
1096
+                       ;
 
1097
+                     if (i > 0 && *pat != NULL)
 
1098
+                       --i;
 
1099
+
 
1100
+                     if (__libc_use_alloca (alloca_used
 
1101
+                                            + i * sizeof (struct gaih_addrtuple)))
 
1102
+                       addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
 
1103
+                                                 alloca_used);
 
1104
+                     else
 
1105
+                       {
 
1106
+                         addrmem = malloc (i
 
1107
+                                           * sizeof (struct gaih_addrtuple));
 
1108
+                         if (addrmem == NULL)
 
1109
+                           {
 
1110
+                             result = -EAI_MEMORY;
 
1111
+                             goto free_and_return;
 
1112
+                           }
 
1113
+                         malloc_addrmem = true;
 
1114
+                       }
 
1115
+
 
1116
+                     /* Now convert it into the list.  */
 
1117
+                     struct gaih_addrtuple *addrfree = addrmem;
 
1118
+                     for (i = 0; h->h_addr_list[i]; ++i)
 
1119
                        {
 
1120
                          if (*pat == NULL)
 
1121
                            {
 
1122
-                             *pat = __alloca (sizeof (struct gaih_addrtuple));
 
1123
+                             *pat = addrfree++;
 
1124
                              (*pat)->scopeid = 0;
 
1125
                            }
 
1126
                          (*pat)->next = NULL;
 
1127
@@ -581,15 +674,16 @@
 
1128
                  if (herrno == NETDB_INTERNAL)
 
1129
                    {
 
1130
                      __set_h_errno (herrno);
 
1131
-                     return -EAI_SYSTEM;
 
1132
+                     result = -EAI_SYSTEM;
 
1133
                    }
 
1134
-                 if (herrno == TRY_AGAIN)
 
1135
-                   {
 
1136
-                     return -EAI_AGAIN;
 
1137
-                   }
 
1138
-                 /* We made requests but they turned out no data.
 
1139
-                    The name is known, though.  */
 
1140
-                 return GAIH_OKIFUNSPEC | -EAI_NODATA;
 
1141
+                 else if (herrno == TRY_AGAIN)
 
1142
+                   result = -EAI_AGAIN;
 
1143
+                 else
 
1144
+                   /* We made requests but they turned out no data.
 
1145
+                      The name is known, though.  */
 
1146
+                   result = GAIH_OKIFUNSPEC | -EAI_NODATA;
 
1147
+
 
1148
+                 goto free_and_return;
 
1149
                }
 
1150
 
 
1151
              goto process_list;
 
1152
@@ -612,21 +706,56 @@
 
1153
                  bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
 
1154
                  char *addrs = air->addrs;
 
1155
 
 
1156
+                 if (__libc_use_alloca (alloca_used
 
1157
+                                        + air->naddrs * sizeof (struct gaih_addrtuple)))
 
1158
+                   addrmem = alloca_account (air->naddrs
 
1159
+                                             * sizeof (struct gaih_addrtuple),
 
1160
+                                             alloca_used);
 
1161
+                 else
 
1162
+                   {
 
1163
+                     addrmem = malloc (air->naddrs
 
1164
+                                       * sizeof (struct gaih_addrtuple));
 
1165
+                     if (addrmem == NULL)
 
1166
+                       {
 
1167
+                         result = -EAI_MEMORY;
 
1168
+                         goto free_and_return;
 
1169
+                       }
 
1170
+                     malloc_addrmem = true;
 
1171
+                   }
 
1172
+
 
1173
+                 struct gaih_addrtuple *addrfree = addrmem;
 
1174
                  for (int i = 0; i < air->naddrs; ++i)
 
1175
                    {
 
1176
                      socklen_t size = (air->family[i] == AF_INET
 
1177
                                        ? INADDRSZ : IN6ADDRSZ);
 
1178
                      if (*pat == NULL)
 
1179
                        {
 
1180
-                         *pat = __alloca (sizeof (struct gaih_addrtuple));
 
1181
+                         *pat = addrfree++;
 
1182
                          (*pat)->scopeid = 0;
 
1183
                        }
 
1184
                      uint32_t *pataddr = (*pat)->addr;
 
1185
                      (*pat)->next = NULL;
 
1186
                      if (added_canon || air->canon == NULL)
 
1187
                        (*pat)->name = NULL;
 
1188
-                     else
 
1189
-                       canon = (*pat)->name = strdupa (air->canon);
 
1190
+                     else if (canonbuf == NULL)
 
1191
+                       {
 
1192
+                         size_t canonlen = strlen (air->canon) + 1;
 
1193
+                         if ((req->ai_flags & AI_CANONIDN) != 0
 
1194
+                             && __libc_use_alloca (alloca_used + canonlen))
 
1195
+                           canonbuf = alloca_account (canonlen, alloca_used);
 
1196
+                         else
 
1197
+                           {
 
1198
+                             canonbuf = malloc (canonlen);
 
1199
+                             if (canonbuf == NULL)
 
1200
+                               {
 
1201
+                                 result = -EAI_MEMORY;
 
1202
+                                 goto free_and_return;
 
1203
+                               }
 
1204
+                             malloc_canonbuf = true;
 
1205
+                           }
 
1206
+                         canon = (*pat)->name = memcpy (canonbuf, air->canon,
 
1207
+                                                        canonlen);
 
1208
+                       }
 
1209
 
 
1210
                      if (air->family[i] == AF_INET
 
1211
                          && req->ai_family == AF_INET6
 
1212
@@ -656,20 +785,26 @@
 
1213
                  free (air);
 
1214
 
 
1215
                  if (at->family == AF_UNSPEC)
 
1216
-                   return GAIH_OKIFUNSPEC | -EAI_NONAME;
 
1217
+                   {
 
1218
+                     result = GAIH_OKIFUNSPEC | -EAI_NONAME;
 
1219
+                     goto free_and_return;
 
1220
+                   }
 
1221
 
 
1222
                  goto process_list;
 
1223
                }
 
1224
              else if (err == 0)
 
1225
                /* The database contains a negative entry.  */
 
1226
-               return 0;
 
1227
+               goto free_and_return;
 
1228
              else if (__nss_not_use_nscd_hosts == 0)
 
1229
                {
 
1230
                  if (herrno == NETDB_INTERNAL && errno == ENOMEM)
 
1231
-                   return -EAI_MEMORY;
 
1232
-                 if (herrno == TRY_AGAIN)
 
1233
-                   return -EAI_AGAIN;
 
1234
-                 return -EAI_SYSTEM;
 
1235
+                   result = -EAI_MEMORY;
 
1236
+                 else if (herrno == TRY_AGAIN)
 
1237
+                   result = -EAI_AGAIN;
 
1238
+                 else
 
1239
+                   result = -EAI_SYSTEM;
 
1240
+
 
1241
+                 goto free_and_return;
 
1242
                }
 
1243
            }
 
1244
 #endif
 
1245
@@ -698,7 +833,19 @@
 
1246
          _res.options &= ~RES_USE_INET6;
 
1247
 
 
1248
          size_t tmpbuflen = 1024;
 
1249
-         char *tmpbuf = alloca (tmpbuflen);
 
1250
+         malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
 
1251
+         assert (tmpbuf == NULL);
 
1252
+         if (malloc_tmpbuf)
 
1253
+           tmpbuf = alloca_account (tmpbuflen, alloca_used);
 
1254
+         else
 
1255
+           {
 
1256
+             tmpbuf = malloc (tmpbuflen);
 
1257
+             if (tmpbuf == NULL)
 
1258
+               {
 
1259
+                 result = -EAI_MEMORY;
 
1260
+                 goto free_and_return;
 
1261
+               }
 
1262
+           }
 
1263
 
 
1264
          while (!no_more)
 
1265
            {
 
1266
@@ -729,8 +876,25 @@
 
1267
                            no_data = herrno == NO_DATA;
 
1268
                          break;
 
1269
                        }
 
1270
-                     tmpbuf = extend_alloca (tmpbuf,
 
1271
-                                             tmpbuflen, 2 * tmpbuflen);
 
1272
+
 
1273
+                     if (!malloc_tmpbuf
 
1274
+                         && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
 
1275
+                       tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
 
1276
+                                                       2 * tmpbuflen,
 
1277
+                                                       alloca_used);
 
1278
+                     else
 
1279
+                       {
 
1280
+                         char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
 
1281
+                                               2 * tmpbuflen);
 
1282
+                         if (newp == NULL)
 
1283
+                           {
 
1284
+                             result = -EAI_MEMORY;
 
1285
+                             goto free_and_return;
 
1286
+                           }
 
1287
+                         tmpbuf = newp;
 
1288
+                         malloc_tmpbuf = true;
 
1289
+                         tmpbuflen = 2 * tmpbuflen;
 
1290
+                       }
 
1291
                    }
 
1292
 
 
1293
                  no_inet6_data = no_data;
 
1294
@@ -805,18 +969,40 @@
 
1295
                              if (cfct != NULL)
 
1296
                                {
 
1297
                                  const size_t max_fqdn_len = 256;
 
1298
-                                 char *buf = alloca (max_fqdn_len);
 
1299
+                                 if ((req->ai_flags & AI_CANONIDN) != 0
 
1300
+                                     && __libc_use_alloca (alloca_used
 
1301
+                                                           + max_fqdn_len))
 
1302
+                                   canonbuf = alloca_account (max_fqdn_len,
 
1303
+                                                              alloca_used);
 
1304
+                                 else
 
1305
+                                   {
 
1306
+                                     canonbuf = malloc (max_fqdn_len);
 
1307
+                                     if (canonbuf == NULL)
 
1308
+                                       {
 
1309
+                                         result = -EAI_MEMORY;
 
1310
+                                         goto free_and_return;
 
1311
+                                       }
 
1312
+                                     malloc_canonbuf = true;
 
1313
+                                   }
 
1314
                                  char *s;
 
1315
 
 
1316
                                  if (DL_CALL_FCT (cfct, (at->name ?: name,
 
1317
-                                                         buf, max_fqdn_len,
 
1318
+                                                         canonbuf,
 
1319
+                                                         max_fqdn_len,
 
1320
                                                          &s, &rc, &herrno))
 
1321
                                      == NSS_STATUS_SUCCESS)
 
1322
                                    canon = s;
 
1323
                                  else
 
1324
-                                   /* Set to name now to avoid using
 
1325
-                                      gethostbyaddr.  */
 
1326
-                                   canon = name;
 
1327
+                                   {
 
1328
+                                     /* Set to name now to avoid using
 
1329
+                                        gethostbyaddr.  */
 
1330
+                                     if (malloc_canonbuf)
 
1331
+                                       {
 
1332
+                                         free (canonbuf);
 
1333
+                                         malloc_canonbuf = false;
 
1334
+                                       }
 
1335
+                                     canon = name;
 
1336
+                                   }
 
1337
                                }
 
1338
                            }
 
1339
 
 
1340
@@ -850,22 +1036,27 @@
 
1341
            {
 
1342
              /* If both requests timed out report this.  */
 
1343
              if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
 
1344
-               return -EAI_AGAIN;
 
1345
+               result = -EAI_AGAIN;
 
1346
+             else
 
1347
+               /* We made requests but they turned out no data.  The name
 
1348
+                  is known, though.  */
 
1349
+               result = GAIH_OKIFUNSPEC | -EAI_NODATA;
 
1350
 
 
1351
-             /* We made requests but they turned out no data.  The name
 
1352
-                is known, though.  */
 
1353
-             return GAIH_OKIFUNSPEC | -EAI_NODATA;
 
1354
+             goto free_and_return;
 
1355
            }
 
1356
        }
 
1357
 
 
1358
     process_list:
 
1359
       if (at->family == AF_UNSPEC)
 
1360
-       return GAIH_OKIFUNSPEC | -EAI_NONAME;
 
1361
+       {
 
1362
+         result = GAIH_OKIFUNSPEC | -EAI_NONAME;
 
1363
+         goto free_and_return;
 
1364
+       }
 
1365
     }
 
1366
   else
 
1367
     {
 
1368
       struct gaih_addrtuple *atr;
 
1369
-      atr = at = __alloca (sizeof (struct gaih_addrtuple));
 
1370
+      atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
 
1371
       memset (at, '\0', sizeof (struct gaih_addrtuple));
 
1372
 
 
1373
       if (req->ai_family == AF_UNSPEC)
 
1374
@@ -904,30 +1095,56 @@
 
1375
        /* Only the first entry gets the canonical name.  */
 
1376
        if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
 
1377
          {
 
1378
+           char *tmpbuf2 = NULL;
 
1379
+           bool malloc_tmpbuf2 = false;
 
1380
+
 
1381
            if (canon == NULL)
 
1382
              {
 
1383
                struct hostent *h = NULL;
 
1384
                int herrno;
 
1385
                struct hostent th;
 
1386
-               size_t tmpbuflen = 512;
 
1387
-               char *tmpbuf = NULL;
 
1388
+               size_t tmpbuf2len = 512;
 
1389
 
 
1390
                do
 
1391
                  {
 
1392
-                   tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
 
1393
+                   if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
 
1394
+                     tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
 
1395
+                                                      tmpbuf2len * 2,
 
1396
+                                                      alloca_used);
 
1397
+                   else
 
1398
+                     {
 
1399
+                       char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
 
1400
+                                             2 * tmpbuf2len);
 
1401
+                       if (newp == NULL)
 
1402
+                         {
 
1403
+                           if (malloc_tmpbuf2)
 
1404
+                             free (tmpbuf2);
 
1405
+                           result = -EAI_MEMORY;
 
1406
+                           goto free_and_return;
 
1407
+                         }
 
1408
+
 
1409
+                       tmpbuf2 = newp;
 
1410
+                       tmpbuf2len = 2 * tmpbuf2len;
 
1411
+                       malloc_tmpbuf2 = true;
 
1412
+                     }
 
1413
+
 
1414
                    rc = __gethostbyaddr_r (at2->addr,
 
1415
                                            ((at2->family == AF_INET6)
 
1416
                                             ? sizeof (struct in6_addr)
 
1417
                                             : sizeof (struct in_addr)),
 
1418
-                                           at2->family, &th, tmpbuf,
 
1419
-                                           tmpbuflen, &h, &herrno);
 
1420
+                                           at2->family, &th, tmpbuf2,
 
1421
+                                           tmpbuf2len, &h, &herrno);
 
1422
                  }
 
1423
                while (rc == ERANGE && herrno == NETDB_INTERNAL);
 
1424
 
 
1425
                if (rc != 0 && herrno == NETDB_INTERNAL)
 
1426
                  {
 
1427
+                   if (malloc_tmpbuf2)
 
1428
+                     free (tmpbuf2);
 
1429
+
 
1430
                    __set_h_errno (herrno);
 
1431
-                   return -EAI_SYSTEM;
 
1432
+                   result = -EAI_SYSTEM;
 
1433
+                   goto free_and_return;
 
1434
                  }
 
1435
 
 
1436
                if (h != NULL)
 
1437
@@ -954,11 +1171,16 @@
 
1438
                int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
 
1439
                if (rc != IDNA_SUCCESS)
 
1440
                  {
 
1441
+                   if (malloc_tmpbuf2)
 
1442
+                     free (tmpbuf2);
 
1443
+
 
1444
                    if (rc == IDNA_MALLOC_ERROR)
 
1445
-                     return -EAI_MEMORY;
 
1446
-                   if (rc == IDNA_DLOPEN_ERROR)
 
1447
-                     return -EAI_SYSTEM;
 
1448
-                   return -EAI_IDN_ENCODE;
 
1449
+                     result = -EAI_MEMORY;
 
1450
+                   else if (rc == IDNA_DLOPEN_ERROR)
 
1451
+                     result = -EAI_SYSTEM;
 
1452
+                   else
 
1453
+                     result = -EAI_IDN_ENCODE;
 
1454
+                   goto free_and_return;
 
1455
                  }
 
1456
                /* In case the output string is the same as the input
 
1457
                   string no new string has been allocated and we
 
1458
@@ -972,10 +1194,25 @@
 
1459
 #ifdef HAVE_LIBIDN
 
1460
              make_copy:
 
1461
 #endif
 
1462
-               canon = strdup (canon);
 
1463
-               if (canon == NULL)
 
1464
-                 return -EAI_MEMORY;
 
1465
+               if (malloc_canonbuf)
 
1466
+                 /* We already allocated the string using malloc.  */
 
1467
+                 malloc_canonbuf = false;
 
1468
+               else
 
1469
+                 {
 
1470
+                   canon = strdup (canon);
 
1471
+                   if (canon == NULL)
 
1472
+                     {
 
1473
+                       if (malloc_tmpbuf2)
 
1474
+                         free (tmpbuf2);
 
1475
+
 
1476
+                       result = -EAI_MEMORY;
 
1477
+                       goto free_and_return;
 
1478
+                     }
 
1479
+                 }
 
1480
              }
 
1481
+
 
1482
+           if (malloc_tmpbuf2)
 
1483
+             free (tmpbuf2);
 
1484
          }
 
1485
 
 
1486
        family = at2->family;
 
1487
@@ -1001,7 +1238,8 @@
 
1488
            if (ai == NULL)
 
1489
              {
 
1490
                free ((char *) canon);
 
1491
-               return -EAI_MEMORY;
 
1492
+               result = -EAI_MEMORY;
 
1493
+               goto free_and_return;
 
1494
              }
 
1495
 
 
1496
            ai->ai_flags = req->ai_flags;
 
1497
@@ -1054,7 +1292,18 @@
 
1498
        at2 = at2->next;
 
1499
       }
 
1500
   }
 
1501
-  return 0;
 
1502
+
 
1503
+ free_and_return:
 
1504
+  if (malloc_name)
 
1505
+    free ((char *) name);
 
1506
+  if (malloc_addrmem)
 
1507
+    free (addrmem);
 
1508
+  if (malloc_canonbuf)
 
1509
+    free (canonbuf);
 
1510
+  if (malloc_tmpbuf)
 
1511
+    free (tmpbuf);
 
1512
+
 
1513
+  return result;
 
1514
 }
 
1515
 
 
1516