Patchwork Properly initialize glob structure with GLOB_BRACE|GLOB_DOOFFS

login
register
mail settings
Submitter Andreas Schwab
Date Oct. 20, 2016, 10:39 a.m.
Message ID <mvmtwc7mhi2.fsf@hawking.suse.de>
Download mbox | patch
Permalink /patch/16687/
State New
Headers show

Comments

Andreas Schwab - Oct. 20, 2016, 10:39 a.m.
When glob with GLOB_BRACE calls itself recusively on each word of the
brace expansion it doesn't handle GLOB_DOOFFS when initializing the glob
structure.

Andreas.

	[BZ #20707]
	* posix/glob.c (glob): Initialize pglob before checking for
	GLOB_BRACE.  Don't call glob recursively if pattern contains no
	valid brace expression despite GLOB_BRACE.
	* posix/globtest.sh: Test it.
---
 posix/glob.c      | 65 ++++++++++++++++++++++---------------------------------
 posix/globtest.sh | 16 ++++++++++++++
 2 files changed, 42 insertions(+), 39 deletions(-)

Patch

diff --git a/posix/glob.c b/posix/glob.c
index ea4b0b61eb..e357195a72 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -312,6 +312,28 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
        also makes all the code that uses gl_offs simpler. */
     pglob->gl_offs = 0;
 
+  if (!(flags & GLOB_APPEND))
+    {
+      pglob->gl_pathc = 0;
+      if (!(flags & GLOB_DOOFFS))
+	pglob->gl_pathv = NULL;
+      else
+	{
+	  size_t i;
+
+	  if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
+	    return GLOB_NOSPACE;
+
+	  pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
+					      * sizeof (char *));
+	  if (pglob->gl_pathv == NULL)
+	    return GLOB_NOSPACE;
+
+	  for (i = 0; i <= pglob->gl_offs; ++i)
+	    pglob->gl_pathv[i] = NULL;
+	}
+    }
+
   if (flags & GLOB_BRACE)
     {
       const char *begin;
@@ -359,14 +381,7 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 	    {
 	      onealt = (char *) malloc (pattern_len);
 	      if (onealt == NULL)
-		{
-		  if (!(flags & GLOB_APPEND))
-		    {
-		      pglob->gl_pathc = 0;
-		      pglob->gl_pathv = NULL;
-		    }
-		  return GLOB_NOSPACE;
-		}
+		return GLOB_NOSPACE;
 	    }
 
 	  /* We know the prefix for all sub-patterns.  */
@@ -383,7 +398,8 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 	      if (__glibc_unlikely (!alloca_onealt))
 #endif
 		free (onealt);
-	      return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
+	      flags &= ~GLOB_BRACE;
+	      goto no_brace;
 	    }
 
 	  /* Now find the end of the whole brace expression.  */
@@ -404,14 +420,6 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 	     points past the final }.  We will accumulate result names from
 	     recursive runs for each brace alternative in the buffer using
 	     GLOB_APPEND.  */
-
-	  if (!(flags & GLOB_APPEND))
-	    {
-	      /* This call is to set a new vector, so clear out the
-		 vector so we can append to it.  */
-	      pglob->gl_pathc = 0;
-	      pglob->gl_pathv = NULL;
-	    }
 	  firstc = pglob->gl_pathc;
 
 	  p = begin + 1;
@@ -463,28 +471,7 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 	}
     }
 
-  if (!(flags & GLOB_APPEND))
-    {
-      pglob->gl_pathc = 0;
-      if (!(flags & GLOB_DOOFFS))
-	pglob->gl_pathv = NULL;
-      else
-	{
-	  size_t i;
-
-	  if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *))
-	    return GLOB_NOSPACE;
-
-	  pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1)
-					      * sizeof (char *));
-	  if (pglob->gl_pathv == NULL)
-	    return GLOB_NOSPACE;
-
-	  for (i = 0; i <= pglob->gl_offs; ++i)
-	    pglob->gl_pathv[i] = NULL;
-	}
-    }
-
+ no_brace:
   oldcount = pglob->gl_pathc + pglob->gl_offs;
 
   /* Find the filename.  */
diff --git a/posix/globtest.sh b/posix/globtest.sh
index 73fe11bd76..e280f7d2b3 100755
--- a/posix/globtest.sh
+++ b/posix/globtest.sh
@@ -794,6 +794,22 @@  if test $failed -ne 0; then
   result=1
 fi
 
+# Test GLOB_BRACE and GLIB_DOOFFS with malloc checking
+failed=0
+${test_wrapper_env} \
+MALLOC_PERTURB_=65 \
+${test_via_rtld_prefix} \
+${common_objpfx}posix/globtest -b -o "$testdir" "file{1,2}" > $testout || failed=1
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`abc'
+`file1'
+`file2'
+EOF
+if test $failed -ne 0; then
+  echo "GLOB_BRACE+GLOB_DOOFFS test failed" >> $logfile
+  result=1
+fi
+
 if test $result -eq 0; then
     chmod 777 $testdir/noread
     rm -fr $testdir $testout