Blame SOURCES/glibc-rh681054.patch

b40826
2011-03-18  Ulrich Drepper  <drepper@gmail.com>
b40826
b40826
	* posix/fnmatch.c (fnmatch): Check size of pattern in wide
b40826
	character representation.
b40826
	Partly based on a patch by Tomas Hoger <thoger@redhat.com>.
b40826
b40826
2010-11-11  Andreas Schwab  <schwab@redhat.com>
b40826
b40826
	* posix/fnmatch_loop.c (NEW_PATTERN): Fix use of alloca.
b40826
	* posix/Makefile (tests): Add $(objpfx)tst-fnmatch-mem.
b40826
	(tst-fnmatch-ENV): Set MALLOC_TRACE.
b40826
	($(objpfx)tst-fnmatch-mem): New rule.
b40826
	(generated): Add tst-fnmatch-mem and tst-fnmatch.mtrace.
b40826
	* posix/tst-fnmatch.c (main): Call mtrace.
b40826
b40826
2010-08-09  Ulrich Drepper  <drepper@redhat.com>
b40826
b40826
	[BZ #11883]
b40826
	* posix/fnmatch.c: Keep track of alloca use and fall back on malloc.
b40826
	* posix/fnmatch_loop.c: Likewise.
b40826
b40826
Index: glibc-2.12-2-gc4ccff1/posix/Makefile
b40826
===================================================================
b40826
--- glibc-2.12-2-gc4ccff1.orig/posix/Makefile
b40826
+++ glibc-2.12-2-gc4ccff1/posix/Makefile
b40826
@@ -114,7 +114,8 @@ generated := $(addprefix wordexp-test-re
b40826
 	     tst-rxspencer-mem tst-rxspencer.mtrace tst-getconf.out \
b40826
 	     tst-pcre-mem tst-pcre.mtrace tst-boost-mem tst-boost.mtrace \
b40826
 	     bug-ga2.mtrace bug-ga2-mem bug-glob2.mtrace bug-glob2-mem \
b40826
-	     tst-vfork3-mem tst-vfork3.mtrace getconf.speclist
b40826
+	     tst-vfork3-mem tst-vfork3.mtrace getconf.speclist \
b40826
+	     tst-fnmatch-mem tst-fnmatch.mtrace
b40826
 
b40826
 include ../Rules
b40826
 
b40826
@@ -226,7 +227,7 @@ ifeq (no,$(cross-compiling))
b40826
 tests: $(objpfx)bug-regex2-mem $(objpfx)bug-regex14-mem \
b40826
   $(objpfx)bug-regex21-mem $(objpfx)tst-rxspencer-mem \
b40826
   $(objpfx)tst-pcre-mem $(objpfx)tst-boost-mem $(objpfx)tst-getconf.out \
b40826
-  $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem
b40826
+  $(objpfx)bug-glob2-mem $(objpfx)tst-vfork3-mem $(objpfx)tst-fnmatch-mem
b40826
 xtests: $(objpfx)bug-ga2-mem
b40826
 endif
b40826
 
b40826
@@ -238,6 +239,11 @@ annexc-CFLAGS = -O
b40826
 $(objpfx)annexc: annexc.c
b40826
 	$(native-compile)
b40826
 
b40826
+tst-fnmatch-ENV += MALLOC_TRACE=$(objpfx)tst-fnmatch.mtrace
b40826
+
b40826
+$(objpfx)tst-fnmatch-mem: $(objpfx)tst-fnmatch.out
b40826
+	$(common-objpfx)malloc/mtrace $(objpfx)tst-fnmatch.mtrace > $@
b40826
+
b40826
 bug-regex2-ENV = MALLOC_TRACE=$(objpfx)bug-regex2.mtrace
b40826
 
b40826
 $(objpfx)bug-regex2-mem: $(objpfx)bug-regex2.out
b40826
Index: glibc-2.12-2-gc4ccff1/posix/fnmatch.c
b40826
===================================================================
b40826
--- glibc-2.12-2-gc4ccff1.orig/posix/fnmatch.c
b40826
+++ glibc-2.12-2-gc4ccff1/posix/fnmatch.c
b40826
@@ -41,6 +41,12 @@
b40826
 # include <stdlib.h>
b40826
 #endif
b40826
 
b40826
+#ifdef _LIBC
b40826
+# include <alloca.h>
b40826
+#else
b40826
+# define alloca_account(size., var) alloca (size)
b40826
+#endif
b40826
+
b40826
 /* For platform which support the ISO C amendement 1 functionality we
b40826
    support user defined character classes.  */
b40826
 #if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
b40826
@@ -330,8 +336,11 @@ fnmatch (pattern, string, flags)
b40826
       mbstate_t ps;
b40826
       size_t n;
b40826
       const char *p;
b40826
+      wchar_t *wpattern_malloc = NULL;
b40826
       wchar_t *wpattern;
b40826
+      wchar_t *wstring_malloc = NULL;
b40826
       wchar_t *wstring;
b40826
+      size_t alloca_used = 0;
b40826
 
b40826
       /* Convert the strings into wide characters.  */
b40826
       memset (&ps, '\0', sizeof (ps));
b40826
@@ -343,7 +352,8 @@ fnmatch (pattern, string, flags)
b40826
 #endif
b40826
       if (__builtin_expect (n < 1024, 1))
b40826
 	{
b40826
-	  wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
b40826
+	  wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
b40826
+						 alloca_used);
b40826
 	  n = mbsrtowcs (wpattern, &p, n + 1, &ps);
b40826
 	  if (__builtin_expect (n == (size_t) -1, 0))
b40826
 	    /* Something wrong.
b40826
@@ -365,8 +375,16 @@ fnmatch (pattern, string, flags)
b40826
 	       XXX Do we have to set `errno' to something which mbsrtows hasn't
b40826
 	       already done?  */
b40826
 	    return -1;
b40826
-	  wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
b40826
+	  if (__builtin_expect (n >= (size_t) -1 / sizeof (wchar_t), 0))
b40826
+	    {
b40826
+	      __set_errno (ENOMEM);
b40826
+	      return -2;
b40826
+	    }
b40826
+	  wpattern_malloc = wpattern
b40826
+	    = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
b40826
 	  assert (mbsinit (&ps);;
b40826
+	  if (wpattern == NULL)
b40826
+	    return -2;
b40826
 	  (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
b40826
 	}
b40826
 
b40826
@@ -379,13 +397,18 @@ fnmatch (pattern, string, flags)
b40826
       p = string;
b40826
       if (__builtin_expect (n < 1024, 1))
b40826
 	{
b40826
-	  wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
b40826
+	  wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
b40826
+						alloca_used);
b40826
 	  n = mbsrtowcs (wstring, &p, n + 1, &ps);
b40826
 	  if (__builtin_expect (n == (size_t) -1, 0))
b40826
-	    /* Something wrong.
b40826
-	       XXX Do we have to set `errno' to something which mbsrtows hasn't
b40826
-	       already done?  */
b40826
-	    return -1;
b40826
+	    {
b40826
+	      /* Something wrong.
b40826
+		 XXX Do we have to set `errno' to something which
b40826
+		 mbsrtows hasn't already done?  */
b40826
+	    free_return:
b40826
+	      free (wpattern_malloc);
b40826
+	      return -1;
b40826
+	    }
b40826
 	  if (p)
b40826
 	    {
b40826
 	      memset (&ps, '\0', sizeof (ps));
b40826
@@ -400,19 +423,38 @@ fnmatch (pattern, string, flags)
b40826
 	    /* Something wrong.
b40826
 	       XXX Do we have to set `errno' to something which mbsrtows hasn't
b40826
 	       already done?  */
b40826
-	    return -1;
b40826
-	  wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t));
b40826
+	    goto free_return;
b40826
+	  if (__builtin_expect (n >= (size_t) -1 / sizeof (wchar_t), 0))
b40826
+	    {
b40826
+	      free (wpattern_malloc);
b40826
+	      __set_errno (ENOMEM);
b40826
+	      return -2;
b40826
+	    }
b40826
+
b40826
+	  wstring_malloc = wstring
b40826
+	    = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
b40826
+	  if (wstring == NULL)
b40826
+	    {
b40826
+	      free (wpattern_malloc);
b40826
+	      return -2;
b40826
+	    }
b40826
 	  assert (mbsinit (&ps);;
b40826
 	  (void) mbsrtowcs (wstring, &string, n + 1, &ps);
b40826
 	}
b40826
 
b40826
-      return internal_fnwmatch (wpattern, wstring, wstring + n,
b40826
-				flags & FNM_PERIOD, flags, NULL);
b40826
+      int res = internal_fnwmatch (wpattern, wstring, wstring + n,
b40826
+				   flags & FNM_PERIOD, flags, NULL,
b40826
+				   alloca_used);
b40826
+
b40826
+      free (wstring_malloc);
b40826
+      free (wpattern_malloc);
b40826
+
b40826
+      return res;
b40826
     }
b40826
 # endif  /* mbstate_t and mbsrtowcs or _LIBC.  */
b40826
 
b40826
   return internal_fnmatch (pattern, string, string + strlen (string),
b40826
-			   flags & FNM_PERIOD, flags, NULL);
b40826
+			   flags & FNM_PERIOD, flags, NULL, 0);
b40826
 }
