Skip to content
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

toybox sh segfault on "case" of empty string #354

Open
ScoreUnder opened this issue Jun 7, 2022 · 0 comments
Open

toybox sh segfault on "case" of empty string #354

ScoreUnder opened this issue Jun 7, 2022 · 0 comments

Comments

@ScoreUnder
Copy link

ScoreUnder commented Jun 7, 2022

crash.sh:

empty_str=""
case $empty_str in
esac

invocation: toybox sh crash.sh

version: 0.8.7

expected: valid program; no output; exit code zero

actual: segmentation fault / crash


This was minimised from a larger script. Originally there were specific patterns inside the case statement, but even with them all removed it still crashes. It only crashes if the empty string is contained in a variable; it does not crash if you use an empty string as a literal instead.

The crash happens here:

Program received signal SIGSEGV, Segmentation fault.
expand_one_arg (new=new@entry=0x5555555da0b0 "$empty_str", flags=flags@entry=32, del=del@entry=0x5555555da198) at toys/pending/sh.c:2265
2265	    if (!(s = *arg.v) && (flags&(SEMI_IFS|NO_NULL))) s = "";
(gdb) bt
#0  expand_one_arg (new=new@entry=0x5555555da0b0 "$empty_str", flags=flags@entry=32, del=del@entry=0x5555555da198) at toys/pending/sh.c:2265
#1  0x000055555558b2d5 in run_lines () at toys/pending/sh.c:3538
#2  do_source (name=name@entry=0x7fffffffdfe3 "crash.sh", ff=<optimized out>) at toys/pending/sh.c:3794
#3  0x000055555558f022 in sh_main () at toys/pending/sh.c:3996
#4  0x000055555556e40d in toy_exec_which (which=<optimized out>, argv=<optimized out>) at main.c:220
#5  0x000055555556e4ba in toybox_main () at main.c:246
#6  0x000055555556e40d in toy_exec_which (which=<optimized out>, argv=<optimized out>) at main.c:220
#7  0x000055555556e4ba in toybox_main () at main.c:246
#8  0x00005555555653ab in main (argc=<optimized out>, argv=<optimized out>) at main.c:293
(gdb) inf loc
arg = {v = 0x0, c = 0}
s = 0x0
(gdb) up
#1  0x000055555558b2d5 in run_lines () at toys/pending/sh.c:3538
3538	          TT.ff->blk->fvar = expand_one_arg(ss, NO_NULL, &TT.ff->blk->fdelete);
(gdb) inf loc
ctl = 0x0
pplist = 0x0
j = <optimized out>
ss = 0x5555555da0b0 "$empty_str"
[... snip, all others are optimised out at -O0]

I don't know much about the inner workings of this shell, but my intuition as a shell scripter(!! lol) says that expand_arg(..., NO_SPLIT, ...) should result in a single-argument empty string rather than an empty argument count if the argument is empty. I have checked with the debugger and it is getting NO_NULL passed into its flags here too, but as far as I can tell that's a different meaning entirely (related to internal error handling?).

Note that a case statement without patterns is not valid according to the POSIX spec but it seems to be a widely accepted construction despite this. If it needs regression testing it might be worth considering a dummy pattern to satisfy that syntax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant