NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: lib/60517: fnmatch(2) does not implement FNM_PATHNAME correctly
On 26-07-29 17:35, drew%ddevault.org@localhost 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);
| }
|
Home |
Main Index |
Thread Index |
Old Index