b40826
 
b40826
 # ifdef _LIBC
b40826
Index: glibc-2.12-2-gc4ccff1/posix/fnmatch_loop.c
b40826
===================================================================
b40826
--- glibc-2.12-2-gc4ccff1.orig/posix/fnmatch_loop.c
b40826
+++ glibc-2.12-2-gc4ccff1/posix/fnmatch_loop.c
b40826
@@ -28,22 +28,24 @@ struct STRUCT
b40826
    it matches, nonzero if not.  */
b40826
 static int FCT (const CHAR *pattern, const CHAR *string,
b40826
 		const CHAR *string_end, int no_leading_period, int flags,
b40826
-		struct STRUCT *ends)
b40826
+		struct STRUCT *ends, size_t alloca_used)
b40826
      internal_function;
b40826
 static int EXT (INT opt, const CHAR *pattern, const CHAR *string,
b40826
-		const CHAR *string_end, int no_leading_period, int flags)
b40826
+		const CHAR *string_end, int no_leading_period, int flags,
b40826
+		size_t alloca_used)
b40826
      internal_function;
b40826
 static const CHAR *END (const CHAR *patternp) internal_function;
b40826
 
b40826
 static int
b40826
 internal_function
b40826
-FCT (pattern, string, string_end, no_leading_period, flags, ends)
b40826
+FCT (pattern, string, string_end, no_leading_period, flags, ends, alloca_used)
b40826
      const CHAR *pattern;
