-
-
Notifications
You must be signed in to change notification settings - Fork 151
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
[osh] arithmetic evaluation context in test clause #3
Comments
Wow I didn't know about this. Do you know if it's documented anywhere? I don't see it in "help [[". Osh actually doesn't parse a top-level "let" yet either. It seems fairly rare -- I think I encountered it exactly once, in Kubernetes, out of hundreds lines of code parsed. Most people use (( )); I think let is basically a ksh-ism. I noticed that let basically like (( )) except the tokenization is more strict, as in your example.
I also noticed that boolean operands can be stuff like:
So this means additionally that boolean operands have to be parsed as arithmetic expressions. Thanks for pointing it out. I accept this as a bug for bash compatibility, but I'm prioritizing based on usage in the wild. Have you encountered this in the wild or is it a corner case you noticed? |
note: the current error is as follows. In any case it shouldn't be an assertion; it should produce a parse error until it's supported.
|
Ja, it appears not to be documented in bash, probably it's somewhere in By the way, ksh considers those arithmetic binary operators as obsolete,
And comments it while describing the "test" builtin command in "Command
That is, in ksh and mksh that thing is valid in the test builtin command and For the test clause in bash, see also its real manual, declare -i s=;
s='(x=5, y[10]+=5), x*=y[10], y[2]==y[10] ? 1 : 0';
declare -p s x y; I suppose that # My first example can be written as:
let x=5 y[10]+=5 x\*=y[10] y[2]==y[10]\?1:0;
s=$? declare -p s x y;
# And yours also as:
let i=1+2 i;
s=$? declare -p s i;
# But see:
_let () { IFS=,; (($*)); };
_let i=1+2 i;
s=$? declare -p s i; And there is a special dealing with environment variables in let: # builtin
i=1+2 let i=i;
s=$? __=$_ declare -p s __ i;
# func
_let () (($*));
i=1+2 _let i=i;
s=$? __=$_ declare -p s __ i; |
Yeah I thought about it last night, and I think there is just a function in bash which is basically "try as hard as you can to convert an arbitrary word (string) to an integer, for use in arithmetic". That function handles 0x10, 64#123, and it ALSO tries to parse the word as an arithmetic expression and evaluate it, which is bizarre. This function is used in lots of places:
And probably all the other places I mentioned that arithmetic expressions are used [1], except for some reason it doesn't work inside $(( )).
I think this is just sloppiness in bash implementation. The author probably just reused this function in a bunch of places, not quite realizing that it leads to horrible language design. A lot of bash has that flavor where it only considers what you CAN do with the language; it doesn't care what you CAN'T do. The error paths are underspecified. So yeah the philosophy is if that people are using this "in the wild" we could copy it, but I don't want to cargo cult horrible design mistakes. [1] http://www.oilshell.org/blog/2016/10/19.html (end of this post) |
I'm closing this since I haven't run into any shell scripts that rely on this behavior. It is documented here, and came up a month or so ago on help-bash@ ! Anyway thanks for the heads up -- that was the first I've heard of it! |
Info: Documented in bash.1 since http://git.savannah.gnu.org/cgit/bash.git/commit/doc/bash.1?h=bash-5.0-testing&id=9a51695bed07d37086c352372ac69d0a30039a6b |
Hm this doesn't fix the infinite loop in case #3 of spec/alias? Still need to work on that. mylib: add comments and test cases
Why didn't this happen on my own machine? http://travis-ci.oilshell.org/srht-jobs/2021-02-06__19-34-07.wwz/_tmp/toil/logs/cpp-unit-all.txt --> COLLECT with 0 roots i = -2147483648 .AddressSanitizer:DEADLYSIGNAL ================================================================= ==3052==ERROR: AddressSanitizer: SEGV on unknown address 0x7f8666c53034 (pc 0x55618e7f6d5b bp 0x7ffc429f1190 sp 0x7ffc429f1180 T0) ==3052==The signal is caused by a READ memory access. #0 0x55618e7f6d5a in gc_heap::str_equals(gc_heap::Str*, gc_heap::Str*) /home/build/oil/mycpp/gc_heap.cc:260 #1 0x55618e7dafd0 in str_replace_test /home/build/oil/mycpp/my_runtime_test.cc:162 #2 0x55618e7e7bd6 in main /home/build/oil/mycpp/my_runtime_test.cc:779 #3 0x7f866924109a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409a) #4 0x55618e7d94b9 in _start (/home/build/oil/mycpp/_bin/my_runtime_test.asan+0xd4b9) AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV /home/build/oil/mycpp/gc_heap.cc:260 in gc_heap::str_equals(gc_heap::Str*, gc_heap::Str*)
If you use the test compound command with arithmetic binary operators, there is also a whole let expression available. In bash you can write stuff like:
osh gives me an AssertionError then.
The text was updated successfully, but these errors were encountered: