1 2011-03-18 Ulrich Drepper <drepper@gmail.com>
3 * posix/fnmatch.c (fnmatch): Check size of pattern in wide
4 character representation.
5 Partly based on a patch by Tomas Hoger <thoger@redhat.com>.
7 2010-11-11 Andreas Schwab <schwab@redhat.com>
9 * posix/fnmatch_loop.c (NEW_PATTERN): Fix use of alloca.
10 * posix/Makefile (tests): Add $(objpfx)tst-fnmatch-mem.
11 (tst-fnmatch-ENV): Set MALLOC_TRACE.
12 ($(objpfx)tst-fnmatch-mem): New rule.
13 (generated): Add tst-fnmatch-mem and tst-fnmatch.mtrace.
14 * posix/tst-fnmatch.c (main): Call mtrace.
16 2010-08-09 Ulrich Drepper <drepper@redhat.com>
19 * posix/fnmatch.c: Keep track of alloca use and fall back on malloc.
20 * posix/fnmatch_loop.c: Likewise.
22 Index: glibc-2.12-2-gc4ccff1/posix/Makefile
23 ===================================================================
24 --- glibc-2.12-2-gc4ccff1.orig/posix/Makefile
25 +++ glibc-2.12-2-gc4ccff1/posix/Makefile
26 @@ -114,7 +114,8 @@ generated := $(addprefix wordexp-test-re
27 tst-rxspencer-mem tst-rxspencer.mtrace tst-getconf.out \
28 tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
29 bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \
30 - tst-vfork3-mem tst-vfork3.mtrace getconf.speclist
31 + tst-vfork3-mem tst-vfork3.mtrace getconf.speclist \
32 + tst-fnmatch-mem tst-fnmatch.mtrace
36 @@ -226,7 +227,7 @@ ifeq (no,$(cross-compiling))
37 tests: $(objpfx)bug-regex2-mem $(objpfx)bug-regex14-mem \
38 $(objpfx)bug-regex21-mem $(objpfx)tst-rxspencer-mem \
39 $(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem $(objpfx)tst-getconf.out \
40 - $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem
41 + $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem $(objpfx)tst-fnmatch-mem
42 xtests: $(objpfx)bug-ga2-mem
45 @@ -238,6 +239,11 @@ annexc-CFLAGS = -O
46 $(objpfx)annexc: annexc.c
49 +tst-fnmatch-ENV += MALLOC_TRACE=$(objpfx)tst-fnmatch.mtrace
51 +$(objpfx)tst-fnmatch-mem: $(objpfx)tst-fnmatch.out
52 + $(common-objpfx)malloc/mtrace $(objpfx)tst-fnmatch.mtrace > $@
54 bug-regex2-ENV = MALLOC_TRACE=$(objpfx)bug-regex2.mtrace
56 $(objpfx)bug-regex2-mem: $(objpfx)bug-regex2.out
57 Index: glibc-2.12-2-gc4ccff1/posix/fnmatch.c
58 ===================================================================
59 --- glibc-2.12-2-gc4ccff1.orig/posix/fnmatch.c
60 +++ glibc-2.12-2-gc4ccff1/posix/fnmatch.c
68 +# define alloca_account(size., var) alloca (size)
71 /* For platform which support the ISO C amendement 1 functionality we
72 support user defined character classes. */
73 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
74 @@ -330,8 +336,11 @@ fnmatch (pattern, string, flags)
78 + wchar_t *wpattern_malloc = NULL;
80 + wchar_t *wstring_malloc = NULL;
82 + size_t alloca_used = 0;
84 /* Convert the strings into wide characters. */
85 memset (&ps, '\0', sizeof (ps));
86 @@ -343,7 +352,8 @@ fnmatch (pattern, string, flags)
88 if (__builtin_expect (n < 1024, 1))
90 - wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
91 + wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
93 n = mbsrtowcs (wpattern, &p, n + 1, &ps);
94 if (__builtin_expect (n == (size_t) -1, 0))
96 @@ -365,8 +375,16 @@ fnmatch (pattern, string, flags)
97 XXX Do we have to set `errno' to something which mbsrtows hasn't
100 - wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
101 + if (__builtin_expect (n >= (size_t) -1 / sizeof (wchar_t), 0))
103 + __set_errno (ENOMEM);
106 + wpattern_malloc = wpattern
107 + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
108 assert (mbsinit (&ps));
109 + if (wpattern == NULL)
111 (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
114 @@ -379,13 +397,18 @@ fnmatch (pattern, string, flags)
116 if (__builtin_expect (n < 1024, 1))
118 - wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
119 + wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
121 n = mbsrtowcs (wstring, &p, n + 1, &ps);
122 if (__builtin_expect (n == (size_t) -1, 0))
123 - /* Something wrong.
124 - XXX Do we have to set `errno' to something which mbsrtows hasn't
128 + /* Something wrong.
129 + XXX Do we have to set `errno' to something which
130 + mbsrtows hasn't already done? */
132 + free (wpattern_malloc);
137 memset (&ps, '\0', sizeof (ps));
138 @@ -400,19 +423,38 @@ fnmatch (pattern, string, flags)
140 XXX Do we have to set `errno' to something which mbsrtows hasn't
143 - wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
145 + if (__builtin_expect (n >= (size_t) -1 / sizeof (wchar_t), 0))
147 + free (wpattern_malloc);
148 + __set_errno (ENOMEM);
152 + wstring_malloc = wstring
153 + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
154 + if (wstring == NULL)
156 + free (wpattern_malloc);
159 assert (mbsinit (&ps));
160 (void) mbsrtowcs (wstring, &string, n + 1, &ps);
163 - return internal_fnwmatch (wpattern, wstring, wstring + n,
164 - flags & FNM_PERIOD, flags, NULL);
165 + int res = internal_fnwmatch (wpattern, wstring, wstring + n,
166 + flags & FNM_PERIOD, flags, NULL,
169 + free (wstring_malloc);
170 + free (wpattern_malloc);
174 # endif /* mbstate_t and mbsrtowcs or _LIBC. */
176 return internal_fnmatch (pattern, string, string + strlen (string),
177 - flags & FNM_PERIOD, flags, NULL);
178 + flags & FNM_PERIOD, flags, NULL, 0);
182 Index: glibc-2.12-2-gc4ccff1/posix/fnmatch_loop.c
183 ===================================================================
184 --- glibc-2.12-2-gc4ccff1.orig/posix/fnmatch_loop.c
185 +++ glibc-2.12-2-gc4ccff1/posix/fnmatch_loop.c
186 @@ -28,22 +28,24 @@ struct STRUCT
187 it matches, nonzero if not. */
188 static int FCT (const CHAR *pattern, const CHAR *string,
189 const CHAR *string_end, int no_leading_period, int flags,
190 - struct STRUCT *ends)
191 + struct STRUCT *ends, size_t alloca_used)
193 static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
194 - const CHAR *string_end, int no_leading_period, int flags)
195 + const CHAR *string_end, int no_leading_period, int flags,
196 + size_t alloca_used)
198 static const CHAR *END (const CHAR *patternp) internal_function;
202 -FCT (pattern, string, string_end, no_leading_period, flags, ends)
203 +FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
206 const CHAR *string_end;
207 int no_leading_period;
210 + size_t alloca_used;
212 register const CHAR *p = pattern, *n = string;
214 @@ -67,10 +69,8 @@ FCT (pattern, string, string_end, no_lea
216 if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
220 - res = EXT (c, p, n, string_end, no_leading_period,
222 + int res = EXT (c, p, n, string_end, no_leading_period,
223 + flags, alloca_used);
227 @@ -99,10 +99,8 @@ FCT (pattern, string, string_end, no_lea
229 if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
233 - res = EXT (c, p, n, string_end, no_leading_period,
235 + int res = EXT (c, p, n, string_end, no_leading_period,
236 + flags, alloca_used);
240 @@ -191,7 +189,7 @@ FCT (pattern, string, string_end, no_lea
242 for (--p; n < endp; ++n, no_leading_period = 0)
243 if (FCT (p, n, string_end, no_leading_period, flags2,
245 + &end, alloca_used) == 0)
248 else if (c == L('/') && (flags & FNM_FILE_NAME))
249 @@ -200,7 +198,7 @@ FCT (pattern, string, string_end, no_lea
251 if (n < string_end && *n == L('/')
252 && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
254 + NULL, alloca_used) == 0))
258 @@ -214,7 +212,7 @@ FCT (pattern, string, string_end, no_lea
259 for (--p; n < endp; ++n, no_leading_period = 0)
260 if (FOLD ((UCHAR) *n) == c
261 && (FCT (p, n, string_end, no_leading_period, flags2,
263 + &end, alloca_used) == 0))
266 if (end.pattern == NULL)
267 @@ -749,7 +747,7 @@ FCT (pattern, string, string_end, no_lea
268 _NL_COLLATE_SYMB_EXTRAMB);
270 /* Locate the character in the hashing
273 hash = elem_hash (str, c1);
276 @@ -971,9 +969,8 @@ FCT (pattern, string, string_end, no_lea
278 if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
282 - res = EXT (c, p, n, string_end, no_leading_period, flags);
283 + int res = EXT (c, p, n, string_end, no_leading_period, flags,
288 @@ -1052,26 +1049,32 @@ END (const CHAR *pattern)
291 EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
292 - int no_leading_period, int flags)
293 + int no_leading_period, int flags, size_t alloca_used)
299 struct patternlist *next;
303 struct patternlist **lastp = &list;
304 size_t pattern_len = STRLEN (pattern);
305 + int any_malloced = 0;
310 /* Parse the pattern. Store the individual parts in the list. */
312 for (startp = p = pattern + 1; level >= 0; ++p)
314 - /* This is an invalid pattern. */
317 + /* This is an invalid pattern. */
321 else if (*p == L('['))
323 /* Handle brackets special. */
324 @@ -1088,8 +1091,11 @@ EXT (INT opt, const CHAR *pattern, const
325 /* Skip over all characters of the list. */
328 - /* This is no valid pattern. */
331 + /* This is no valid pattern. */
336 else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
337 || *p == L('!')) && p[1] == L('('))
338 @@ -1102,15 +1108,25 @@ EXT (INT opt, const CHAR *pattern, const
339 /* This means we found the end of the pattern. */
340 #define NEW_PATTERN \
341 struct patternlist *newp; \
343 - if (opt == L('?') || opt == L('@')) \
344 - newp = alloca (sizeof (struct patternlist) \
345 - + (pattern_len * sizeof (CHAR))); \
346 + size_t slen = (opt == L('?') || opt == L('@') \
347 + ? pattern_len : (p - startp + 1)); \
348 + slen = sizeof (struct patternlist) + (slen * sizeof (CHAR)); \
349 + int malloced = ! __libc_use_alloca (alloca_used + slen); \
350 + if (__builtin_expect (malloced, 0)) \
352 + newp = malloc (slen); \
353 + if (newp == NULL) \
358 + any_malloced = 1; \
361 - newp = alloca (sizeof (struct patternlist) \
362 - + ((p - startp + 1) * sizeof (CHAR))); \
363 - *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
364 + newp = alloca_account (slen, alloca_used); \
366 + newp->malloced = malloced; \
367 + *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \
371 @@ -1131,8 +1147,9 @@ EXT (INT opt, const CHAR *pattern, const
375 - if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0)
377 + if (FCT (p, string, string_end, no_leading_period, flags, NULL,
383 @@ -1143,7 +1160,7 @@ EXT (INT opt, const CHAR *pattern, const
385 if (FCT (list->str, string, rs, no_leading_period,
386 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
388 + NULL, alloca_used) == 0
389 /* This was successful. Now match the rest with the rest
391 && (FCT (p, rs, string_end,
392 @@ -1151,7 +1168,7 @@ EXT (INT opt, const CHAR *pattern, const
394 : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
395 flags & FNM_FILE_NAME
396 - ? flags : flags & ~FNM_PERIOD, NULL) == 0
397 + ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
398 /* This didn't work. Try the whole pattern. */
400 && FCT (pattern - 1, rs, string_end,
401 @@ -1160,18 +1177,21 @@ EXT (INT opt, const CHAR *pattern, const
402 : (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
404 flags & FNM_FILE_NAME
405 - ? flags : flags & ~FNM_PERIOD, NULL) == 0)))
406 + ? flags : flags & ~FNM_PERIOD, NULL,
407 + alloca_used) == 0)))
408 /* It worked. Signal success. */
412 while ((list = list->next) != NULL);
414 /* None of the patterns lead to a match. */
415 - return FNM_NOMATCH;
416 + retval = FNM_NOMATCH;
420 - if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0)
422 + if (FCT (p, string, string_end, no_leading_period, flags, NULL,
428 @@ -1183,13 +1203,14 @@ EXT (INT opt, const CHAR *pattern, const
429 if (FCT (STRCAT (list->str, p), string, string_end,
431 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
433 + NULL, alloca_used) == 0)
434 /* It worked. Signal success. */
437 while ((list = list->next) != NULL);
439 /* None of the patterns lead to a match. */
440 - return FNM_NOMATCH;
441 + retval = FNM_NOMATCH;
445 for (rs = string; rs <= string_end; ++rs)
446 @@ -1199,7 +1220,7 @@ EXT (INT opt, const CHAR *pattern, const
447 for (runp = list; runp != NULL; runp = runp->next)
448 if (FCT (runp->str, string, rs, no_leading_period,
449 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
451 + NULL, alloca_used) == 0)
454 /* If none of the patterns matched see whether the rest does. */
455 @@ -1209,21 +1230,34 @@ EXT (INT opt, const CHAR *pattern, const
457 : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
458 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
460 + NULL, alloca_used) == 0))
461 /* This is successful. */
466 /* None of the patterns together with the rest of the pattern
468 - return FNM_NOMATCH;
469 + retval = FNM_NOMATCH;
473 assert (! "Invalid extended matching operator");
482 + while (list != NULL)
484 + struct patternlist *old = list;
494 Index: glibc-2.12-2-gc4ccff1/posix/tst-fnmatch.c
495 ===================================================================
496 --- glibc-2.12-2-gc4ccff1.orig/posix/tst-fnmatch.c
497 +++ glibc-2.12-2-gc4ccff1/posix/tst-fnmatch.c
501 #include <sys/types.h>
505 static char *next_input (char **line, int first, int last);
506 @@ -46,6 +47,8 @@ main (void)
507 size_t escpatternlen = 0;
512 /* Read lines from stdin with the following format:
514 locale input-string match-string flags result