-
-
Notifications
You must be signed in to change notification settings - Fork 158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Common bash-compatible syntax to avoid expansion of (associative) array subscripts (ble.sh) #645
Comments
I think this it the same issue as #648. Arithmetic is always static, and there's no recursive evaluation, regardless of where it appears -- in array indices, or in |
OK now that I look carefully I see what's going on... This is very confusing and exactly why I didn't reproduce that behavior in Oil! However I see that it would be better to have a single syntax that works in BOTH bash and Oil. That is, a common subset. Let me think about this... BTW is |
This feels like a bug in bash to me. The bash maintainer has a habit of claiming that bugs were intentional behavior when they were really accidents of the implementation. Is it documented anywhere? Not that it really changes anything, because what's done is done, but still I would call it more like working around a bug in bash than anything. Also
I do NOT get |
It's not a special construct of the form $ key=123; echo $key \$key
123 $key
$
Actually I have a similar feeling, but I don't know better solutions as far as one wants to support (associative) arrays by extending the POSIX arithmetic expression. POSIX specifies the order of the shell expansions and the arithmetic evaluation for the construct
In principle, we might not have to follow the POSIX when extensions such as the associative arrays are used, but it's even worse that we have different syntactic treatment of arithmetic expressions depending on whether the extension is contained or not in the expression. As far as we follow the POSIX evaluation order, Zsh behaves similarly to Bash in this situation (but not exactly the same). Zsh also performs extra array-subscript expansions. I just tried zsh to obtain the following results. Zsh only works as expected with $ zsh --version
zsh 5.7.1 (x86_64-redhat-linux-gnu)
$ zsh -c 'x=1],e[; declare -A d=(["$x"]=123); echo $((d[$x]))'
0
$ zsh -c 'x=1],e[; declare -A d=(["$x"]=123); echo $((d["$x"]))'
0
$ zsh -c 'x=1],e[; declare -A d=(["$x"]=123); echo $((d[\$x]))'
123
$ zsh -c 'x=1],e[; declare -A d=(["$x"]=123); echo $((d['\''$x'\'']))'
0 I tried ksh and found that ksh seems to have given up complete compatibility with POSIX. It seems like evaluating $ ksh -c 'x=1],e[1; d[9]=123; echo $((d[$x]))'
ksh: 1],e[1: arithmetic syntax error
$ ksh -c 'x=1],e[1; d[9]=123; echo $((d["$x"]))'
ksh: 1],e[1: arithmetic syntax error
$ ksh -c 'x=9; d[9]=123; echo $((d[\$x]))'
123
$ ksh -c 'x=9; d[9]=123; echo $((d['\''$x'\'']))'
123 Actually this topic pops up occasionally in bug-bash mailing list, but the behavior is unlikely to be changed. Also I don't have an idea on what would be the better solution. For example, see the following discussions in the mailing list: https://lists.gnu.org/archive/html/bug-bash/2014-06/msg00003.html
I would say nowhere. In the above 2014-06 discussion, the Bash maintainer, Chet, explains the behavior quoting the Bash documents, but actually I haven't yet understood his logic for this. Chet tends to say something like "it's implied by the description here".
Oh, I didn't know that. Thank you! |
Yeah bash 4.3 is already 7 years old, so I think this is just an old bug in bash. And yes those threads are good examples of the confusion over bash -- i.e. undocumented behavior and post-hoc rationalizations of the implementation. That is one of the main reasons for Oil. In any case the
Since you're avoiding associative arrays within |
Also, |
OK I don't think there's anything to be done here (whew) |
I think It actually depends on the context. In the construct But POSIX doesn't define the arithmetic command Edit: I'm sorry... I noticed the inconsistency of my discussion. I was confused. for bash in $(compgen -c -- bash- | sort); do
echo -n $bash:
$bash -c 'i=9; a[9]=123; : $((b=a['\''$i'\'']));echo $b'
done
bash-2.05b.13:123
bash-3.0.22:123
bash-3.1.23:123
bash-3.2.57:123
bash-4.0.44:123
bash-4.1.17:123
bash-4.2.53:123
bash-4.3.48:123
bash-4.4.23:bash-4.4.23: '9': syntax error: operand expected (error token is "'9'")
bash-5.0.7:bash-5.0.7: '9': syntax error: operand expected (error token is "'9'")
bash-dev:bash-dev: '9': syntax error: operand expected (error token is "'9'")
I think it's useful to warn about this issue somewhere (maybe in the section of static arithmetic parsing of known-differences?). Thank you. |
Hm well if you want to draft some text about how to use associative arrays in a way that's compatible with (newer versions of) bash and Oil, I will include it :) Or feel free to send me a PR. I'm a little confused -- personally I would just use the workarounds so that you have |
e.g. personally I would limit my dialect inside and outside of
That's basically how I designed Oil... I DID encounter a lot of bugs in bash while I was implementing this feature, e.g. in https://www.oilshell.org/release/0.8.pre2/test/spec.wwz/assoc.html Basically I don't want to use anything that requires me to remember specific rules inside I believe Oil is pretty "context independent". There are only a few obvious differences between command context and arithmetic context. The additional http://www.oilshell.org/blog/2019/01/18.html#a-story-about-a-30-year-old-security-problem because the exploit is allowed within |
I guess I could write that last comment as the advice in Oil's docs, but if you have something better, let me know :) And I appreciate the testing because this was one place where I knew it may be hard to come up with a common subset of bash and Oil. But if bash itself is changing in undocumented ways, then there's limited hope to begin with. |
I think that's enough (just something like "Do not reference associative array elements in arithmetic expressions"). |
Another way to say it is that Oil is supposed to obey the invariant that
is the same as
for all arithmetic expressions X and Y. Bash doesn't obey that and I'd argue that all the differences are undocumented bugs. I didn't test that invariant but I'm pretty sure it should hold ... |
Related to the above issue, I noticed that the interpretation is different in Oil and Bash. In Bash, the subscripts of arrays and associative arrays in arithmetic expressions are subject of the shell expansions in the arithmetic evaluation phase. As a consequence, for example, the following commands produces the same results in Bash:
Oil produces syntax errors for the latter two cases:
One of the reason why Bash performs the shell expansions on the array subscript in the arithmetic evaluation phase is related to the case where the array subscript variable
$x
contains a value resembling arithmetic expressions. In Bash, normal shell expansions are processed before parsing the arithmetic expression. So the array subscript needs to be deferred by quoting. See the following example:For this reason, the parameter expansion of the variables (whose value is not under control of the script) appearing in the array subscripts of the arithmetic expression must be quoted always in Bash scripts. If some Bash script has unquoted parameter expansion of array subscripts in the arithmetic expression, it's a bug of that script. This Bash behavior seems strange and not user friendly, but that's a sad compatibility burden coming from the shell history.
The text was updated successfully, but these errors were encountered: