Suspicious BUG in hush, while 'elif' has more commands than 1, only the first command is executed

Denys Vlasenko vda.linux at googlemail.com
Thu May 25 12:39:45 UTC 2023


Thanks for the report.
Fixed in git.

On Fri, May 19, 2023 at 9:07 AM vsfos <vsfos at qq.com> wrote:
>
> Tested on wsl ubuntu 22.04 and linux orangepi5 by executing scripts below:
>
> #!/bin/sh
> if false; then
>     : nothing
> elif echo 'test-1'; echo 'test-2' ; echo 'test-3'; then
>     echo "abcdefg-1"
> fi
> echo again
> if echo 'test-1'; echo 'test-2' ; echo 'test-3'; then
>     echo "abcdefg-1"
> fi
>
> Output will be like below on hush:
> test-1
> again
> test-1
> test-2
> test-3
> abcdefg-1
>
> On bash, output will be
> test-1
> test-2
> test-3
> abcdefg-1
> again
> test-1
> test-2
> test-3
> abcdefg-1
>
> exec log:
> parse_and_run_stream: run_and_free_list
> run_and_free_list entered
> : run_list: 1st pipe with 1 cmds
> run_list start lvl 0
>   : rword=0 cond_code=0 last_rword=17
>   : run_pipe with 1 members
>   run_pipe start: members:1
>     : group:0 argv:'./test'
>     : pipe member './test' '  run_pipe return -1 (1 children started)
>   execing './test'
> parse_and_run_stream: run_and_free_list
> run_and_free_list entered
> : run_list: 1st pipe with 0 cmds
> run_list start lvl 0
>   : rword=0 cond_code=0 last_rword=17
> run_list lvl 1 return 0
> run_and_free_list return 0
> parse_and_run_stream: run_and_free_list
> run_and_free_list entered
> : run_list: 1st pipe with 1 cmds
> run_list start lvl 0
>   : rword=0 cond_code=0 last_rword=17
>   : run_pipe with 1 members
>   run_pipe start: members:1
>     : group:71a768 argv:'NONE'
>     non-subshell group
>     : run_list
>     run_list start lvl 1
>       : rword=1 cond_code=0 last_rword=17
>       : run_pipe with 1 members
>       run_pipe start: members:1
>         : group:0 argv:'false'
>         : pipe member 'false' '      run_pipe return -1 (1 children started)
>       execing 'false'
>       : checkjobs exitcode 255
>       : rword=2 cond_code=255 last_rword=1
>       : rword=3 cond_code=255 last_rword=2
>       : run_pipe with 1 members
>       run_pipe start: members:1
>         : group:0 argv:'echo'
>         found builtin 'echo'
>         : builtin 'echo' 'test-1'...
> test-1
>       run_pipe return 0
>       : builtin/func exitcode 0
>       : rword=3 cond_code=0 last_rword=3
>     run_list lvl 2 return 0
>   run_pipe: return 0
>   : builtin/func exitcode 0
>   : rword=0 cond_code=0 last_rword=0
> run_list lvl 1 return 0
> run_and_free_list return 0
> parse_and_run_stream: run_and_free_list
> run_and_free_list entered
> : run_list: 1st pipe with 1 cmds
> run_list start lvl 0
>   : rword=0 cond_code=0 last_rword=17
>   : run_pipe with 1 members
>   run_pipe start: members:1
>     : group:0 argv:'echo'
>     found builtin 'echo'
>     : builtin 'echo' 'again'...
> again
>   run_pipe return 0
>   : builtin/func exitcode 0
>   : rword=0 cond_code=0 last_rword=0
> run_list lvl 1 return 0
> run_and_free_list return 0
> parse_and_run_stream: run_and_free_list
> run_and_free_list entered
> : run_list: 1st pipe with 1 cmds
> run_list start lvl 0
>   : rword=0 cond_code=0 last_rword=17
>   : run_pipe with 1 members
>   run_pipe start: members:1
>     : group:71a768 argv:'NONE'
>     non-subshell group
>     : run_list
>     run_list start lvl 1
>       : rword=1 cond_code=0 last_rword=17
>       : run_pipe with 1 members
>       run_pipe start: members:1
>         : group:0 argv:'echo'
>         found builtin 'echo'
>         : builtin 'echo' 'test-1'...
> test-1
>       run_pipe return 0
>       : builtin/func exitcode 0
>       : rword=1 cond_code=0 last_rword=1
>       : run_pipe with 1 members
>       run_pipe start: members:1
>         : group:0 argv:'echo'
>         found builtin 'echo'
>         : builtin 'echo' 'test-2'...
> test-2
>       run_pipe return 0
>       : builtin/func exitcode 0
>       : rword=1 cond_code=0 last_rword=1
>       : run_pipe with 1 members
>       run_pipe start: members:1
>         : group:0 argv:'echo'
>         found builtin 'echo'
>         : builtin 'echo' 'test-3'...
> test-3
>       run_pipe return 0
>       : builtin/func exitcode 0
>       : rword=2 cond_code=0 last_rword=1
>       : run_pipe with 1 members
>       run_pipe start: members:1
>         : group:0 argv:'echo'
>         found builtin 'echo'
>         : builtin 'echo' 'abcdefg-1'...
> abcdefg-1
>       run_pipe return 0
>       : builtin/func exitcode 0
>       : rword=5 cond_code=0 last_rword=2
>       : rword=0 cond_code=0 last_rword=5
>     run_list lvl 2 return 0
>   run_pipe: return 0
>   : builtin/func exitcode 0
>   : rword=0 cond_code=0 last_rword=0
> run_list lvl 1 return 0
> run_and_free_list return 0
>   : checkjobs_and_fg_shell exitcode 0
>   : rword=0 cond_code=0 last_rword=0
> run_list lvl 1 return 0
> run_and_free_list return 0
>
> From the log, after the echo 'test-1' command, elif exited.
> The exit point is at here in run_list function:
> #if ENABLE_HUSH_IF
> if (cond_code) {
> if (rword == RES_THEN) {
> /* if false; then ... fi has exitcode 0! */
> G.last_exitcode = rcode = EXIT_SUCCESS;
> /* "if <false> THEN cmd": skip cmd */
> continue;
> }
> } else {
> if (rword == RES_ELSE || rword == RES_ELIF) {
> /* "if <true> then ... ELSE/ELIF cmd":
> * skip cmd and all following ones */
> break;  // <<<<---- here
> }
> }
> #endif
> Because echo returns 0, and current rword is elif.
> _______________________________________________
> busybox mailing list
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox


More information about the busybox mailing list