On 27/03/2018 17:14, Herbert Xu wrote:
On Tue, Mar 27, 2018 at 02:57:12PM +0200, Harald van Dijk wrote:
That's a good point and wouldn't have too much of an impact on performance
of existing scripts. BTW, that means both expandmeta()'s metachars variable,
if (metaflag == 0 || lstat64(expdir, &statb) >= 0)
optimisation. You already got rid of the latter in your patch to prevent
No the purpose of this metaflag check is to bypass the lstat call.
My patch simply made it bypass the call by returning earlier.
It is not relevant to whether we include backslash as a metacharacter.
I was thinking about not making backslashes set metaflag in expmeta():
when the pathname component doesn't include *, ?, or [, but does include
backslashes, then the if (metaflag == 0) block could handle that as long
as it performs the lstat64() check unconditionally. There's no need to
go through the opendir()/readdir()/closedir() path for that case. Since
expmeta() is bypassed for words not containing any potentially-magic
characters, the impact might be small enough.
Regardless of whether metaflag is set, it would mean things like 'set
"["' would start hitting the FS unnecessarily, if I understand
correctly: the preglob()-expanded pattern is '\[', and expmeta() can no
longer tell this apart from $v where v='\[' where a FS check would be
Perhaps preglob() should just be avoided, and expmeta() taught to
respect both '\\' and CTLESC. '\\' would be a metacharacter and require
a FS hit, CTLESC wouldn't require it. This would also avoid some memory
In regular /d\ev that doesn't come from a variable, the backslash will have
been replaced by CTLESC, but it's not necessary to treat CTLESC as a
metacharacter: in that case, either there's a match and pathname expansion
produces /dev, or there's no match and quote removal produces /dev, so the
optimisation is still valid. It'd only affect backslashes that come from a
variable, so it's very limited in scope.
For the case where the backslash came from the parser, the CTLESC
would have already been removed by preglob so there should be no
if (!strpbrk(str->text, metachars))
in expandmeta() is done before preglob() is called. Here, it is still
not necessary to include CTLESC.
The only problem with the metacharacter approach is that glibc's
glob(3) probably won't treat it as a metacharacter and therefore
it will still behave in the same way as the current bash.
This doesn't matter much yet, but yeah, it will if you decide to enable
--enable-glob by default in the future. As long as you don't include
GLOB_NOESCAPE, then normally, it should be taken as escaping the next
character, but it might still trigger GLOB_NOMAGIC to return early. If
it does, I'd take that as a glibc bug, but that doesn't help dash.
Harald van Dijk
To unsubscribe from this list: send the line "unsubscribe dash" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html