|
|
Message-ID: <20261111000950.3772888-1-bernie@codewiz.org>
Date: Wed, 11 Nov 2026 09:09:50 +0900
From: Bernie Innocenti <bernie@...ewiz.org>
To: musl@...ts.openwall.com
Cc: Szabolcs Nagy <nsz@...t70.net>,
Bernie Innocenti <bernie@...ewiz.org>
Subject: [PATCH libc-test] functional/fnmatch: accept either reading of a backslash in brackets
Without FNM_NOESCAPE, POSIX makes a backslash an escape character
inside a bracket expression too: XCU 2.13.1 in POSIX.1-2017 names
fnmatch() among the places where a backslash escapes the next
character, without an exception for brackets, and XCU 2.14.1 in
POSIX.1-2024 leaves it unspecified for the shell only. Then \] does
not close the bracket, and no bracket expression starts: "[[?*\]" and
"[]?*\]" match "[[" or "[]", then any character, any string and ']',
so neither matches its one-character test string. glibc reads them
that way; musl takes the backslash as an ordinary character, and both
match.
The two cases now accept a match or FNM_NOMATCH, and two more write the
backslash escaped, "[[?*\\]" and "[]?*\\]", on which both readings
agree.
---
src/functional/fnmatch.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/src/functional/fnmatch.c b/src/functional/fnmatch.c
index 96b8e06..c75a369 100644
--- a/src/functional/fnmatch.c
+++ b/src/functional/fnmatch.c
@@ -47,6 +47,10 @@ static char *flagstr(const struct xlat *map, int flags)
return buf;
}
+/* An expected value for a pattern that POSIX and musl read differently:
+ either a match or FNM_NOMATCH passes. */
+#define EITHER 0x7fff
+
/* tests harness adapted from glibc testfnm.c */
struct {
const char *pattern;
@@ -70,8 +74,15 @@ struct {
{ "a*.c", "a/x.c", FNM_PATHNAME, FNM_NOMATCH },
{ "*/foo", "/foo", FNM_PATHNAME, 0 },
{ "-O[01]", "-O1", 0, 0 },
- { "[[?*\\]", "\\", 0, 0 },
- { "[]?*\\]", "]", 0, 0 },
+ /* Without FNM_NOESCAPE, POSIX makes a backslash an escape inside a
+ bracket expression too (XCU 2.13.1, 2.14.1 in POSIX.1-2024): the
+ \] doesn't close the bracket, and these two don't match, as with
+ glibc. musl takes the backslash there as an ordinary character, and
+ they match. With the backslash escaped, both readings agree. */
+ { "[[?*\\]", "\\", 0, EITHER },
+ { "[]?*\\]", "]", 0, EITHER },
+ { "[[?*\\\\]", "\\", 0, 0 },
+ { "[]?*\\\\]", "]", 0, 0 },
/* initial right-bracket tests */
{ "[!]a-]", "b", 0, 0 },
{ "[]-_]", "^", 0, 0 }, /* range: ']', '^', '_' */
@@ -152,7 +163,8 @@ int main(void)
r = fnmatch(tests[i].pattern, tests[i].string, tests[i].flags);
x = tests[i].expected;
- if (r != x && (r != FNM_NOMATCH || x != -FNM_NOMATCH)) {
+ if (x == EITHER ? r != 0 && r != FNM_NOMATCH :
+ r != x && (r != FNM_NOMATCH || x != -FNM_NOMATCH)) {
t_error("fnmatch(\"%s\", \"%s\", %s) failed, got %d want %d\n",
tests[i].pattern, tests[i].string,
flagstr(fnmatch_flags, tests[i].flags),
--
2.56.0
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.