NetBSD Problem Report #60517

From www@netbsd.org  Wed Jul 29 17:31:46 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits)
	 client-signature RSA-PSS (2048 bits))
	(Client CN "mail.netbsd.org", Issuer "YR2" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 00A2B1A923B
	for <gnats-bugs@gnats.NetBSD.org>; Wed, 29 Jul 2026 17:31:45 +0000 (UTC)
Message-Id: <20260729173144.AE6241A923C@mollari.NetBSD.org>
Date: Wed, 29 Jul 2026 17:31:44 +0000 (UTC)
From: drew@ddevault.org
Reply-To: drew@ddevault.org
To: gnats-bugs@NetBSD.org
Subject: fnmatch(2) does not implement FNM_PATHNAME correctly
X-Send-Pr-Version: www-1.0
X-From4GNATS: "drew@ddevault.org via gnats" <gnats-admin@NetBSD.org>

>Number:         60517
>Category:       lib
>Synopsis:       fnmatch(2) does not implement FNM_PATHNAME correctly
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jul 29 17:35:00 +0000 2026
>Last-Modified:  Wed Aug 05 08:35:02 +0000 2026
>Originator:     Drew DeVault
>Release:        NetBSD 11.0-rc7
>Organization:
>Environment:
NetBSD kludge 11.0_RC7 NetBSD 11.0_RC7 (GENERIC) #0: Wed Jul 22 05:26:24 UTC 2026  mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/amd64/compile/GENERIC amd64 x86_64 Intel 686-class NetBSD

>Description:
fnmatch(3) does not implement FNM_PATHNAME correctly in rangematch, causing some patterns to not match correctly.
>How-To-Repeat:
The following program reproduces the issue:

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

int main(int argc, char *argv[]) {
	int match = fnmatch(argv[1], argv[2], 0);
	printf("%d\n", match);
	return 0;
}

Run:

./fnmatch '[\\/$]*' '/usr/lib'

And it should print 0.
>Fix:
--- src.orig/lib/libc/gen/fnmatch.c	2014-10-13 00:32:33.000000000 +0200
+++ src/lib/libc/gen/fnmatch.c	2026-07-29 15:25:45.271817024 +0200
@@ -91,7 +91,7 @@
 	need = 1;
 	for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']' || need;) {
 		need = 0;
-		if (c == '/')
+		if (c == '/' && (flags & FNM_PATHNAME))
 			return (void *)-1;
 		if (c == '\\' && !(flags & FNM_NOESCAPE))
 			c = FOLDCASE(*pattern++, flags);
--- src.orig/tests/lib/libc/gen/t_fnmatch.c	2016-10-31 06:08:53.000000000 +0100
+++ src/tests/lib/libc/gen/t_fnmatch.c	2026-07-29 19:25:10.723264988 +0200
@@ -125,6 +125,8 @@
 	ATF_CHECK(fnmatch("???x", "xxxx", FNM_PATHNAME) == 0);
 	ATF_CHECK(fnmatch("*/xxx", "/xxx", FNM_PATHNAME) == 0);
 	ATF_CHECK(fnmatch("x/*.y", "x/z.y", FNM_PATHNAME) == 0);
+
+	ATF_CHECK(fnmatch("[\\\\/$]*", "/usr/lib", 0) == 0);
 }

>Audit-Trail:
From: Luke Mewburn <luke@mewburn.net>
To: gnats-bugs@netbsd.org, christos@netbsd.org
Cc: lib-bug-people@netbsd.org, gnats-admin@netbsd.org,
	netbsd-bugs@netbsd.org
