Bug 181129

Summary: fnmatch doesn't translate "\\"
Product: Base System Reporter: Enji Cooper <ngie>
Component: binAssignee: Andrey A. Chernov <ache>
Status: Closed FIXED    
Severity: Affects Only Me CC: pfg, schily
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   
URL: http://austingroupbugs.net/view.php?id=806
Attachments:
Description Flags
Variant of Joerg's patch none

Description Enji Cooper freebsd_committer freebsd_triage 2013-08-08 04:50:00 UTC
fnmatch("\\", "\\", 0);

should work, but instead it returns FNM_NOMATCH. See http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=41558 for more details.
Comment 1 Andrey A. Chernov freebsd_committer freebsd_triage 2013-08-08 09:29:22 UTC
Responsible Changed
From-To: freebsd-bugs->ache

Take
Comment 2 dfilter service freebsd_committer freebsd_triage 2013-08-08 10:04:15 UTC
Author: ache
Date: Thu Aug  8 09:04:02 2013
New Revision: 254091
URL: http://svnweb.freebsd.org/changeset/base/254091

Log:
  According to POSIX \ in the fnmatch(3) pattern should escape
  any character including '\0', but our version replace escaped '\0'
  with '\\'.
  I.e. fnmatch("\\", "\\", 0) should not match while fnmatch("\\", "", 0)
  should (Linux and NetBSD does the same). Was vice versa.
  
  PR:     181129
  MFC after:      1 week

Modified:
  head/lib/libc/gen/fnmatch.c

Modified: head/lib/libc/gen/fnmatch.c
==============================================================================
--- head/lib/libc/gen/fnmatch.c	Thu Aug  8 06:15:58 2013	(r254090)
+++ head/lib/libc/gen/fnmatch.c	Thu Aug  8 09:04:02 2013	(r254091)
@@ -194,8 +194,6 @@ fnmatch1(pattern, string, stringstart, f
 				    &patmbs);
 				if (pclen == (size_t)-1 || pclen == (size_t)-2)
 					return (FNM_NOMATCH);
-				if (pclen == 0)
-					pc = '\\';
 				pattern += pclen;
 			}
 			/* FALLTHROUGH */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 3 Andrey A. Chernov freebsd_committer freebsd_triage 2013-08-08 10:08:35 UTC
State Changed
From-To: open->patched

Committed into -current
Comment 4 dfilter service freebsd_committer freebsd_triage 2013-08-11 22:54:38 UTC
Author: jilles
Date: Sun Aug 11 21:54:20 2013
New Revision: 254231
URL: http://svnweb.freebsd.org/changeset/base/254231

Log:
  fnmatch(): Add test for r254091 (pattern with single backslash).
  
  This test cannot be converted to an sh(1) test because the syntax would be
  invalid.
  
  PR:		181129
  MFC after:	1 week

Modified:
  head/tools/regression/lib/libc/gen/test-fnmatch.c

Modified: head/tools/regression/lib/libc/gen/test-fnmatch.c
==============================================================================
--- head/tools/regression/lib/libc/gen/test-fnmatch.c	Sun Aug 11 21:46:06 2013	(r254230)
+++ head/tools/regression/lib/libc/gen/test-fnmatch.c	Sun Aug 11 21:54:20 2013	(r254231)
@@ -135,6 +135,8 @@ struct testcase {
 	"\\[", "\\[", 0, FNM_NOMATCH,
 	"\\(", "\\(", 0, FNM_NOMATCH,
 	"\\a", "\\a", 0, FNM_NOMATCH,
+	"\\", "\\", 0, FNM_NOMATCH,
+	"\\", "", 0, 0,
 	"\\*", "\\*", FNM_NOESCAPE, 0,
 	"\\?", "\\?", FNM_NOESCAPE, 0,
 	"\\", "\\", FNM_NOESCAPE, 0,
@@ -236,6 +238,8 @@ write_sh_tests(const char *progname, int
 		if (strchr(t->pattern, '\'') != NULL ||
 		    strchr(t->string, '\'') != NULL)
 			continue;
+		if (t->flags == 0 && strcmp(t->pattern, "\\") == 0)
+			continue;
 		if (num == 1 && t->flags == 0)
 			printf("test%smatch '%s' '%s'\n",
 			    t->result == FNM_NOMATCH ? "no" : "",
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 5 dfilter service freebsd_committer freebsd_triage 2013-08-15 06:20:00 UTC
Author: ache
Date: Thu Aug 15 04:27:10 2013
New Revision: 254353
URL: http://svnweb.freebsd.org/changeset/base/254353

Log:
  MFC: r254091
  
  According to POSIX \ in the fnmatch(3) pattern should escape
  any character including '\0', but our version replace escaped '\0'
  with '\\'.
  I.e. fnmatch("\\", "\\", 0) should not match while fnmatch("\\", "", 0)
  should (Linux and NetBSD does the same). Was vice versa.
  
  PR:     181129

Modified:
  stable/9/lib/libc/gen/fnmatch.c
Directory Properties:
  stable/9/lib/libc/   (props changed)

Modified: stable/9/lib/libc/gen/fnmatch.c
==============================================================================
--- stable/9/lib/libc/gen/fnmatch.c	Thu Aug 15 04:25:16 2013	(r254352)
+++ stable/9/lib/libc/gen/fnmatch.c	Thu Aug 15 04:27:10 2013	(r254353)
@@ -194,8 +194,6 @@ fnmatch1(pattern, string, stringstart, f
 				    &patmbs);
 				if (pclen == (size_t)-1 || pclen == (size_t)-2)
 					return (FNM_NOMATCH);
-				if (pclen == 0)
-					pc = '\\';
 				pattern += pclen;
 			}
 			/* FALLTHROUGH */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 6 Andrey A. Chernov freebsd_committer freebsd_triage 2013-08-15 10:03:15 UTC
State Changed
From-To: patched->closed

Committed into -stable
Comment 7 dfilter service freebsd_committer freebsd_triage 2013-08-30 11:10:29 UTC
Author: jilles
Date: Fri Aug 30 10:10:22 2013
New Revision: 255066
URL: http://svnweb.freebsd.org/changeset/base/255066

Log:
  MFC r254231: fnmatch(): Add test for r254353 (pattern with single backslash)
  
  This test cannot be converted to an sh(1) test because the syntax would be
  invalid.
  
  r254091 was merged to stable/9 as r254353.
  
  PR:		181129

Modified:
  stable/9/tools/regression/lib/libc/gen/test-fnmatch.c
Directory Properties:
  stable/9/tools/regression/lib/libc/   (props changed)

Modified: stable/9/tools/regression/lib/libc/gen/test-fnmatch.c
==============================================================================
--- stable/9/tools/regression/lib/libc/gen/test-fnmatch.c	Fri Aug 30 10:07:10 2013	(r255065)
+++ stable/9/tools/regression/lib/libc/gen/test-fnmatch.c	Fri Aug 30 10:10:22 2013	(r255066)
@@ -135,6 +135,8 @@ struct testcase {
 	"\\[", "\\[", 0, FNM_NOMATCH,
 	"\\(", "\\(", 0, FNM_NOMATCH,
 	"\\a", "\\a", 0, FNM_NOMATCH,
+	"\\", "\\", 0, FNM_NOMATCH,
+	"\\", "", 0, 0,
 	"\\*", "\\*", FNM_NOESCAPE, 0,
 	"\\?", "\\?", FNM_NOESCAPE, 0,
 	"\\", "\\", FNM_NOESCAPE, 0,
@@ -236,6 +238,8 @@ write_sh_tests(const char *progname, int
 		if (strchr(t->pattern, '\'') != NULL ||
 		    strchr(t->string, '\'') != NULL)
 			continue;
+		if (t->flags == 0 && strcmp(t->pattern, "\\") == 0)
+			continue;
 		if (num == 1 && t->flags == 0)
 			printf("test%smatch '%s' '%s'\n",
 			    t->result == FNM_NOMATCH ? "no" : "",
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 8 Pedro F. Giffuni freebsd_committer freebsd_triage 2017-08-08 02:13:09 UTC
Joerg Shilling has noted the Austin group has recorded a re-interpretation:

http://austingroupbugs.net/view.php?id=806
Comment 9 Pedro F. Giffuni freebsd_committer freebsd_triage 2017-08-08 02:16:28 UTC
Created attachment 185141 [details]
Variant of Joerg's patch

(Submitted by Joerg in a private email)
The old code:

               case '\\': 
                        if (!(flags & FNM_NOESCAPE)) { 
                                pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, 
                                    &patmbs); 
                                if (pclen == (size_t)-1 || pclen == (size_t)-2) 
                                        return (FNM_NOMATCH); 
                                if (pclen == 0) 
                                        pc = '\\'; 
                                pattern += pclen; 
                        } 
                        /* FALLTHROUGH */ 

was wrong and BSD changed this to:

               case '\\': 
                        if (!(flags & FNM_NOESCAPE)) { 
                                pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, 
                                    &patmbs); 
                                if (pclen == (size_t)-1 || pclen == (size_t)-2) 
                                        return (FNM_NOMATCH); 
                                pattern += pclen; 
                        } 
                        /* FALLTHROUGH */ 

but this is incorrect as well.

Correct would be:

               case '\\': 
                        if (!(flags & FNM_NOESCAPE)) { 
                                pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, 
                                    &patmbs); 
                                if (pclen == (size_t)-1 || pclen == (size_t)-2) 
                                        return (FNM_NOMATCH); 
                                if (pclen == 0) 
                                        return (FNM_NOMATCH);
                                pattern += pclen; 
                        } 
                        /* FALLTHROUGH */
Comment 10 Pedro F. Giffuni freebsd_committer freebsd_triage 2017-08-10 15:51:57 UTC
I committed the change as r322368.
I mentioned the related revision instead of this PR (which is not really related) so we can close this PR now.