about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2010-03-24 11:58:05 -0700
committerUlrich Drepper <drepper@redhat.com>2010-03-24 11:58:05 -0700
commit8f2e39941309c1a590e71b9a8035dbbc7e587fae (patch)
tree99eaa2aade2538519497d013f2582b3c10fbec48
parent4ad43b62d6b893e73d5af72565f23c064b9c59b5 (diff)
downloadglibc-8f2e39941309c1a590e71b9a8035dbbc7e587fae.tar.gz
glibc-8f2e39941309c1a590e71b9a8035dbbc7e587fae.tar.xz
glibc-8f2e39941309c1a590e71b9a8035dbbc7e587fae.zip
Fix glob with empty pattern
-rw-r--r--ChangeLog6
-rw-r--r--posix/glob.c48
-rw-r--r--posix/tst-gnuglob.c75
3 files changed, 87 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index 9a2b2ca64c..87d8d57ae1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2010-03-24  Ulrich Drepper  <drepper@redhat.com>
+	    Andreas Schwab  <andreas@redhat.com>
+
+	* posix/glob.c (glob): Clean up gl_pathc and gl_pathv earlier.
+	If pattern is "" bail out early
+
 2010-03-23  Jakub Jelinek  <jakub@redhat.com>
 
 	* elf/dl-lookup.c (do_lookup_x): If tab->entries is NULL,
diff --git a/posix/glob.c b/posix/glob.c
index 73081ece66..3ae055d430 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008
+/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -418,6 +418,24 @@ glob (pattern, flags, errfunc, pglob)
 	}
     }
 
+  if (!(flags & GLOB_APPEND))
+    {
+      pglob->gl_pathc = 0;
+      if (!(flags & GLOB_DOOFFS))
+	pglob->gl_pathv = NULL;
+      else
+	{
+	  size_t i;
+	  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;
+	}
+    }
+
   /* Find the filename.  */
   filename = strrchr (pattern, '/');
 #if defined __MSDOS__ || defined WINDOWS32
@@ -445,6 +463,12 @@ glob (pattern, flags, errfunc, pglob)
 	}
       else
 	{
+	  if (__builtin_expect (pattern[0] == '\0', 0))
+	    {
+	      dirs.gl_pathv = NULL;
+	      goto no_matches;
+	    }
+
 	  filename = pattern;
 #ifdef _AMIGA
 	  dirname = "";
@@ -492,7 +516,7 @@ glob (pattern, flags, errfunc, pglob)
 
       if (filename[0] == '\0'
 #if defined __MSDOS__ || defined WINDOWS32
-          && dirname[dirlen - 1] != ':'
+	  && dirname[dirlen - 1] != ':'
 	  && (dirlen < 3 || dirname[dirlen - 2] != ':'
 	      || dirname[dirlen - 1] != '/')
 #endif
@@ -529,24 +553,6 @@ glob (pattern, flags, errfunc, pglob)
 	}
     }
 
-  if (!(flags & GLOB_APPEND))
-    {
-      pglob->gl_pathc = 0;
-      if (!(flags & GLOB_DOOFFS))
-        pglob->gl_pathv = NULL;
-      else
-	{
-	  size_t i;
-	  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;
-	}
-    }
-
   oldcount = pglob->gl_pathc + pglob->gl_offs;
 
 #ifndef VMS
@@ -564,7 +570,7 @@ glob (pattern, flags, errfunc, pglob)
 # else
 #  ifdef WINDOWS32
 	  if (home_dir == NULL || home_dir[0] == '\0')
