Harald van Dijk <harald@xxxxxxxxxxx> wrote: > > On 12/01/2022 16:25, Christoph Anton Mitterer wrote: >> The results for the run-circumflex seem pretty odd. >> Apparently, the ^ is taken literally, but the other two are negated. > > The ^ is not taken literally. The ^ in the pattern is wrongly taken as > the negation operator, and the ^ in the argument is then reported as a > match because it is neither . nor a. > > This bug (you're right that it's a bug) is specific to builds that use > fnmatch(). In dash itself, ^ is always assumed as a literal. In builds > with --disable-fnmatch you get correct results. In builds with > --enable-fnmatch, because dash assumes ^ is assumed as a literal, dash > fails to escape it before passing it on to fnmatch(), and the system > fnmatch() may choose differently from dash on how to deal with unquoted > ^s. What dash should do to get whatever behaviour the system fnmatch() > chooses is leave unquoted ^s unquoted, and leave quoted ^s quoted. This > can be achieved by > > --- a/src/mksyntax.c > +++ b/src/mksyntax.c > @@ -178,14 +178,14 @@ main(int argc, char **argv) > add("$", "CVAR"); > add("}", "CENDVAR"); > /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ > - add("!*?[=~:/-]", "CCTL"); > + add("!*?[^=~:/-]", "CCTL"); > print("dqsyntax"); > init(); > fputs("\n/* syntax table used when in single quotes */\n", cfile); > add("\n", "CNL"); > add("'", "CENDQUOTE"); > /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ > - add("!*?[=~:/-]\\", "CCTL"); > + add("!*?[^=~:/-]\\", "CCTL"); > print("sqsyntax"); > init(); > fputs("\n/* syntax table used when in arithmetic */\n", cfile); > > However, whether this is the correct approach is a matter of opinion: > dash could alternatively choose to always take ^ as a literal and always > escape it before passing it on to fnmatch(), overriding whatever > decision the libc people had taken. Yes, this would produce the most consistent result. This patch forces ^ to be a literal when we use fnmatch. Fixes: 7638476c18f2 ("shell: Enable fnmatch/glob by default") Reported-by: Christoph Anton Mitterer <calestyo@xxxxxxxxxxxx> Suggested-by: Harald van Dijk <harald@xxxxxxxxxxx> Signed-off-by: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> diff --git a/src/expand.c b/src/expand.c index aea5cc4..04bf8fb 100644 --- a/src/expand.c +++ b/src/expand.c @@ -47,6 +47,9 @@ #include <string.h> #ifdef HAVE_FNMATCH #include <fnmatch.h> +#define FNMATCH_IS_ENABLED 1 +#else +#define FNMATCH_IS_ENABLED 0 #endif #ifdef HAVE_GLOB #include <glob.h> @@ -1693,8 +1696,11 @@ _rmescapes(char *str, int flag) notescaped = 0; goto copy; } + if (FNMATCH_IS_ENABLED && *p == '^') + goto add_escape; if (*p == (char)CTLESC) { p++; +add_escape: if (notescaped) *q++ = '\\'; } -- Email: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt