diff options
author | Ulrich Drepper <drepper@redhat.com> | 2010-08-09 21:09:37 -0700 |
---|---|---|
committer | Andreas Schwab <schwab@redhat.com> | 2010-12-01 15:35:18 +0100 |
commit | f925c225e4c523c00decc78ad023feb29c533d84 (patch) | |
tree | acbb09098df1fde1db31c656898fe6751db7e47c /posix/fnmatch.c | |
parent | 4838fdcfdc95f0dacda6463c2dd81d11ee9e0414 (diff) | |
download | glibc-f925c225e4c523c00decc78ad023feb29c533d84.tar.gz glibc-f925c225e4c523c00decc78ad023feb29c533d84.tar.xz glibc-f925c225e4c523c00decc78ad023feb29c533d84.zip |
Avoid too much stack use in fnmatch.
(cherry picked from commit f15ce4d8dc139523fe0c273580b604b2453acba6
Diffstat (limited to 'posix/fnmatch.c')
-rw-r--r-- | posix/fnmatch.c | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/posix/fnmatch.c b/posix/fnmatch.c index 4baef9e69b..0af5ee6b1e 100644 --- a/posix/fnmatch.c +++ b/posix/fnmatch.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2007 +/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2007,2010 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -41,6 +41,12 @@ # include <stdlib.h> #endif +#ifdef _LIBC +# include <alloca.h> +#else +# define alloca_account(size., var) alloca (size) +#endif + /* For platform which support the ISO C amendement 1 functionality we support user defined character classes. */ #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) @@ -330,8 +336,11 @@ fnmatch (pattern, string, flags) mbstate_t ps; size_t n; const char *p; + wchar_t *wpattern_malloc = NULL; wchar_t *wpattern; + wchar_t *wstring_malloc = NULL; wchar_t *wstring; + size_t alloca_used = 0; /* Convert the strings into wide characters. */ memset (&ps, '\0', sizeof (ps)); @@ -343,7 +352,8 @@ fnmatch (pattern, string, flags) #endif if (__builtin_expect (n < 1024, 1)) { - wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), + alloca_used); n = mbsrtowcs (wpattern, &p, n + 1, &ps); if (__builtin_expect (n == (size_t) -1, 0)) /* Something wrong. @@ -365,8 +375,11 @@ fnmatch (pattern, string, flags) XXX Do we have to set `errno' to something which mbsrtows hasn't already done? */ return -1; - wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + wpattern_malloc = wpattern + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); assert (mbsinit (&ps)); + if (wpattern == NULL) + return -2; (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps); } @@ -379,13 +392,18 @@ fnmatch (pattern, string, flags) p = string; if (__builtin_expect (n < 1024, 1)) { - wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), + alloca_used); n = mbsrtowcs (wstring, &p, n + 1, &ps); if (__builtin_expect (n == (size_t) -1, 0)) - /* Something wrong. - XXX Do we have to set `errno' to something which mbsrtows hasn't - already done? */ - return -1; + { + /* Something wrong. + XXX Do we have to set `errno' to something which + mbsrtows hasn't already done? */ + free_return: + free (wpattern_malloc); + return -1; + } if (p) { memset (&ps, '\0', sizeof (ps)); @@ -400,19 +418,32 @@ fnmatch (pattern, string, flags) /* Something wrong. XXX Do we have to set `errno' to something which mbsrtows hasn't already done? */ - return -1; - wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + goto free_return; + + wstring_malloc = wstring + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); + if (wstring == NULL) + { + free (wpattern_malloc); + return -2; + } assert (mbsinit (&ps)); (void) mbsrtowcs (wstring, &string, n + 1, &ps); } - return internal_fnwmatch (wpattern, wstring, wstring + n, - flags & FNM_PERIOD, flags, NULL); + int res = internal_fnwmatch (wpattern, wstring, wstring + n, + flags & FNM_PERIOD, flags, NULL, + alloca_used); + + free (wstring_malloc); + free (wpattern_malloc); + + return res; } # endif /* mbstate_t and mbsrtowcs or _LIBC. */ return internal_fnmatch (pattern, string, string + strlen (string), - flags & FNM_PERIOD, flags, NULL); + flags & FNM_PERIOD, flags, NULL, 0); } # ifdef _LIBC |