]>
Commit | Line | Data |
---|---|---|
12788f63 MT |
1 | From: Ulrich Drepper <drepper@gmail.com> |
2 | Date: Mon, 23 May 2011 03:04:16 +0000 (-0400) | |
3 | Subject: Add a few more alloca size checks | |
4 | X-Git-Tag: glibc-2.14~41 | |
5 | X-Git-Url: http://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=f2962a71959fd254a7a223437ca4b63b9e81130c | |
6 | ||
7 | Add a few more alloca size checks | |
8 | --- | |
9 | ||
10 | 2011-05-22 Ulrich Drepper <drepper@gmail.com> | |
11 | ||
12 | [BZ #12671] | |
13 | * nis/nss_nis/nis-alias.c (_nss_nis_getaliasbyname_r): Use malloc in | |
14 | some situations. | |
15 | * nscd/nscd_getserv_r.c (nscd_getserv_r): Likewise. | |
16 | * posix/glob.c (glob_in_dir): Take additional parameter alloca_used. | |
17 | add in in __libc_use_alloca calls. Adjust callers. | |
18 | (glob): Use malloc in some situations. | |
19 | diff --git a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c | |
20 | index 9286e36..cfe4097 100644 | |
21 | --- a/nis/nss_nis/nis-alias.c | |
22 | +++ b/nis/nss_nis/nis-alias.c | |
23 | @@ -1,4 +1,4 @@ | |
24 | -/* Copyright (C) 1996-2002, 2003, 2006 Free Software Foundation, Inc. | |
25 | +/* Copyright (C) 1996-2002, 2003, 2006, 2011 Free Software Foundation, Inc. | |
26 | This file is part of the GNU C Library. | |
27 | Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. | |
28 | ||
29 | @@ -142,10 +142,10 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer, | |
30 | int yperr; | |
31 | ||
32 | if (new_start) | |
33 | - yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result, | |
34 | + yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result, | |
35 | &len); | |
36 | else | |
37 | - yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey, | |
38 | + yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey, | |
39 | &keylen, &result, &len); | |
40 | ||
41 | if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) | |
42 | @@ -153,20 +153,20 @@ internal_nis_getaliasent_r (struct aliasent *alias, char *buffer, | |
43 | enum nss_status retval = yperr2nss (yperr); | |
44 | ||
45 | if (retval == NSS_STATUS_TRYAGAIN) | |
46 | - *errnop = errno; | |
47 | - return retval; | |
48 | - } | |
49 | + *errnop = errno; | |
50 | + return retval; | |
51 | + } | |
52 | ||
53 | if (__builtin_expect ((size_t) (len + 1) > buflen, 0)) | |
54 | - { | |
55 | + { | |
56 | free (result); | |
57 | - *errnop = ERANGE; | |
58 | - return NSS_STATUS_TRYAGAIN; | |
59 | - } | |
60 | + *errnop = ERANGE; | |
61 | + return NSS_STATUS_TRYAGAIN; | |
62 | + } | |
63 | char *p = strncpy (buffer, result, len); | |
64 | buffer[len] = '\0'; | |
65 | while (isspace (*p)) | |
66 | - ++p; | |
67 | + ++p; | |
68 | free (result); | |
69 | ||
70 | parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer, | |
71 | @@ -213,13 +213,25 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias, | |
72 | return NSS_STATUS_UNAVAIL; | |
73 | } | |
74 | ||
75 | - size_t namlen = strlen (name); | |
76 | - char name2[namlen + 1]; | |
77 | - | |
78 | char *domain; | |
79 | if (__builtin_expect (yp_get_default_domain (&domain), 0)) | |
80 | return NSS_STATUS_UNAVAIL; | |
81 | ||
82 | + size_t namlen = strlen (name); | |
83 | + char *name2; | |
84 | + int use_alloca = __libc_use_alloca (namlen + 1); | |
85 | + if (use_alloca) | |
86 | + name2 = __alloca (namlen + 1); | |
87 | + else | |
88 | + { | |
89 | + name2 = malloc (namlen + 1); | |
90 | + if (name2 == NULL) | |
91 | + { | |
92 | + *errnop = ENOMEM; | |
93 | + return NSS_STATUS_TRYAGAIN; | |
94 | + } | |
95 | + } | |
96 | + | |
97 | /* Convert name to lowercase. */ | |
98 | size_t i; | |
99 | for (i = 0; i < namlen; ++i) | |
100 | @@ -230,6 +242,9 @@ _nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias, | |
101 | int len; | |
102 | int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len); | |
103 | ||
104 | + if (!use_alloca) | |
105 | + free (name2); | |
106 | + | |
107 | if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) | |
108 | { | |
109 | enum nss_status retval = yperr2nss (yperr); | |
110 | diff --git a/nscd/nscd_getserv_r.c b/nscd/nscd_getserv_r.c | |
111 | index dce4165..de96a57 100644 | |
112 | --- a/nscd/nscd_getserv_r.c | |
113 | +++ b/nscd/nscd_getserv_r.c | |
114 | @@ -1,4 +1,4 @@ | |
115 | -/* Copyright (C) 2007, 2009 Free Software Foundation, Inc. | |
116 | +/* Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc. | |
117 | This file is part of the GNU C Library. | |
118 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2007. | |
119 | ||
120 | @@ -17,6 +17,7 @@ | |
121 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
122 | 02111-1307 USA. */ | |
123 | ||
124 | +#include <assert.h> | |
125 | #include <errno.h> | |
126 | #include <string.h> | |
127 | #include <not-cancel.h> | |
128 | @@ -80,6 +81,7 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto, | |
129 | { | |
130 | int gc_cycle; | |
131 | int nretries = 0; | |
132 | + size_t alloca_used = 0; | |
133 | ||
134 | /* If the mapping is available, try to search there instead of | |
135 | communicating with the nscd. */ | |
136 | @@ -88,13 +90,23 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto, | |
137 | &gc_cycle); | |
138 | size_t protolen = proto == NULL ? 0 : strlen (proto); | |
139 | size_t keylen = critlen + 1 + protolen + 1; | |
140 | - char *key = alloca (keylen); | |
141 | + int alloca_key = __libc_use_alloca (keylen); | |
142 | + char *key; | |
143 | + if (alloca_key) | |
144 | + key = alloca_account (keylen, alloca_used); | |
145 | + else | |
146 | + { | |
147 | + key = malloc (keylen); | |
148 | + if (key == NULL) | |
149 | + return -1; | |
150 | + } | |
151 | memcpy (__mempcpy (__mempcpy (key, crit, critlen), | |
152 | "/", 1), proto ?: "", protolen + 1); | |
153 | ||
154 | retry:; | |
155 | const char *s_name = NULL; | |
156 | const char *s_proto = NULL; | |
157 | + int alloca_aliases_len = 0; | |
158 | const uint32_t *aliases_len = NULL; | |
159 | const char *aliases_list = NULL; | |
160 | int retval = -1; | |
161 | @@ -136,8 +148,22 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto, | |
162 | if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1)) | |
163 | != 0) | |
164 | { | |
165 | - uint32_t *tmp = alloca (serv_resp.s_aliases_cnt | |
166 | - * sizeof (uint32_t)); | |
167 | + uint32_t *tmp; | |
168 | + alloca_aliases_len | |
169 | + = __libc_use_alloca (alloca_used | |
170 | + + (serv_resp.s_aliases_cnt | |
171 | + * sizeof (uint32_t))); | |
172 | + if (alloca_aliases_len) | |
173 | + tmp = __alloca (serv_resp.s_aliases_cnt * sizeof (uint32_t)); | |
174 | + else | |
175 | + { | |
176 | + tmp = malloc (serv_resp.s_aliases_cnt * sizeof (uint32_t)); | |
177 | + if (tmp == NULL) | |
178 | + { | |
179 | + retval = ENOMEM; | |
180 | + goto out; | |
181 | + } | |
182 | + } | |
183 | aliases_len = memcpy (tmp, aliases_len, | |
184 | serv_resp.s_aliases_cnt | |
185 | * sizeof (uint32_t)); | |
186 | @@ -217,8 +243,24 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto, | |
187 | ||
188 | if (serv_resp.s_aliases_cnt > 0) | |
189 | { | |
190 | - aliases_len = alloca (serv_resp.s_aliases_cnt | |
191 | - * sizeof (uint32_t)); | |
192 | + assert (alloca_aliases_len == 0); | |
193 | + alloca_aliases_len | |
194 | + = __libc_use_alloca (alloca_used | |
195 | + + (serv_resp.s_aliases_cnt | |
196 | + * sizeof (uint32_t))); | |
197 | + if (alloca_aliases_len) | |
198 | + aliases_len = alloca (serv_resp.s_aliases_cnt | |
199 | + * sizeof (uint32_t)); | |
200 | + else | |
201 | + { | |
202 | + aliases_len = malloc (serv_resp.s_aliases_cnt | |
203 | + * sizeof (uint32_t)); | |
204 | + if (aliases_len == NULL) | |
205 | + { | |
206 | + retval = ENOMEM; | |
207 | + goto out_close; | |
208 | + } | |
209 | + } | |
210 | vec[n].iov_base = (void *) aliases_len; | |
211 | vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t); | |
212 | ||
213 | @@ -329,5 +371,10 @@ nscd_getserv_r (const char *crit, size_t critlen, const char *proto, | |
214 | goto retry; | |
215 | } | |
216 | ||
217 | + if (!alloca_aliases_len) | |
218 | + free ((void *) aliases_len); | |
219 | + if (!alloca_key) | |
220 | + free (key); | |
221 | + | |
222 | return retval; | |
223 | } | |
224 | diff --git a/posix/glob.c b/posix/glob.c | |
225 | index 6df083a..79b6e50 100644 | |
226 | --- a/posix/glob.c | |
227 | +++ b/posix/glob.c | |
228 | @@ -1,4 +1,4 @@ | |
229 | -/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 | |
230 | +/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 | |
231 | Free Software Foundation, Inc. | |
232 | This file is part of the GNU C Library. | |
233 | ||
234 | @@ -199,7 +199,7 @@ static const char *next_brace_sub (const char *begin, int flags) __THROW; | |
235 | ||
236 | static int glob_in_dir (const char *pattern, const char *directory, | |
237 | int flags, int (*errfunc) (const char *, int), | |
238 | - glob_t *pglob); | |
239 | + glob_t *pglob, size_t alloca_used); | |
240 | extern int __glob_pattern_type (const char *pattern, int quote) | |
241 | attribute_hidden; | |
242 | ||
243 | @@ -253,13 +253,18 @@ glob (pattern, flags, errfunc, pglob) | |
244 | glob_t *pglob; | |
245 | { | |
246 | const char *filename; | |
247 | - const char *dirname; | |
248 | + char *dirname = NULL; | |
249 | size_t dirlen; | |
250 | int status; | |
251 | size_t oldcount; | |
252 | int meta; | |
253 | int dirname_modified; | |
254 | + int malloc_dirname = 0; | |
255 | glob_t dirs; | |
256 | + int retval = 0; | |
257 | +#ifdef _LIBC | |
258 | + size_t alloca_used = 0; | |
259 | +#endif | |
260 | ||
261 | if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) | |
262 | { | |
263 | @@ -308,20 +313,26 @@ glob (pattern, flags, errfunc, pglob) | |
264 | const char *next; | |
265 | const char *rest; | |
266 | size_t rest_len; | |
267 | -#ifdef __GNUC__ | |
268 | - char onealt[strlen (pattern) - 1]; | |
269 | -#else | |
270 | - char *onealt = (char *) malloc (strlen (pattern) - 1); | |
271 | - if (onealt == NULL) | |
272 | + char *onealt; | |
273 | + size_t pattern_len = strlen (pattern) - 1; | |
274 | +#ifdef _LIBC | |
275 | + int alloca_onealt = __libc_use_alloca (alloca_used + pattern_len); | |
276 | + if (alloca_onealt) | |
277 | + onealt = alloca_account (pattern_len, alloca_used); | |
278 | + else | |
279 | +#endif | |
280 | { | |
281 | - if (!(flags & GLOB_APPEND)) | |
282 | + onealt = (char *) malloc (pattern_len); | |
283 | + if (onealt == NULL) | |
284 | { | |
285 | - pglob->gl_pathc = 0; | |
286 | - pglob->gl_pathv = NULL; | |
287 | + if (!(flags & GLOB_APPEND)) | |
288 | + { | |
289 | + pglob->gl_pathc = 0; | |
290 | + pglob->gl_pathv = NULL; | |
291 | + } | |
292 | + return GLOB_NOSPACE; | |
293 | } | |
294 | - return GLOB_NOSPACE; | |
295 | } | |
296 | -#endif | |
297 | ||
298 | /* We know the prefix for all sub-patterns. */ | |
299 | alt_start = mempcpy (onealt, pattern, begin - pattern); | |
300 | @@ -332,9 +343,11 @@ glob (pattern, flags, errfunc, pglob) | |
301 | if (next == NULL) | |
302 | { | |
303 | /* It is an illegal expression. */ | |
304 | -#ifndef __GNUC__ | |
305 | - free (onealt); | |
306 | + illegal_brace: | |
307 | +#ifdef _LIBC | |
308 | + if (__builtin_expect (!alloca_onealt, 0)) | |
309 | #endif | |
310 | + free (onealt); | |
311 | return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); | |
312 | } | |
313 | ||
314 | @@ -344,13 +357,8 @@ glob (pattern, flags, errfunc, pglob) | |
315 | { | |
316 | rest = next_brace_sub (rest + 1, flags); | |
317 | if (rest == NULL) | |
318 | - { | |
319 | - /* It is an illegal expression. */ | |
320 | -#ifndef __GNUC__ | |
321 | - free (onealt); | |
322 | -#endif | |
323 | - return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); | |
324 | - } | |
325 | + /* It is an illegal expression. */ | |
326 | + goto illegal_brace; | |
327 | } | |
328 | /* Please note that we now can be sure the brace expression | |
329 | is well-formed. */ | |
330 | @@ -386,9 +394,10 @@ glob (pattern, flags, errfunc, pglob) | |
331 | /* If we got an error, return it. */ | |
332 | if (result && result != GLOB_NOMATCH) | |
333 | { | |
334 | -#ifndef __GNUC__ | |
335 | - free (onealt); | |
336 | +#ifdef _LIBC | |
337 | + if (__builtin_expect (!alloca_onealt, 0)) | |
338 | #endif | |
339 | + free (onealt); | |
340 | if (!(flags & GLOB_APPEND)) | |
341 | { | |
342 | globfree (pglob); | |
343 | @@ -406,9 +415,10 @@ glob (pattern, flags, errfunc, pglob) | |
344 | assert (next != NULL); | |
345 | } | |
346 | ||
347 | -#ifndef __GNUC__ | |
348 | - free (onealt); | |
349 | +#ifdef _LIBC | |
350 | + if (__builtin_expect (!alloca_onealt, 0)) | |
351 | #endif | |
352 | + free (onealt); | |
353 | ||
354 | if (pglob->gl_pathc != firstc) | |
355 | /* We found some entries. */ | |
356 | @@ -455,7 +465,7 @@ glob (pattern, flags, errfunc, pglob) | |
357 | case is nothing but a notation for a directory. */ | |
358 | if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') | |
359 | { | |
360 | - dirname = pattern; | |
361 | + dirname = (char *) pattern; | |
362 | dirlen = strlen (pattern); | |
363 | ||
364 | /* Set FILENAME to NULL as a special flag. This is ugly but | |
365 | @@ -473,9 +483,9 @@ glob (pattern, flags, errfunc, pglob) | |
366 | ||
367 | filename = pattern; | |
368 | #ifdef _AMIGA | |
369 | - dirname = ""; | |
370 | + dirname = (char *) ""; | |
371 | #else | |
372 | - dirname = "."; | |
373 | + dirname = (char *) "."; | |
374 | #endif | |
375 | dirlen = 0; | |
376 | } | |
377 | @@ -485,7 +495,7 @@ glob (pattern, flags, errfunc, pglob) | |
378 | && (flags & GLOB_NOESCAPE) == 0)) | |
379 | { | |
380 | /* "/pattern" or "\\/pattern". */ | |
381 | - dirname = "/"; | |
382 | + dirname = (char *) "/"; | |
383 | dirlen = 1; | |
384 | ++filename; | |
385 | } | |
386 | @@ -511,7 +521,17 @@ glob (pattern, flags, errfunc, pglob) | |
387 | from "d:/", since "d:" and "d:/" are not the same.*/ | |
388 | } | |
389 | #endif | |
390 | - newp = (char *) __alloca (dirlen + 1); | |
391 | +#ifdef _LIBC | |
392 | + if (__libc_use_alloca (alloca_used + dirlen + 1)) | |
393 | + newp = alloca_account (dirlen + 1, alloca_used); | |
394 | + else | |
395 | +#endif | |
396 | + { | |
397 | + newp = malloc (dirlen + 1); | |
398 | + if (newp == NULL) | |
399 | + return GLOB_NOSPACE; | |
400 | + malloc_dirname = 1; | |
401 | + } | |
402 | *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; | |
403 | dirname = newp; | |
404 | ++filename; | |
405 | @@ -551,7 +571,8 @@ glob (pattern, flags, errfunc, pglob) | |
406 | oldcount = pglob->gl_pathc + pglob->gl_offs; | |
407 | goto no_matches; | |
408 | } | |
409 | - return val; | |
410 | + retval = val; | |
411 | + goto out; | |
412 | } | |
413 | } | |
414 | ||
415 | @@ -563,7 +584,8 @@ glob (pattern, flags, errfunc, pglob) | |
416 | && (dirname[2] == '\0' || dirname[2] == '/'))) | |
417 | { | |
418 | /* Look up home directory. */ | |
419 | - const char *home_dir = getenv ("HOME"); | |
420 | + char *home_dir = getenv ("HOME"); | |
421 | + int malloc_home_dir = 0; | |
422 | # ifdef _AMIGA | |
423 | if (home_dir == NULL || home_dir[0] == '\0') | |
424 | home_dir = "SYS:"; | |
425 | @@ -582,7 +604,7 @@ glob (pattern, flags, errfunc, pglob) | |
426 | /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try | |
427 | a moderate value. */ | |
428 | buflen = 20; | |
429 | - name = (char *) __alloca (buflen); | |
430 | + name = alloca_account (buflen, alloca_used); | |
431 | ||
432 | success = getlogin_r (name, buflen) == 0; | |
433 | if (success) | |
434 | @@ -592,6 +614,7 @@ glob (pattern, flags, errfunc, pglob) | |
435 | long int pwbuflen = GETPW_R_SIZE_MAX (); | |
436 | char *pwtmpbuf; | |
437 | struct passwd pwbuf; | |
438 | + int malloc_pwtmpbuf = 0; | |
439 | int save = errno; | |
440 | ||
441 | # ifndef _LIBC | |
442 | @@ -600,7 +623,18 @@ glob (pattern, flags, errfunc, pglob) | |
443 | Try a moderate value. */ | |
444 | pwbuflen = 1024; | |
445 | # endif | |
446 | - pwtmpbuf = (char *) __alloca (pwbuflen); | |
447 | + if (__libc_use_alloca (alloca_used + pwbuflen)) | |
448 | + pwtmpbuf = alloca_account (pwbuflen, alloca_used); | |
449 | + else | |
450 | + { | |
451 | + pwtmpbuf = malloc (pwbuflen); | |
452 | + if (pwtmpbuf == NULL) | |
453 | + { | |
454 | + retval = GLOB_NOSPACE; | |
455 | + goto out; | |
456 | + } | |
457 | + malloc_pwtmpbuf = 1; | |
458 | + } | |
459 | ||
460 | while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) | |
461 | != 0) | |
462 | @@ -610,46 +644,115 @@ glob (pattern, flags, errfunc, pglob) | |
463 | p = NULL; | |
464 | break; | |
465 | } | |
466 | -# ifdef _LIBC | |
467 | - pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen, | |
468 | + | |
469 | + if (!malloc_pwtmpbuf | |
470 | + && __libc_use_alloca (alloca_used | |
471 | + + 2 * pwbuflen)) | |
472 | + pwtmpbuf = extend_alloca_account (pwtmpbuf, pwbuflen, | |
473 | + 2 * pwbuflen, | |
474 | + alloca_used); | |
475 | + else | |
476 | + { | |
477 | + char *newp = realloc (malloc_pwtmpbuf | |
478 | + ? pwtmpbuf : NULL, | |
479 | 2 * pwbuflen); | |
480 | -# else | |
481 | - pwbuflen *= 2; | |
482 | - pwtmpbuf = (char *) __alloca (pwbuflen); | |
483 | -# endif | |
484 | + if (newp == NULL) | |
485 | + { | |
486 | + if (__builtin_expect (malloc_pwtmpbuf, 0)) | |
487 | + free (pwtmpbuf); | |
488 | + retval = GLOB_NOSPACE; | |
489 | + goto out; | |
490 | + } | |
491 | + pwtmpbuf = newp; | |
492 | + pwbuflen = 2 * pwbuflen; | |
493 | + malloc_pwtmpbuf = 1; | |
494 | + } | |
495 | __set_errno (save); | |
496 | } | |
497 | # else | |
498 | p = getpwnam (name); | |
499 | # endif | |
500 | if (p != NULL) | |
501 | - home_dir = p->pw_dir; | |
502 | + { | |
503 | + if (!malloc_pwtmpbuf) | |
504 | + home_dir = p->pw_dir; | |
505 | + else | |
506 | + { | |
507 | + size_t home_dir_len = strlen (p->pw_dir) + 1; | |
508 | + if (__libc_use_alloca (alloca_used + home_dir_len)) | |
509 | + home_dir = alloca_account (home_dir_len, | |
510 | + alloca_used); | |
511 | + else | |
512 | + { | |
513 | + home_dir = malloc (home_dir_len); | |
514 | + if (home_dir == NULL) | |
515 | + { | |
516 | + free (pwtmpbuf); | |
517 | + retval = GLOB_NOSPACE; | |
518 | + goto out; | |
519 | + } | |
520 | + malloc_home_dir = 1; | |
521 | + } | |
522 | + memcpy (home_dir, p->pw_dir, home_dir_len); | |
523 | + | |
524 | + free (pwtmpbuf); | |
525 | + } | |
526 | + } | |
527 | } | |
528 | } | |
529 | if (home_dir == NULL || home_dir[0] == '\0') | |
530 | { | |
531 | if (flags & GLOB_TILDE_CHECK) | |
532 | - return GLOB_NOMATCH; | |
533 | + { | |
534 | + if (__builtin_expect (malloc_home_dir, 0)) | |
535 | + free (home_dir); | |
536 | + retval = GLOB_NOMATCH; | |
537 | + goto out; | |
538 | + } | |
539 | else | |
540 | - home_dir = "~"; /* No luck. */ | |
541 | + home_dir = (char *) "~"; /* No luck. */ | |
542 | } | |
543 | # endif /* WINDOWS32 */ | |
544 | # endif | |
545 | /* Now construct the full directory. */ | |
546 | if (dirname[1] == '\0') | |
547 | { | |
548 | + if (__builtin_expect (malloc_dirname, 0)) | |
549 | + free (dirname); | |
550 | + | |
551 | dirname = home_dir; | |
552 | dirlen = strlen (dirname); | |
553 | + malloc_dirname = malloc_home_dir; | |
554 | } | |
555 | else | |
556 | { | |
557 | char *newp; | |
558 | size_t home_len = strlen (home_dir); | |
559 | - newp = (char *) __alloca (home_len + dirlen); | |
560 | + int use_alloca = __libc_use_alloca (alloca_used | |
561 | + + home_len + dirlen); | |
562 | + if (use_alloca) | |
563 | + newp = alloca_account (home_len + dirlen, alloca_used); | |
564 | + else | |
565 | + { | |
566 | + newp = malloc (home_len + dirlen); | |
567 | + if (newp == NULL) | |
568 | + { | |
569 | + if (__builtin_expect (malloc_home_dir, 0)) | |
570 | + free (home_dir); | |
571 | + retval = GLOB_NOSPACE; | |
572 | + goto out; | |
573 | + } | |
574 | + } | |
575 | + | |
576 | mempcpy (mempcpy (newp, home_dir, home_len), | |
577 | &dirname[1], dirlen); | |
578 | + | |
579 | + if (__builtin_expect (malloc_dirname, 0)) | |
580 | + free (dirname); | |
581 | + | |
582 | dirname = newp; | |
583 | dirlen += home_len - 1; | |
584 | + malloc_dirname = !use_alloca; | |
585 | } | |
586 | dirname_modified = 1; | |
587 | } | |
588 | @@ -657,7 +760,8 @@ glob (pattern, flags, errfunc, pglob) | |
589 | else | |
590 | { | |
591 | char *end_name = strchr (dirname, '/'); | |
592 | - const char *user_name; | |
593 | + char *user_name; | |
594 | + int malloc_user_name = 0; | |
595 | const char *home_dir; | |
596 | char *unescape = NULL; | |
597 | ||
598 | @@ -677,7 +781,18 @@ glob (pattern, flags, errfunc, pglob) | |
599 | else | |
600 | { | |
601 | char *newp; | |
602 | - newp = (char *) __alloca (end_name - dirname); | |
603 | + if (__libc_use_alloca (alloca_used + (end_name - dirname))) | |
604 | + newp = alloca_account (end_name - dirname, alloca_used); | |
605 | + else | |
606 | + { | |
607 | + newp = malloc (end_name - dirname); | |
608 | + if (newp == NULL) | |
609 | + { | |
610 | + retval = GLOB_NOSPACE; | |
611 | + goto out; | |
612 | + } | |
613 | + malloc_user_name = 1; | |
614 | + } | |
615 | if (unescape != NULL) | |
616 | { | |
617 | char *p = mempcpy (newp, dirname + 1, | |
618 | @@ -714,6 +829,7 @@ glob (pattern, flags, errfunc, pglob) | |
619 | # if defined HAVE_GETPWNAM_R || defined _LIBC | |
620 | long int buflen = GETPW_R_SIZE_MAX (); | |
621 | char *pwtmpbuf; | |
622 | + int malloc_pwtmpbuf = 0; | |
623 | struct passwd pwbuf; | |
624 | int save = errno; | |
625 | ||
626 | @@ -723,7 +839,21 @@ glob (pattern, flags, errfunc, pglob) | |
627 | moderate value. */ | |
628 | buflen = 1024; | |
629 | # endif | |
630 | - pwtmpbuf = (char *) __alloca (buflen); | |
631 | + if (__libc_use_alloca (alloca_used + buflen)) | |
632 | + pwtmpbuf = alloca_account (buflen, alloca_used); | |
633 | + else | |
634 | + { | |
635 | + pwtmpbuf = malloc (buflen); | |
636 | + if (pwtmpbuf == NULL) | |
637 | + { | |
638 | + nomem_getpw: | |
639 | + if (__builtin_expect (malloc_user_name, 0)) | |
640 | + free (user_name); | |
641 | + retval = GLOB_NOSPACE; | |
642 | + goto out; | |
643 | + } | |
644 | + malloc_pwtmpbuf = 1; | |
645 | + } | |
646 | ||
647 | while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) | |
648 | { | |
649 | @@ -732,40 +862,77 @@ glob (pattern, flags, errfunc, pglob) | |
650 | p = NULL; | |
651 | break; | |
652 | } | |
653 | -# ifdef _LIBC | |
654 | - pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen); | |
655 | -# else | |
656 | - buflen *= 2; | |
657 | - pwtmpbuf = __alloca (buflen); | |
658 | -# endif | |
659 | + if (!malloc_pwtmpbuf | |
660 | + && __libc_use_alloca (alloca_used + 2 * buflen)) | |
661 | + pwtmpbuf = extend_alloca_account (pwtmpbuf, buflen, | |
662 | + 2 * buflen, alloca_used); | |
663 | + else | |
664 | + { | |
665 | + char *newp = realloc (malloc_pwtmpbuf ? pwtmpbuf : NULL, | |
666 | + 2 * buflen); | |
667 | + if (newp == NULL) | |
668 | + { | |
669 | + if (__builtin_expect (malloc_pwtmpbuf, 0)) | |
670 | + free (pwtmpbuf); | |
671 | + goto nomem_getpw; | |
672 | + } | |
673 | + pwtmpbuf = newp; | |
674 | + malloc_pwtmpbuf = 1; | |
675 | + } | |
676 | __set_errno (save); | |
677 | } | |
678 | # else | |
679 | p = getpwnam (user_name); | |
680 | # endif | |
681 | + | |
682 | + if (__builtin_expect (malloc_user_name, 0)) | |
683 | + free (user_name); | |
684 | + | |
685 | + /* If we found a home directory use this. */ | |
686 | if (p != NULL) | |
687 | - home_dir = p->pw_dir; | |
688 | + { | |
689 | + size_t home_len = strlen (p->pw_dir); | |
690 | + size_t rest_len = end_name == NULL ? 0 : strlen (end_name); | |
691 | + | |
692 | + if (__builtin_expect (malloc_dirname, 0)) | |
693 | + free (dirname); | |
694 | + malloc_dirname = 0; | |
695 | + | |
696 | + if (__libc_use_alloca (alloca_used + home_len + rest_len + 1)) | |
697 | + dirname = alloca_account (home_len + rest_len + 1, | |
698 | + alloca_used); | |
699 | + else | |
700 | + { | |
701 | + dirname = malloc (home_len + rest_len + 1); | |
702 | + if (dirname == NULL) | |
703 | + { | |
704 | + if (__builtin_expect (malloc_pwtmpbuf, 0)) | |
705 | + free (pwtmpbuf); | |
706 | + retval = GLOB_NOSPACE; | |
707 | + goto out; | |
708 | + } | |
709 | + malloc_dirname = 1; | |
710 | + } | |
711 | + *((char *) mempcpy (mempcpy (dirname, p->pw_dir, home_len), | |
712 | + end_name, rest_len)) = '\0'; | |
713 | + | |
714 | + dirlen = home_len + rest_len; | |
715 | + dirname_modified = 1; | |
716 | + | |
717 | + if (__builtin_expect (malloc_pwtmpbuf, 0)) | |
718 | + free (pwtmpbuf); | |
719 | + } | |
720 | else | |
721 | - home_dir = NULL; | |
722 | + { | |
723 | + if (__builtin_expect (malloc_pwtmpbuf, 0)) | |
724 | + free (pwtmpbuf); | |
725 | + | |
726 | + if (flags & GLOB_TILDE_CHECK) | |
727 | + /* We have to regard it as an error if we cannot find the | |
728 | + home directory. */ | |
729 | + return GLOB_NOMATCH; | |
730 | + } | |
731 | } | |
732 | - /* If we found a home directory use this. */ | |
733 | - if (home_dir != NULL) | |
734 | - { | |
735 | - char *newp; | |
736 | - size_t home_len = strlen (home_dir); | |
737 | - size_t rest_len = end_name == NULL ? 0 : strlen (end_name); | |
738 | - newp = (char *) __alloca (home_len + rest_len + 1); | |
739 | - *((char *) mempcpy (mempcpy (newp, home_dir, home_len), | |
740 | - end_name, rest_len)) = '\0'; | |
741 | - dirname = newp; | |
742 | - dirlen = home_len + rest_len; | |
743 | - dirname_modified = 1; | |
744 | - } | |
745 | - else | |
746 | - if (flags & GLOB_TILDE_CHECK) | |
747 | - /* We have to regard it as an error if we cannot find the | |
748 | - home directory. */ | |
749 | - return GLOB_NOMATCH; | |
750 | } | |
751 | # endif /* Not Amiga && not WINDOWS32. */ | |
752 | } | |
753 | @@ -899,7 +1066,7 @@ glob (pattern, flags, errfunc, pglob) | |
754 | status = glob_in_dir (filename, dirs.gl_pathv[i], | |
755 | ((flags | GLOB_APPEND) | |
756 | & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), | |
757 | - errfunc, pglob); | |
758 | + errfunc, pglob, alloca_used); | |
759 | if (status == GLOB_NOMATCH) | |
760 | /* No matches in this directory. Try the next. */ | |
761 | continue; | |
762 | @@ -1000,7 +1167,8 @@ glob (pattern, flags, errfunc, pglob) | |
763 | } | |
764 | if (dirname_modified) | |
765 | flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); | |
766 | - status = glob_in_dir (filename, dirname, flags, errfunc, pglob); | |
767 | + status = glob_in_dir (filename, dirname, flags, errfunc, pglob, | |
768 | + alloca_used); | |
769 | if (status != 0) | |
770 | { | |
771 | if (status == GLOB_NOMATCH && flags != orig_flags | |
772 | @@ -1063,7 +1231,11 @@ glob (pattern, flags, errfunc, pglob) | |
773 | sizeof (char *), collated_compare); | |
774 | } | |
775 | ||
776 | - return 0; | |
777 | + out: | |
778 | + if (__builtin_expect (malloc_dirname, 0)) | |
779 | + free (dirname); | |
780 | + | |
781 | + return retval; | |
782 | } | |
783 | #if defined _LIBC && !defined glob | |
784 | libc_hidden_def (glob) | |
785 | @@ -1273,7 +1445,7 @@ link_exists2_p (const char *dir, size_t dirlen, const char *fname, | |
786 | static int | |
787 | glob_in_dir (const char *pattern, const char *directory, int flags, | |
788 | int (*errfunc) (const char *, int), | |
789 | - glob_t *pglob) | |
790 | + glob_t *pglob, size_t alloca_used) | |
791 | { | |
792 | size_t dirlen = strlen (directory); | |
793 | void *stream = NULL; | |
794 | @@ -1288,11 +1460,12 @@ glob_in_dir (const char *pattern, const char *directory, int flags, | |
795 | struct globnames *names = &init_names; | |
796 | struct globnames *names_alloca = &init_names; | |
797 | size_t nfound = 0; | |
798 | - size_t allocasize = sizeof (init_names); | |
799 | size_t cur = 0; | |
800 | int meta; | |
801 | int save; | |
802 | ||
803 | + alloca_used += sizeof (init_names); | |
804 | + | |
805 | init_names.next = NULL; | |
806 | init_names.count = INITIAL_COUNT; | |
807 | ||
808 | @@ -1308,20 +1481,36 @@ glob_in_dir (const char *pattern, const char *directory, int flags, | |
809 | { | |
810 | /* Since we use the normal file functions we can also use stat() | |
811 | to verify the file is there. */ | |
812 | - struct stat st; | |
813 | - struct_stat64 st64; | |
814 | + union | |
815 | + { | |
816 | + struct stat st; | |
817 | + struct_stat64 st64; | |
818 | + } ust; | |
819 | size_t patlen = strlen (pattern); | |
820 | - char *fullname = (char *) __alloca (dirlen + 1 + patlen + 1); | |
821 | + int alloca_fullname = __libc_use_alloca (alloca_used | |
822 | + + dirlen + 1 + patlen + 1); | |
823 | + char *fullname; | |
824 | + if (alloca_fullname) | |
825 | + fullname = alloca_account (dirlen + 1 + patlen + 1, alloca_used); | |
826 | + else | |
827 | + { | |
828 | + fullname = malloc (dirlen + 1 + patlen + 1); | |
829 | + if (fullname == NULL) | |
830 | + return GLOB_NOSPACE; | |
831 | + } | |
832 | ||
833 | mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), | |
834 | "/", 1), | |
835 | pattern, patlen + 1); | |
836 | if ((__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) | |
837 | - ? (*pglob->gl_stat) (fullname, &st) | |
838 | - : __stat64 (fullname, &st64)) == 0) | |
839 | + ? (*pglob->gl_stat) (fullname, &ust.st) | |
840 | + : __stat64 (fullname, &ust.st64)) == 0) | |
841 | /* We found this file to be existing. Now tell the rest | |
842 | of the function to copy this name into the result. */ | |
843 | flags |= GLOB_NOCHECK; | |
844 | + | |
845 | + if (__builtin_expect (!alloca_fullname, 0)) | |
846 | + free (fullname); | |
847 | } | |
848 | else | |
849 | { | |
850 | @@ -1409,9 +1598,9 @@ glob_in_dir (const char *pattern, const char *directory, int flags, | |
851 | size_t size = (sizeof (struct globnames) | |
852 | + ((count - INITIAL_COUNT) | |
853 | * sizeof (char *))); | |
854 | - allocasize += size; | |
855 | - if (__libc_use_alloca (allocasize)) | |
856 | - newnames = names_alloca = __alloca (size); | |
857 | + if (__libc_use_alloca (alloca_used + size)) | |
858 | + newnames = names_alloca | |
859 | + = alloca_account (size, alloca_used); | |
860 | else if ((newnames = malloc (size)) | |
861 | == NULL) | |
862 | goto memory_error; |