b40826
      const CHAR *string;
b40826
      const CHAR *string_end;
b40826
      int no_leading_period;
b40826
      int flags;
b40826
      struct STRUCT *ends;
b40826
+     size_t alloca_used;
b40826
 {
b40826
   register const CHAR *p = pattern, *n = string;
b40826
   register UCHAR c;
b40826
@@ -67,10 +69,8 @@ FCT (pattern, string, string_end, no_lea
b40826
 	case L('?'):
b40826
 	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
b40826
 	    {
b40826
-	      int res;
b40826
-
b40826
-	      res = EXT (c, p, n, string_end, no_leading_period,
b40826
-			 flags);
b40826
+	      int res = EXT (c, p, n, string_end, no_leading_period,
b40826
+			     flags, alloca_used);
b40826
 	      if (res != -1)
b40826
 		return res;
b40826
 	    }
b40826
@@ -99,10 +99,8 @@ FCT (pattern, string, string_end, no_lea
b40826
 	case L('*'):
b40826
 	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
b40826
 	    {
b40826
-	      int res;
b40826
-
b40826
-	      res = EXT (c, p, n, string_end, no_leading_period,
b40826
-			 flags);
b40826
+	      int res = EXT (c, p, n, string_end, no_leading_period,
b40826
+			     flags, alloca_used);
b40826
 	      if (res != -1)
b40826
 		return res;
b40826
 	    }
b40826
@@ -191,7 +189,7 @@ FCT (pattern, string, string_end, no_lea
b40826
 
b40826
 		  for (--p; n < endp; ++n, no_leading_period = 0)
b40826
 		    if (FCT (p, n, string_end, no_leading_period, flags2,
b40826
-			     &end) == 0)
b40826
+			     &end, alloca_used) == 0)
b40826
 		      goto found;
b40826
 		}
b40826
 	      else if (c == L('/') && (flags & FNM_FILE_NAME))
b40826
@@ -200,7 +198,7 @@ FCT (pattern, string, string_end, no_lea
b40826
 		    ++n;
b40826
 		  if (n < string_end && *n == L('/')
b40826
 		      && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags,
b40826
-			       NULL) == 0))
b40826
+			       NULL, alloca_used) == 0))
b40826
 		    return 0;
