[18/18] posix: Fix glob with GLOB_NOCHECK returning modified patterns (BZ#10246)

Submitted by Adhemerval Zanella on Aug. 11, 2017, 2:50 p.m.

Details

Message ID 1502463044-4042-19-git-send-email-adhemerval.zanella@linaro.org
State New
Headers show

Commit Message

Adhemerval Zanella Aug. 11, 2017, 2:50 p.m.
Acconding to POSIX glob with GLOB_NOCHECK should return a list consisting
of only of the input pattern in case of no match.  However GLIBC does not
honor in case of '//<something'.  This is due internally this is handled
and special case and prefix_array (responsable to prepend the directory
name) does not know if the input already contains a slash or not since
either '/<something>' or '//<something>' will be handle in same way.

This patch fix it by using a empty directory name for the latter (since
prefix_array already adds a slash as default for each entry).

Checked on x86_64-linux-gnu.

	[BZ #10246]
	* posix/glob.c (glob): Handle pattern that do not match and
	start with '/' correctly.
	* posix/globtest.sh: New tests for NOCHECK.
---
 posix/glob.c      | 14 ++++++++------
 posix/globtest.sh | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/posix/glob.c b/posix/glob.c
index 37e8702..3f85586 100644
--- a/posix/glob.c
+++ b/posix/glob.c
@@ -358,6 +358,8 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
   size_t oldcount;
   int meta;
   bool dirname_modified;
+  /* Indicate if the directory should be prepended on return values.  */
+  bool dirname_prefix = true;
   glob_t dirs;
   int retval = 0;
   struct char_array dirname;
@@ -591,6 +593,10 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
 	goto err_nospace;
       dirlen = 1;
       ++filename;
+      /* prefix_array adds a separator for each result and DIRNAME is
+	 already '/'.  So we indicate later that we should not prepend
+	 anything for this specific case.  */
+      dirname_prefix = false;
     }
   else
     {
@@ -1101,7 +1107,7 @@  glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
       if (dirlen > 0)
 	{
 	  /* Stick the directory on the front of each name.  */
-	  if (prefix_array (char_array_str (&dirname),
+	  if (prefix_array (dirname_prefix ? char_array_str (&dirname) : "",
 			    &pglob->gl_pathv[old_pathc + pglob->gl_offs],
 			    pglob->gl_pathc - old_pathc))
 	    {
@@ -1198,12 +1204,8 @@  prefix_array (const char *dirname, char **array, size_t n)
 # define DIRSEP_CHAR '/'
 #endif
 
-  if (dirlen == 1 && dirname[0] == '/')
-    /* DIRNAME is just "/", so normal prepending would get us "//foo".
-       We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
-    dirlen = 0;
 #if defined __MSDOS__ || defined WINDOWS32
-  else if (dirlen > 1)
+  if (dirlen > 1)
     {
       if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':')
 	/* DIRNAME is "d:/".  Don't prepend the slash from DIRNAME.  */
diff --git a/posix/globtest.sh b/posix/globtest.sh
index 73f7ae3..938bc47 100755
--- a/posix/globtest.sh
+++ b/posix/globtest.sh
@@ -242,6 +242,42 @@  if test $failed -ne 0; then
   result=1
 fi
 
+# Test NOCHECK for specific cases where the pattern used starts
+# with '/' (BZ#10246).
+failed=0
+${test_program_prefix} \
+${common_objpfx}posix/globtest -c "$testdir" "/%" |
+sort > $testout
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`/%'
+EOF
+if test $failed -ne 0; then
+  echo "No check test failed" >> $logfile
+  result=1
+fi
+
+${test_program_prefix} \
+${common_objpfx}posix/globtest -c "$testdir" "//%" |
+sort > $testout
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`//%'
+EOF
+if test $failed -ne 0; then
+  echo "No check test failed" >> $logfile
+  result=1
+fi
+
+${test_program_prefix} \
+${common_objpfx}posix/globtest -c "$testdir" "///%" |
+sort > $testout
+cat <<"EOF" | $CMP - $testout >> $logfile || failed=1
+`///%'
+EOF
+if test $failed -ne 0; then
+  echo "No check test failed" >> $logfile
+  result=1
+fi
+
 # Test NOMAGIC without magic characters
 failed=0
 ${test_program_prefix} \