Hello, here is another bashbug report. Configuration Information [Automatically generated, do not change]: Machine: i686 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/home/murase/opt/bash-4.4/share/locale' -DPACKAGE='ba\ sh' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -O2 -march=native -Wno-parentheses -Wno-format-security uname output: Linux padparadscha 4.7.2-101.fc23.i686 #1 SMP Fri Aug 26 16:39:46 UTC 2016 i686 i686 i386 GNU/Linux Machine Type: i686-pc-linux-gnu
Bash Version: 4.4 Patch Level: 0 Release Status: release Description: Variables in the discarded branches of conditional expressions are evaluated. This is caused by the function `evalcond' in expr.c. The calls of `readtok' in `evalcond' are made before the global variable `noeval' is set up. Repeat-By: $ bash-4.4 -c 'a=0 x="a=1"; ((0?x:0)); echo $a' 1 $ bash-4.4 -c 'a=0 x="a=1"; ((1?0:x)); echo $a' 1 The value 1 is set by the evaluation of x. But I expect the result 0 because the variable `x' is in the discarded branch and therefore is natural not to be evaluated. All the other similar patterns returns 0: $ bash-4.4 -c 'a=0 x="a=1"; ((0?(x):0)); echo $a' 0 $ bash-4.4 -c 'a=0 x="a=1"; ((0?$x:0)); echo $a' 0 In addition, variables in logical and/or expressions are not evaluated if the branch is not selected: $ bash-4.4 -c 'a=0 x="a=1"; ((0&&x)); echo $a' 0 $ bash-4.4 -c 'a=0 x="a=1"; ((1||x)); echo $a' 0 There is another pattern caused by the same bug. $ bash-4.4 -c 'a=0; ((0?arr[a=1]:0)); echo $a' 1 All the versions of bash from 3.0 to 4.4 behave the same. Is the result `1' intended? It's not intuitive for me. Fix: In `evalcond', the selection of branches are controlled by setting the global variable `noeval'. While, evaluation of variables are made in `readtok'. The function `readtok' is aware of `noeval', but is called by `evalcond' before `noeval' is modified. In the following patch, the calls of `readtok' are moved after the set of `noeval'. diff --git a/expr.c b/expr.c index 1ddb693..ad3e24d 100644 --- a/expr.c +++ b/expr.c @@ -578,24 +578,21 @@ expcond () rval = cval = explor (); if (curtok == QUES) /* found conditional expr */ { - readtok (); - if (curtok == 0 || curtok == COL) - evalerror (_("expression expected")); if (cval == 0) { set_noeval = 1; noeval++; } + readtok (); + if (curtok == 0 || curtok == COL) + evalerror (_("expression expected")); val1 = EXP_HIGHEST (); if (set_noeval) noeval--; if (curtok != COL) evalerror (_("`:' expected for conditional expression")); - readtok (); - if (curtok == 0) - evalerror (_("expression expected")); set_noeval = 0; if (cval) { @@ -603,7 +600,11 @@ expcond () noeval++; } + readtok (); + if (curtok == 0) + evalerror (_("expression expected")); val2 = expcond (); + if (set_noeval) noeval--; rval = cval ? val1 : val2; Regards, Koichi