Subject: Re: lib/60517: fnmatch(2) does not implement FNM_PATHNAME correctly
Date: Wed, 5 Aug 2026 18:32:02 +1000

 On 26-07-29 17:35, drew@ddevault.org via gnats wrote:
   | >Description:
   | fnmatch(3) does not implement FNM_PATHNAME correctly in rangematch,
   | causing some patterns to not match correctly.
   | 
   | >How-To-Repeat:
   | The following program reproduces the issue:
   | 
   | #include <fnmatch.h>
   | #include <stdio.h>
   | 
   | int main(int argc, char *argv[]) {
   | 	int match = fnmatch(argv[1], argv[2], 0);
   | 	printf("%d\n", match);
   | 	return 0;
   | }
   | 
   | Run:
   | 
   | ./fnmatch '[\\/$]*' '/usr/lib'
   | 
   | And it should print 0.

 (+ Christos)

 Hi Drew,

 tl;dr: I think you have identified a bug with fnmatch without FNM_PATHNAME,
 even if I think your test case pattern was a bit tricky at first :)

 Unless Christos (or someone else) disagrees with your report
 and my analysis, I think this should be committed.


 Details:

 When I first analyzed your report it wasn't clear what the fault was:
 1. Your pattern was a bit tricky. Now I see that the intention is to
    match any string starting with `\', `/', or `$', relying upon
    `\\' to become `\` because you're not using FNM_NOESCAPE.
 2. You're not using FNM_PATHNAME.

 I've dug into the commit that caused the issue, and read multiple
 versions of the relevant POSIX pages, and I now understand your bug
 report and think your proposed fix is correct.

 The commit to lib/libc/gen/fnmatch.c 1.26 on 2014-10-12 was by Christos,
 with commit message:
 	Fix fnmatch issues according to POSIX.
 	http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13_01
 	1. A [...] pattern containing a slash is not a pattern; the [ ]'s become regular
 	   characters
 	2. A [] or a [!] is not an empty pattern, why would it? The first would never
 	   match and the second would always match which makes it equivalent to ?
 	   In those cases the ] is taken as a literal character and does not have
 	   special meaning.

 Reading that POSIX (issue 6) "Shell Command Language" page linked in item 1,
 I don't actually see the text relating to item 1 in section 2.13.1.
 There's related text in section 2.13.3 "Patterns Used for Filename Expansion".

 However, the POSIX (issue 6) fnmatch page at
   https://pubs.opengroup.org/onlinepubs/009695399/functions/fnmatch.html 
 doesn't cross-reference back to this shell section 2.13.3 about filename
 expansion.  It seems to me that fnmatch FNM_PATHNAME has a limited and
 different implementation than the shell.

 The relevant text in fnmatch for slash without FNM_PATHNAME is:
 	If the FNM_PATHNAME flag is not set, the slash character shall be
 	treated as an ordinary character.

 The latest POSIX (issue 8) page for fnmatch at
   https://pubs.opengroup.org/onlinepubs/9799919799/functions/fnmatch.html
 has similar text:
 	If the FNM_PATHNAME flag is not set, the <slash> character shall
 	be treated as an ordinary character.

 Regards,
 Luke.



   | >Fix:
   | --- src.orig/lib/libc/gen/fnmatch.c	2014-10-13 00:32:33.000000000 +0200
   | +++ src/lib/libc/gen/fnmatch.c	2026-07-29 15:25:45.271817024 +0200
   | @@ -91,7 +91,7 @@
   |  	need = 1;
   |  	for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']' || need;) {
   |  		need = 0;
   | -		if (c == '/')
   | +		if (c == '/' && (flags & FNM_PATHNAME))
   |  			return (void *)-1;
   |  		if (c == '\\' && !(flags & FNM_NOESCAPE))
   |  			c = FOLDCASE(*pattern++, flags);
   | --- src.orig/tests/lib/libc/gen/t_fnmatch.c	2016-10-31 06:08:53.000000000 +0100
   | +++ src/tests/lib/libc/gen/t_fnmatch.c	2026-07-29 19:25:10.723264988 +0200
   | @@ -125,6 +125,8 @@
   |  	ATF_CHECK(fnmatch("???x", "xxxx", FNM_PATHNAME) == 0);
   |  	ATF_CHECK(fnmatch("*/xxx", "/xxx", FNM_PATHNAME) == 0);
   |  	ATF_CHECK(fnmatch("x/*.y", "x/z.y", FNM_PATHNAME) == 0);
   | +
   | +	ATF_CHECK(fnmatch("[\\\\/$]*", "/usr/lib", 0) == 0);
   |  }
   | 

From: Christos Zoulas <christos@zoulas.com>
To: Luke Mewburn <luke@mewburn.net>
Cc: gnats-bugs@netbsd.org,
 christos@netbsd.org,
 lib-bug-people@netbsd.org,
 gnats-admin@netbsd.org,
 netbsd-bugs@netbsd.org
Subject: Re: lib/60517: fnmatch(2) does not implement FNM_PATHNAME correctly
Date: Wed, 5 Aug 2026 11:34:16 +0300

 Yes, I believe the fix is correct and should be committed.

 christos

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.