From cejkar@fit.vutbr.cz  Tue Sep  4 09:16:59 2007
Return-Path: <cejkar@fit.vutbr.cz>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 908C716A469
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  4 Sep 2007 09:16:59 +0000 (UTC)
	(envelope-from cejkar@fit.vutbr.cz)
Received: from kazi.fit.vutbr.cz (kazi.fit.vutbr.cz [147.229.8.12])
	by mx1.freebsd.org (Postfix) with ESMTP id 0E37A13C468
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  4 Sep 2007 09:16:58 +0000 (UTC)
	(envelope-from cejkar@fit.vutbr.cz)
Received: from kazi.fit.vutbr.cz (localhost [127.0.0.1])
	by kazi.fit.vutbr.cz (envelope-from cejkar@fit.vutbr.cz) (8.14.1/8.14.1) with ESMTP id l8496iiJ019646
	(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 4 Sep 2007 11:06:44 +0200 (CEST)
Received: (from cejkar@localhost)
	by kazi.fit.vutbr.cz (8.14.1/8.13.1/Submit) id l8496h8s019645;
	Tue, 4 Sep 2007 11:06:43 +0200 (CEST)
	(envelope-from cejkar)
Message-Id: <200709040906.l8496h8s019645@kazi.fit.vutbr.cz>
Date: Tue, 4 Sep 2007 11:06:43 +0200 (CEST)
From: Rudolf Cejka <cejkar@fit.vutbr.cz>
Reply-To: Rudolf Cejka <cejkar@fit.vutbr.cz>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [libc] fnmatch() does not handle FNM_PERIOD correctly
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         116074
>Category:       bin
>Synopsis:       [libc] fnmatch() does not handle FNM_PERIOD correctly
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    jilles
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Sep 04 09:20:02 GMT 2007
>Closed-Date:    Wed Aug 17 21:00:45 UTC 2011
>Last-Modified:  Wed Aug 17 21:00:45 UTC 2011
>Originator:     Rudolf Cejka
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
FIT, Brno University of Technology, Czech Republic
>Environment:
	FreeBSD 6.2-STABLE, Aug 20, 2007
>Description:

	The example in How-To-Repeat does incorrectly return
	"Match: Yes (should be No)". The problem in fnmatch() is that
	the implementation finds first "*" character after "a" match,
	and then recursively tries to call itself, but now with
	FNM_PERIOD disabled:

	...
	if (!fnmatch1(pattern, string,
	    flags & ~FNM_PERIOD, patmbs, strmbs))
	        return (0);
	...

	Tried patterns are
	fnmatch("b/*", "bbb/.x", ...)
	fnmatch("b/*", "bb/.x", ...)
	fnmatch("b/*", "b/.x", ...)
	where the third try is successfull, because the FNM_PERIOD
	is disabled. I tried to find a solution, but I'm afraid, that
	it is not so easy, because simply removing code disabling
	FNM_PERIOD could cause another problems (if there is a dot in
	asterisk matching pattern - maybe mangling stringstart inside
	recursive call with FNM_PERIOD allowed could do the job).

>How-To-Repeat:

	#include <stdio.h>
	#include <fnmatch.h>

	int main(void)
	{
	    int r = fnmatch("a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD);
	    printf("Match: %s\n", (r == 0) ? "Yes (should be No)" : "No");
	    return 0;
	}

>Fix:
>Release-Note:
>Audit-Trail:

From: Jilles Tjoelker <jilles@stack.nl>
To: bug-followup@FreeBSD.org, cejkar@fit.vutbr.cz
Cc:  
Subject: Re: bin/116074: [libc] fnmatch() does not handle FNM_PERIOD
	correctly
Date: Thu, 30 Apr 2009 13:52:18 +0200

 --rwEMma7ioTxnRzrJ
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 A possible patch: http://www.stack.nl/~jilles/unix/fnmatch-period.patch
 
 This passes the original stringstart along with recursive calls.
 
 I suppose the recursion could be removed entirely and replaced by
 backtracking (to the last asterisk seen), like ircd's match function
 does. It is not necessary to backtrack to any other asterisk. Note that
 this is only possible because the asterisk can match arbitrarily many of
 any character.
 
 -- 
 Jilles Tjoelker
 
 --rwEMma7ioTxnRzrJ
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="fnmatch-period.patch"
 
 --- src/lib/libc/gen/fnmatch.c.orig	2008-03-18 23:15:53.000000000 +0100
 +++ src/lib/libc/gen/fnmatch.c	2009-04-26 22:41:18.000000000 +0200
 @@ -67,7 +67,8 @@
  #define RANGE_ERROR     (-1)
  
  static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
 -static int fnmatch1(const char *, const char *, int, mbstate_t, mbstate_t);
 +static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
 +		mbstate_t);
  
  int
  fnmatch(pattern, string, flags)
 @@ -76,22 +77,21 @@
  {
  	static const mbstate_t initial;
  
 -	return (fnmatch1(pattern, string, flags, initial, initial));
 +	return (fnmatch1(pattern, string, string, flags, initial, initial));
  }
  
  static int
 -fnmatch1(pattern, string, flags, patmbs, strmbs)
 -	const char *pattern, *string;
 +fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
 +	const char *pattern, *string, *stringstart;
  	int flags;
  	mbstate_t patmbs, strmbs;
  {
 -	const char *stringstart;
  	char *newp;
  	char c;
  	wchar_t pc, sc;
  	size_t pclen, sclen;
  
 -	for (stringstart = string;;) {
 +	for (;;) {
  		pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
  		if (pclen == (size_t)-1 || pclen == (size_t)-2)
  			return (FNM_NOMATCH);
 @@ -145,8 +145,8 @@
  
  			/* General case, use recursion. */
  			while (sc != EOS) {
 -				if (!fnmatch1(pattern, string,
 -				    flags & ~FNM_PERIOD, patmbs, strmbs))
 +				if (!fnmatch1(pattern, string, stringstart,
 +				    flags, patmbs, strmbs))
  					return (0);
  				sclen = mbrtowc(&sc, string, MB_LEN_MAX,
  				    &strmbs);
 
 --rwEMma7ioTxnRzrJ--

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/116074: commit references a PR
Date: Fri, 16 Apr 2010 22:29:33 +0000 (UTC)

 Author: jilles
 Date: Fri Apr 16 22:29:24 2010
 New Revision: 206711
 URL: http://svn.freebsd.org/changeset/base/206711
 
 Log:
   fnmatch: Fix bad FNM_PERIOD disabling if an asterisk has been seen.
   
   Example: fnmatch("a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD)
   
   PR:		116074
   MFC after:	1 week
 
 Modified:
   head/lib/libc/gen/fnmatch.c
   head/tools/regression/lib/libc/gen/test-fnmatch.c
 
 Modified: head/lib/libc/gen/fnmatch.c
 ==============================================================================
 --- head/lib/libc/gen/fnmatch.c	Fri Apr 16 22:15:26 2010	(r206710)
 +++ head/lib/libc/gen/fnmatch.c	Fri Apr 16 22:29:24 2010	(r206711)
 @@ -67,7 +67,8 @@ __FBSDID("$FreeBSD$");
  #define RANGE_ERROR     (-1)
  
  static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
 -static int fnmatch1(const char *, const char *, int, mbstate_t, mbstate_t);
 +static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
 +		mbstate_t);
  
  int
  fnmatch(pattern, string, flags)
 @@ -76,22 +77,21 @@ fnmatch(pattern, string, flags)
  {
  	static const mbstate_t initial;
  
 -	return (fnmatch1(pattern, string, flags, initial, initial));
 +	return (fnmatch1(pattern, string, string, flags, initial, initial));
  }
  
  static int
 -fnmatch1(pattern, string, flags, patmbs, strmbs)
 -	const char *pattern, *string;
 +fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
 +	const char *pattern, *string, *stringstart;
  	int flags;
  	mbstate_t patmbs, strmbs;
  {
 -	const char *stringstart;
  	char *newp;
  	char c;
  	wchar_t pc, sc;
  	size_t pclen, sclen;
  
 -	for (stringstart = string;;) {
 +	for (;;) {
  		pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
  		if (pclen == (size_t)-1 || pclen == (size_t)-2)
  			return (FNM_NOMATCH);
 @@ -145,8 +145,8 @@ fnmatch1(pattern, string, flags, patmbs,
  
  			/* General case, use recursion. */
  			while (sc != EOS) {
 -				if (!fnmatch1(pattern, string,
 -				    flags & ~FNM_PERIOD, patmbs, strmbs))
 +				if (!fnmatch1(pattern, string, stringstart,
 +				    flags, patmbs, strmbs))
  					return (0);
  				sclen = mbrtowc(&sc, string, MB_LEN_MAX,
  				    &strmbs);
 
 Modified: head/tools/regression/lib/libc/gen/test-fnmatch.c
 ==============================================================================
 --- head/tools/regression/lib/libc/gen/test-fnmatch.c	Fri Apr 16 22:15:26 2010	(r206710)
 +++ head/tools/regression/lib/libc/gen/test-fnmatch.c	Fri Apr 16 22:29:24 2010	(r206711)
 @@ -174,6 +174,7 @@ struct testcase {
  	"*a", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0,
  	"*", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH,
  	"*a", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH,
 +	"a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH,
  };
  
  static const char *
 _______________________________________________
 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"
 
State-Changed-From-To: open->patched 
State-Changed-By: jilles 
State-Changed-When: Fri Apr 16 22:43:12 UTC 2010 
State-Changed-Why:  
Fixed in 9-CURRENT. 


Responsible-Changed-From-To: freebsd-bugs->jilles 
Responsible-Changed-By: jilles 
Responsible-Changed-When: Fri Apr 16 22:43:12 UTC 2010 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=116074 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/116074: commit references a PR
Date: Fri, 23 Apr 2010 18:01:32 +0000 (UTC)

 Author: jilles
 Date: Fri Apr 23 18:01:19 2010
 New Revision: 207129
 URL: http://svn.freebsd.org/changeset/base/207129
 
 Log:
   MFC r206711: fnmatch: Fix bad FNM_PERIOD disabling
   if an asterisk has been seen.
   
   Example: fnmatch("a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD)
   
   PR:		116074
 
 Modified:
   stable/8/lib/libc/gen/fnmatch.c
   stable/8/tools/regression/lib/libc/gen/test-fnmatch.c
 Directory Properties:
   stable/8/lib/libc/   (props changed)
   stable/8/lib/libc/stdtime/   (props changed)
   stable/8/tools/regression/lib/libc/   (props changed)
 
 Modified: stable/8/lib/libc/gen/fnmatch.c
 ==============================================================================
 --- stable/8/lib/libc/gen/fnmatch.c	Fri Apr 23 17:52:36 2010	(r207128)
 +++ stable/8/lib/libc/gen/fnmatch.c	Fri Apr 23 18:01:19 2010	(r207129)
 @@ -67,7 +67,8 @@ __FBSDID("$FreeBSD$");
  #define RANGE_ERROR     (-1)
  
  static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
 -static int fnmatch1(const char *, const char *, int, mbstate_t, mbstate_t);
 +static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
 +		mbstate_t);
  
  int
  fnmatch(pattern, string, flags)
 @@ -76,22 +77,21 @@ fnmatch(pattern, string, flags)
  {
  	static const mbstate_t initial;
  
 -	return (fnmatch1(pattern, string, flags, initial, initial));
 +	return (fnmatch1(pattern, string, string, flags, initial, initial));
  }
  
  static int
 -fnmatch1(pattern, string, flags, patmbs, strmbs)
 -	const char *pattern, *string;
 +fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
 +	const char *pattern, *string, *stringstart;
  	int flags;
  	mbstate_t patmbs, strmbs;
  {
 -	const char *stringstart;
  	char *newp;
  	char c;
  	wchar_t pc, sc;
  	size_t pclen, sclen;
  
 -	for (stringstart = string;;) {
 +	for (;;) {
  		pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
  		if (pclen == (size_t)-1 || pclen == (size_t)-2)
  			return (FNM_NOMATCH);
 @@ -145,8 +145,8 @@ fnmatch1(pattern, string, flags, patmbs,
  
  			/* General case, use recursion. */
  			while (sc != EOS) {
 -				if (!fnmatch1(pattern, string,
 -				    flags & ~FNM_PERIOD, patmbs, strmbs))
 +				if (!fnmatch1(pattern, string, stringstart,
 +				    flags, patmbs, strmbs))
  					return (0);
  				sclen = mbrtowc(&sc, string, MB_LEN_MAX,
  				    &strmbs);
 
 Modified: stable/8/tools/regression/lib/libc/gen/test-fnmatch.c
 ==============================================================================
 --- stable/8/tools/regression/lib/libc/gen/test-fnmatch.c	Fri Apr 23 17:52:36 2010	(r207128)
 +++ stable/8/tools/regression/lib/libc/gen/test-fnmatch.c	Fri Apr 23 18:01:19 2010	(r207129)
 @@ -174,6 +174,7 @@ struct testcase {
  	"*a", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0,
  	"*", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH,
  	"*a", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH,
 +	"a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH,
  };
  
  static const char *
 _______________________________________________
 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"
 
State-Changed-From-To: patched->closed 
State-Changed-By: jilles 
State-Changed-When: Wed Aug 17 21:00:13 UTC 2011 
State-Changed-Why:  
Fixed in 9-current and 8-stable, no MFC planned for 7-stable. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=116074 
>Unformatted:
