On Sun, Feb 20, 2022 at 07:15:44AM +0000, Stephane Chazelas wrote: > 2022-01-19 16:37:54 +1100, Herbert Xu: > [...] > > This patch forces ^ to be a literal when we use fnmatch. > [...] > The "fix" also seems incomplete and causes at least this > regression: > > $ ltrace -e fnmatch ./bin/dash -c 'case "\\" in ($1) echo match; esac' sh '[\^]' > dash->fnmatch("[\\\\^]", "\\", 0) = 0 > match > > See how that added \ caused it to be included in the set. Compare with: > > +++ exited (status 0) +++ > $ ltrace -e fnmatch ./bin/dash -c 'case "\\" in ($1) echo match; esac' sh '[\!]' > dash->fnmatch("[\\!]", "\\", 0) = 1 > +++ exited (status 0) +++ > $ ltrace -e fnmatch ./bin/dash -c 'case "\\" in ($1) echo match; esac' sh '[\x]' > dash->fnmatch("[\\x]", "\\", 0) = 1 > +++ exited (status 0) +++ If you want to escape ^ to always be treated as a literal when calling fnmatch(), you have to spell it something like [[=^=]...], not [\^...] (that is, since \^ inside [] does NOT treat the \ as an escape character, but as yet another literal character as part of the brakcet group, you instead have to resort to calling out the literal character ^ via alternative spellings such as by a collation equivalent). Another alternative is to rewrite the [] bracket exprsesion so that ^ is no longer first (but be careful if the character after ^ is -, ], or !, as the rewrite is not always a trivial swap with the next character). -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org