autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 2/5] docs: mention cost of globbing during variable expansion


From: Eric Blake
Subject: Re: [PATCH 2/5] docs: mention cost of globbing during variable expansion
Date: Thu, 26 Aug 2010 07:45:30 -0600
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.8) Gecko/20100806 Fedora/3.1.2-1.fc13 Mnenhy/0.8.3 Thunderbird/3.1.2

On 08/25/2010 09:40 PM, Gary V. Vaughan wrote:
@example
-: address@hidden'Some words'@}
+$ time bash -c ': "address@hidden/usr/bin/address@hidden"; echo "$a"'
+real   0m0.005s
+$ time bash -c ': address@hidden/usr/bin/address@hidden; echo "$a"'
+real   0m0.039s

Really?  Not here:

; bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
Copyright (C) 2007 Free Software Foundation, Inc.
; time bash -c ': "${var=usr/bin/*}"; echo $var'

; time bash -c ': ${var=usr/bin/*}; echo $var'

You weren't testing the same thing. "usr/bin/*" will be much faster at globbing if ./usr does not exist; try 'cd /' and repeat your test, or use my test of "/usr/bin/*". For an even more dramatic effect, try "/*/*" as your glob. You can also use 'set -x' to make the shell confess that it is doing globbing, or view strace/truss results to see the difference in the number of syscalls.


Does this only affect old/brain-damaged shells?

I tested bash 4.1 and current dash. Dash was faster all around, but the difference was still there. (It may be worth a QoI bug report to these particular shells to implement an optimization that no-op globbing be suppressed behind : except when set -x is in effect.)

address@hidden
+: "address@hidden'Some words'@}"
@end example

Still not sold on the outer double quotes...

That example is wrong, as demonstrated by my followup patch. You either use inner quotes or outer quotes, but not both (unless you intended for the inner quotes to be part of the variable assignment). Sorry for checking in a half-tested patch in the first place.

default="yu,yaa"
-: address@hidden"$default"@}
+: "address@hidden"$default"@}"
@end example

I don't understand this either, since it is tokenised like this:

   :
   ${var=
   $default     =>  expanded, globbed and split
   }

This one's even worse - it is undefined per POSIX, and behaves differently on bash (acts as nested quoting), ksh (breaks the tokenization into parts, such that $default is globbed), and /bin/sh (outright rejected). Again, fixed in my next patch.

Where earlier you say that $default should be quoted.  I've reread
the newly edited section of the manual through twice, and while I
appreciate that you're trying to give an example of triggering a
shell bug on Solaris and/or OSF... the "nested" double quotes in
the example look extremely weird - I don't think anyone would
accidentally or otherwise quote the ${var= and } token but leave
the variable expansion unquoted.  Or are you trying to show a
situation where that is necessary to avoid bugs?  Maybe the manual
is just confusing in this section, and I misunderstand?

I misunderstood when I wrote my first patch, and hopefully did a lot better job on the followup patch.

# with $RANDOM to make collisions less likely.
-: address@hidden/address@hidden
+: "address@hidden/address@hidden"

Surely, with a literal containing no spaces, glob meta chars or
closing braces, scanning the extra two characters is actually
infinitesimally slower, but otherwise functionally identical?

Not true, if $TMPDIR already has a value that contains globbing characters (of course, the likelihood of this is slim, but the whole point of ${a=b} is that you are assigning a value to $a _if_ it doesn't already have one, which implies that you are also admitting that $a may already have an unspecified value inherited from the user - and we know that it is never a good idea to blindly trust user input to be sane.

$ foo=/usr/bin/*
$ time : ${foo=safe}

real    0m0.030s
user    0m0.019s
sys     0m0.009s

$ time : "${foo=safe}"

real    0m0.000s
user    0m0.000s
sys     0m0.000s
$ echo "$foo"
/usr/bin/*

+    : "${build_alias=$ac_option} ${host_alias=$ac_option} 
${target_alias=$ac_option}"
     ;;

Agreed - although I prefer the look of:

   : ${build_alias="$ac_option"} ${host_alias="$ac_option"} 
${target_alias="$ac_option"}

Not the same. Your variant is still subject to globbing. But I could see going with:

: "${build_alias=$ac_option}" "${host_alias=$ac_option}" "${target_alias=$ac_option}"

(that is, three non-globbed arguments instead of one).

--
Eric Blake   address@hidden    +1-801-349-2682
Libvirt virtualization library http://libvirt.org



reply via email to

[Prev in Thread] Current Thread [Next in Thread]