b40826
 		}
b40826
 	      else
b40826
@@ -214,7 +212,7 @@ FCT (pattern, string, string_end, no_lea
b40826
 		  for (--p; n < endp; ++n, no_leading_period = 0)
b40826
 		    if (FOLD ((UCHAR) *n) == c
b40826
 			&& (FCT (p, n, string_end, no_leading_period, flags2,
b40826
-				 &end) == 0))
b40826
+				 &end, alloca_used) == 0))
b40826
 		      {
b40826
 		      found:
b40826
 			if (end.pattern == NULL)
b40826
@@ -749,7 +747,7 @@ FCT (pattern, string, string_end, no_lea
b40826
 					       _NL_COLLATE_SYMB_EXTRAMB);
b40826
 
b40826
 				/* Locate the character in the hashing
b40826
-                                   table.  */
b40826
+				   table.  */
b40826
 				hash = elem_hash (str, c1);
b40826
 
b40826
 				idx = 0;
b40826
@@ -971,9 +969,8 @@ FCT (pattern, string, string_end, no_lea
b40826
 	case L('!'):
b40826
 	  if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(')
b40826
 	    {
b40826
-	      int res;
b40826
-
b40826
-	      res = EXT (c, p, n, string_end, no_leading_period, flags);
b40826
+	      int res = EXT (c, p, n, string_end, no_leading_period, flags,
b40826
+			     alloca_used);
b40826
 	      if (res != -1)
b40826
 		return res;
b40826
 	    }
b40826
@@ -1052,26 +1049,32 @@ END (const CHAR *pattern)
b40826
 static int
b40826
 internal_function
b40826
 EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end,
b40826
-     int no_leading_period, int flags)
b40826
+     int no_leading_period, int flags, size_t alloca_used)
b40826
 {
b40826
   const CHAR *startp;
b40826
   int level;
b40826
   struct patternlist
b40826
   {
b40826
     struct patternlist *next;
b40826
+    CHAR malloced;
b40826
     CHAR str[0];
b40826
   } *list = NULL;
b40826
   struct patternlist **lastp = &list;
b40826
   size_t pattern_len = STRLEN (pattern);
b40826
+  int any_malloced = 0;
b40826
   const CHAR *p;
b40826
   const CHAR *rs;
b40826
+  int retval = 0;
b40826
 
b40826
   /* Parse the pattern.  Store the individual parts in the list.  */
b40826
   level = 0;
b40826
   for (startp = p = pattern + 1; level >= 0; ++p)
b40826
     if (*p == L('\0'))
b40826
-      /* This is an invalid pattern.  */
b40826
-      return -1;
b40826
+      {
b40826
+	/* This is an invalid pattern.  */
b40826
+	retval = -1;
b40826
+	goto out;
b40826
+      }
b40826
     else if (*p == L('['))
b40826
       {
b40826
 	/* Handle brackets special.  */
b40826
@@ -1088,8 +1091,11 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 	/* Skip over all characters of the list.  */
b40826
 	while (*p != L(']'))
b40826
 	  if (*p++ == L('\0'))
b40826
-	    /* This is no valid pattern.  */
b40826
-	    return -1;
b40826
+	    {
b40826
+	      /* This is no valid pattern.  */
b40826
+	      retval = -1;
b40826
+	      goto out;
b40826
+	    }
b40826
       }
b40826
     else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
b40826
 	      || *p == L('!')) && p[1] == L('('))
