On Friday, May 30, 2014 08:57:42 PM Pierre Gaston wrote: > It doesn't seem right for code looking as innocent as $((a[$i])) or > $((a["$i"])) to allow running arbitrary commands for some value of i, that > are no even that clever: > > $ i='$( echo >&2 an arbitrary command )';: $((a["$i"])) > an arbitrary command > > $ i='"$( echo >&2 an arbitrary command)"';: $((a[$i])) > an arbitrary command
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. The correct way to write such a thing is to let the variable evaluation expand the parameter from the arithmetic evaluator: $ bash -c 'typeset -A a; i=\" a[$i]=1+1; echo "$((a[\$i]))"' 2 $ ksh -c 'typeset -A a; i=\" a[$i]=1+1; echo "$((a[\$i]))"' 2 $ zsh -c 'typeset -A a; i=\" a[$i]=1+1; echo "$((a[\$i]))"' 2 Just to clarify, this came up during a discussion in freenode/#ksh (I believe Jilles Tjoelker first pointed out the issue). He noticed that ksh93 in some cases allows associative array indexes to be interpreted differently by the arithmetic evaluator. Namely, if `i=]` or `i=\"` then ksh uses that value as the index. Bash simply performs all the usual expansions then takes the resulting string and passes it to the arithmetic evaluator. But notice that even ksh processes indexes for expansions. I don't know why it allows those specific exceptions, and I think I even found a bug in ksh here. # Bash is correct here AFAICT. $ bash -c 'typeset -A a; i="\$(echo \\\")" a[\"]=1+1; echo "$((a[$i]))"' 2 # ksh93 fails this test: $ ksh -c 'typeset -A a; i="\$(echo \\\")" a[\"]=1+1; echo "$((a[$i]))"' ksh: syntax error at line 1: `end of file' unexpected -- Dan Douglas