-            home_dir = "c:/users/default"; /* poor default */
+	    home_dir = "c:/users/default"; /* poor default */
 #  else
 	  if (home_dir == NULL || home_dir[0] == '\0')
 	    {
diff --git a/posix/tst-gnuglob.c b/posix/tst-gnuglob.c
index 95bfbae641..d4539bddbc 100644
--- a/posix/tst-gnuglob.c
+++ b/posix/tst-gnuglob.c
@@ -1,6 +1,6 @@
 /* Test the GNU extensions in glob which allow the user to provide callbacks
    for the filesystem access functions.
-   Copyright (C) 2001-2002, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2001-2002, 2007, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -61,9 +61,9 @@ static struct
       { "..", 3, DT_DIR },
       { ".foo", 3, DT_REG },
       { "dir1lev3", 3, DT_DIR },
-        { ".", 4, DT_DIR },
-        { "..", 4, DT_DIR },
-        { "file1lev4", 4, DT_REG },
+	{ ".", 4, DT_DIR },
+	{ "..", 4, DT_DIR },
+	{ "file1lev4", 4, DT_REG },
       { "file1lev3", 3, DT_REG },
       { "file2lev3", 3, DT_REG },
     { "file2lev2", 2, DT_REG },
@@ -81,9 +81,9 @@ static struct
       { "..", 3, DT_DIR },
       { ".foo", 3, DT_REG },
       { ".dir", 3, DT_DIR },
-        { ".", 4, DT_DIR },
-        { "..", 4, DT_DIR },
-        { "hidden", 4, DT_REG }
+	{ ".", 4, DT_DIR },
+	{ "..", 4, DT_DIR },
+	{ "hidden", 4, DT_REG }
 };
 #define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
 
@@ -283,7 +283,7 @@ static const char *glob_errstring[] =
 static const char *
 flagstr (int flags)
 {
-  const char *strs[] =
+  static const char *const strs[] =
   {
     "GLOB_ERR", "GLOB_MARK", "GLOB_NOSORT", "GLOB_DOOFSS", "GLOB_NOCHECK",
     "GLOB_APPEND", "GLOB_NOESCAPE", "GLOB_PERIOD", "GLOB_MAGCHAR",
@@ -312,6 +312,29 @@ flagstr (int flags)
     }
 
   return buf;
+#undef nstrs
+}
+
+
+static const char *
+errstr (int val)
+{
+  static const char *const strs[] =
+    {
+      [GLOB_NOSPACE] = "GLOB_NOSPACE",
+      [GLOB_ABORTED] = "GLOB_ABORTED",
+      [GLOB_NOMATCH] = "GLOB_NOMATCH",
+      [GLOB_NOSYS] = "GLOB_NOSYS"
+    };
+#define nstrs (sizeof (strs) / sizeof (strs[0]))
+  static char buf[100];
+  if (val < 0 || val >= nstrs || strs[val] == NULL)
+    {
+      snprintf (buf, sizeof (buf), "GLOB_??? (%d)", val);
+      return buf;
+    }
+  return strs[val];
+#undef nstrs
 }
 
 
@@ -376,28 +399,34 @@ main (void)
   gl.gl_lstat = my_stat;
   gl.gl_stat = my_stat;
 
-#define test(a, b, c...) \
+#define test(a, b, r, c...) \
   fmt = a;								      \
-  flags = b;								      \
+  flags = GLOB_ALTDIRFUNC | b;						      \
   errval = glob (fmt, flags, NULL, &gl);				      \
-  if (errval != 0)							      \
+  if (errval != r)							      \
     {									      \
-      printf ("glob (\"%s\", %s) failed: %s\n", fmt, flagstr (flags),	      \
-	      errval >= 0 && errval < nglob_errstring			      \
-	      ? glob_errstring[errval] : "???");			      \
+      if (r == 0)							      \
+	printf ("glob (\"%s\", %s) failed: %s\n", fmt, flagstr (flags),	      \
+		errval >= 0 && errval < nglob_errstring			      \
+		? glob_errstring[errval] : "???");			      \
+      else								      \
+	printf ("glob (\"%s\", %s) did not fail\n", fmt, flagstr (flags));    \
       result = 1;							      \
     }									      \
+  else if (r == 0)							      \
+    result |= test_result (fmt, flags, &gl, (const char *[]) { c, NULL });    \
   else									      \
-    result |= test_result (fmt, flags, &gl, (const char *[]) { c, NULL })
+    printf ("result for glob (\"%s\", %s) = %s\n\n", fmt, flagstr (flags),    \
+	    errstr (errval))
 
-  test ("*/*/*", GLOB_ALTDIRFUNC,
+  test ("*/*/*", 0, 0,
 	"dir1lev1/dir2lev2/dir1lev3",
 	"dir1lev1/dir2lev2/file1lev3",
 	"dir1lev1/dir2lev2/file2lev3",
 	"dir1lev1/dir3lev2/file3lev3",
 	"dir1lev1/dir3lev2/file4lev3");
 
-  test ("*/*/*", GLOB_ALTDIRFUNC | GLOB_PERIOD,
+  test ("*/*/*", GLOB_PERIOD, 0,
 	"dir1lev1/dir1lev2/.",
 	"dir1lev1/dir1lev2/..",
 	"dir1lev1/dir2lev2/.",
@@ -415,7 +444,7 @@ main (void)
 	"dir2lev1/dir1lev2/.dir",
 	"dir2lev1/dir1lev2/.foo");
 
-  test ("*/*/.*", GLOB_ALTDIRFUNC,
+  test ("*/*/.*", 0, 0,
 	"dir1lev1/dir1lev2/.",
 	"dir1lev1/dir1lev2/..",
 	"dir1lev1/dir2lev2/.",
@@ -428,7 +457,7 @@ main (void)
 	"dir2lev1/dir1lev2/.dir",
 	"dir2lev1/dir1lev2/.foo");
 
-  test ("*1*/*2*/.*", GLOB_ALTDIRFUNC,
+  test ("*1*/*2*/.*", 0, 0,
 	"dir1lev1/dir1lev2/.",
 	"dir1lev1/dir1lev2/..",
 	"dir1lev1/dir2lev2/.",
@@ -441,7 +470,7 @@ main (void)
 	"dir2lev1/dir1lev2/.dir",
 	"dir2lev1/dir1lev2/.foo");
 
-  test ("*1*/*1*/.*", GLOB_ALTDIRFUNC,
+  test ("*1*/*1*/.*", 0, 0,
 	"dir1lev1/dir1lev2/.",
 	"dir1lev1/dir1lev2/..",
 	"dir2lev1/dir1lev2/.",
@@ -449,12 +478,16 @@ main (void)
 	"dir2lev1/dir1lev2/.dir",
 	"dir2lev1/dir1lev2/.foo");
 
-  test ("\\/*", GLOB_ALTDIRFUNC,
+  test ("\\/*", 0, 0,
 	"/dir1lev1",
 	"/dir2lev1",
 	"/file1lev1",
 	"/file2lev1");
 
+  test ("", 0, GLOB_NOMATCH, NULL);
+
+  test ("", GLOB_NOCHECK, 0, "");
+
   globfree (&gl);
 
   return result;