On Mon, Jun 2, 2014 at 4:44 PM, Chet Ramey <chet.ra...@case.edu> wrote:
> On 6/2/14, 8:21 AM, Greg Wooledge wrote: > > On Fri, May 30, 2014 at 09:28:13PM -0500, Dan Douglas wrote: > >> The problem is most people don't realize how "variables" are evaluated. > >> Any time the shell needs to reference a variable, it takes a string > >> like: "arr[$foo]" and, if there's an index, the string within the index > >> gets processed for expansions. The arithmetic evaluator is no exception. > > > > I'm trying to understand this, but it's not clear to me yet. > > > > imadev:~$ x='$(date)' > > imadev:~$ : $(($x)) > > bash: $(date): syntax error: operand expected (error token is "$(date)") > > > > That looks OK. > > > > imadev:~$ : $((a[$x])) > > bash: Mon Jun 2 08:06:39 EDT 2014: syntax error in expression (error > token is "Jun 2 08:06:39 EDT 2014") > > > > There's the code-injection problem that started the thread. > > > > imadev:~$ : ${a[$x]} > > bash: $(date): syntax error: operand expected (error token is "$(date)") > > > > That also looks OK. > > > > Why is there no code injection in the last example? There is an index. > > According to your paragraph, "... the string within the index gets > > processed for expansions. The arithmetic evaluator is no exception." > > The arithmetic evaluator is, in fact, an exception. That, combined with > the expansions that happen before the arithmetic evaluator gets hold of > the expression -- and it is an expression -- leads to the difference. > > In the first case, the arithmetic evaluator sees `a[$(date)]' as the > expression after parameter expansion is performed: > > "All tokens in the expression undergo parameter and variable expansion, > command substitution, and quote removal. The result is treated as the > arithmetic expression to be evaluated." > > Since that expression looks like a variable expansion, the following > sentence in the description of arithmetic evaluation is applicable: > > "Within an expression, shell variables may also be referenced by name > without using the parameter expansion syntax. A shell variable that > is null or unset evaluates to 0 when referenced by name without using the > parameter expansion syntax." > > The a[$(date)] is identified as an array index, so the $(date) is expanded > like any other index, and evaluated as an expression. > > This is what lets you use things like 'x+1' and 'x[y+1]' in arithmetic > expansions. > > The parameter expansion example (${a[$x]}) doesn't undergo that `extra' > expansion. The index that ends up being passed to the evaluator is `$x', > which is expanded to `$(date)'. That is treated as an expression and > evaluation fails. > > Chet > -- > ``The lyf so short, the craft so long to lerne.'' - Chaucer > ``Ars longa, vita brevis'' - Hippocrates > Chet Ramey, ITS, CWRU c...@case.edu > http://cnswww.cns.cwru.edu/~chet/ > Even if there is a perfectly good justification as to why this works, I still think this is a terribly broken feature of the language. The number of shell scripters, even experimented, that will realize that $((a["$i"])) makes code injection possible is probably very close to 0 while the first thing an script kid would do to create trouble is to embed $( ) in his strings.