b40826
@@ -1102,15 +1108,25 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 	    /* This means we found the end of the pattern.  */
b40826
 #define NEW_PATTERN \
b40826
 	    struct patternlist *newp;					      \
b40826
-									      \
b40826
-	    if (opt == L('?') || opt == L('@'))				      \
b40826
-	      newp = alloca (sizeof (struct patternlist)		      \
b40826
-			     + (pattern_len * sizeof (CHAR)));		      \
b40826
+	    size_t slen = (opt == L('?') || opt == L('@')		      \
b40826
+			   ? pattern_len : (p - startp + 1));		      \
b40826
+	    slen = sizeof (struct patternlist) + (slen * sizeof (CHAR));      \
b40826
+	    int malloced = ! __libc_use_alloca (alloca_used + slen);	      \
b40826
+	    if (__builtin_expect (malloced, 0))				      \
b40826
+	      {								      \
b40826
+		newp = malloc (slen);					      \
b40826
+		if (newp == NULL)					      \
b40826
+		  {							      \
b40826
+		    retval = -2;					      \
b40826
+		    goto out;						      \
b40826
+		  }							      \
b40826
+		any_malloced = 1;					      \
b40826
+	      }								      \
b40826
 	    else							      \
b40826
-	      newp = alloca (sizeof (struct patternlist)		      \
b40826
-			     + ((p - startp + 1) * sizeof (CHAR)));	      \
b40826
-	    *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0');    \
b40826
+	      newp = alloca_account (slen, alloca_used);		      \
b40826
 	    newp->next = NULL;						      \
b40826
+	    newp->malloced = malloced;					      \
b40826
+	    *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0');    \
b40826
 	    *lastp = newp;						      \
b40826
 	    lastp = &newp->next
b40826
 	    NEW_PATTERN;
b40826
@@ -1131,8 +1147,9 @@ EXT (INT opt, const CHAR *pattern, const
b40826
   switch (opt)
b40826
     {
b40826
     case L('*'):
b40826
-      if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0)
b40826
-	return 0;
b40826
+      if (FCT (p, string, string_end, no_leading_period, flags, NULL,
b40826
+	       alloca_used) == 0)
b40826
+	goto success;
b40826
       /* FALLTHROUGH */
b40826
 
b40826
     case L('+'):
b40826
@@ -1143,7 +1160,7 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 	       current pattern.  */
b40826
 	    if (FCT (list->str, string, rs, no_leading_period,
b40826
 		     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
b40826
-		     NULL) == 0
b40826
+		     NULL, alloca_used) == 0
b40826
 		/* This was successful.  Now match the rest with the rest
b40826
 		   of the pattern.  */
b40826
 		&& (FCT (p, rs, string_end,
b40826
@@ -1151,7 +1168,7 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 			 ? no_leading_period
b40826
 			 : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
b40826
 			 flags & FNM_FILE_NAME
b40826
-			 ? flags : flags & ~FNM_PERIOD, NULL) == 0
b40826
+			 ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0
b40826
 		    /* This didn't work.  Try the whole pattern.  */
b40826
 		    || (rs != string
b40826
 			&& FCT (pattern - 1, rs, string_end,
b40826
@@ -1160,18 +1177,21 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 				: (rs[-1] == '/' && NO_LEADING_PERIOD (flags)
b40826
 				   ? 1 : 0),
b40826
 				flags & FNM_FILE_NAME
b40826
-				? flags : flags & ~FNM_PERIOD, NULL) == 0)))
b40826
+				? flags : flags & ~FNM_PERIOD, NULL,
b40826
+				alloca_used) == 0)))
b40826
 	      /* It worked.  Signal success.  */
b40826
-	      return 0;
b40826
+	      goto success;
b40826
 	}
b40826
       while ((list = list->next) != NULL);
b40826
 
b40826
       /* None of the patterns lead to a match.  */
b40826
-      return FNM_NOMATCH;
b40826
+      retval = FNM_NOMATCH;
b40826
+      break;
b40826
 
b40826
     case L('?'):
b40826
-      if (FCT (p, string, string_end, no_leading_period, flags, NULL) == 0)
b40826
-	return 0;
b40826
+      if (FCT (p, string, string_end, no_leading_period, flags, NULL,
b40826
+	       alloca_used) == 0)
b40826
+	goto success;
b40826
       /* FALLTHROUGH */
b40826
 
b40826
     case L('@'):
b40826
@@ -1183,13 +1203,14 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 	if (FCT (STRCAT (list->str, p), string, string_end,
b40826
 		 no_leading_period,
b40826
 		 flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
b40826
-		 NULL) == 0)
b40826
+		 NULL, alloca_used) == 0)
b40826
 	  /* It worked.  Signal success.  */
b40826
-	  return 0;
b40826
+	  goto success;
b40826
       while ((list = list->next) != NULL);
b40826
 
b40826
       /* None of the patterns lead to a match.  */
b40826
-      return FNM_NOMATCH;
b40826
+      retval = FNM_NOMATCH;
b40826
+      break;
b40826
 
b40826
     case L('!'):
b40826
       for (rs = string; rs <= string_end; ++rs)
b40826
@@ -1199,7 +1220,7 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 	  for (runp = list; runp != NULL; runp = runp->next)
b40826
 	    if (FCT (runp->str, string, rs,  no_leading_period,
b40826
 		     flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
b40826
-		     NULL) == 0)
b40826
+		     NULL, alloca_used) == 0)
b40826
 	      break;
b40826
 
b40826
 	  /* If none of the patterns matched see whether the rest does.  */
b40826
@@ -1209,21 +1230,34 @@ EXT (INT opt, const CHAR *pattern, const
b40826
 		       ? no_leading_period
b40826
 		       : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0,
b40826
 		       flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD,
b40826
-		       NULL) == 0))
b40826
+		       NULL, alloca_used) == 0))
b40826
 	    /* This is successful.  */
b40826
-	    return 0;
b40826
+	    goto success;
b40826
 	}
b40826
 
b40826
       /* None of the patterns together with the rest of the pattern
b40826
 	 lead to a match.  */
b40826
-      return FNM_NOMATCH;
b40826
+      retval = FNM_NOMATCH;
b40826
+      break;
b40826
 
b40826
     default:
b40826
       assert (! "Invalid extended matching operator");
b40826
+      retval = -1;
b40826
       break;
b40826
     }
b40826
 
b40826
-  return -1;
b40826
+ success:
b40826
+ out:
b40826
+  if (any_malloced)
b40826
+    while (list != NULL)
b40826
+      {
b40826
+	struct patternlist *old = list;
b40826
+	list = list->next;
b40826
+	if (old->malloced)
b40826
+	  free (old);
b40826
+      }
b40826
+
b40826
+  return retval;
b40826
 }
b40826
 
b40826
 
b40826
Index: glibc-2.12-2-gc4ccff1/posix/tst-fnmatch.c
b40826
===================================================================
b40826
--- glibc-2.12-2-gc4ccff1.orig/posix/tst-fnmatch.c
b40826
+++ glibc-2.12-2-gc4ccff1/posix/tst-fnmatch.c
b40826
@@ -25,6 +25,7 @@
b40826
 #include <stdlib.h>
b40826
 #include <string.h>
b40826
 #include <sys/types.h>
b40826
+#include <mcheck.h>
b40826
 
b40826
 
b40826
 static char *next_input (char **line, int first, int last);
b40826
@@ -46,6 +47,8 @@ main (void)
b40826
   size_t escpatternlen = 0;
b40826
   int nr = 0;
b40826
 
b40826
+  mtrace ();
b40826
+
b40826
   /* Read lines from stdin with the following format:
b40826
 
b40826
        locale  input-string  match-string  flags  result