From 5b2cc0aaee6985431d9bab1b49ceea7e1fa1d7af Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 18 Jul 2017 02:44:06 +0200 Subject: [PATCH] hush: do not assign to readonly VAR in "VAR=VAL CMD" syntax too Signed-off-by: Denys Vlasenko --- shell/hush.c | 9 ++++++- shell/hush_test/hush-vars/readonly0.right | 6 +++-- shell/hush_test/hush-vars/readonly0.tests | 30 ++++++++++++++++------- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index eab1284f6..55e581e16 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -2089,6 +2089,8 @@ static int set_local_var(char *str, unsigned flags) if (cur->flg_read_only) { bb_error_msg("%s: readonly variable", str); free(str); +//NOTE: in bash, assignment in "export READONLY_VAR=Z" fails, and sets $?=1, +//but export per se succeeds (does put the var in env). We don't mimic that. return -1; } if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ? @@ -2283,8 +2285,12 @@ static struct variable *set_vars_and_save_old(char **strings) if (eq) { var_pp = get_ptr_to_local_var(*s, eq - *s); if (var_pp) { - /* Remove variable from global linked list */ var_p = *var_pp; + if (var_p->flg_read_only) { + bb_error_msg("%s: readonly variable", *s); + goto next; + } + /* Remove variable from global linked list */ debug_printf_env("%s: removing '%s'\n", __func__, var_p->varstr); *var_pp = var_p->next; /* Add it to returned list */ @@ -2293,6 +2299,7 @@ static struct variable *set_vars_and_save_old(char **strings) } set_local_var(*s, SETFLAG_EXPORT); } + next: s++; } return old; diff --git a/shell/hush_test/hush-vars/readonly0.right b/shell/hush_test/hush-vars/readonly0.right index 9688d2e5f..07ca6e07f 100644 --- a/shell/hush_test/hush-vars/readonly0.right +++ b/shell/hush_test/hush-vars/readonly0.right @@ -5,8 +5,10 @@ hush: a=A: readonly variable Fail:1 hush: a=A: readonly variable Fail:1 -hush: a=A: readonly variable +hush: a=Z: readonly variable Fail:1 -Visible:0 +hush: a=Z: readonly variable +b=B +^^^a is not exported hush: a: readonly variable Fail:1 diff --git a/shell/hush_test/hush-vars/readonly0.tests b/shell/hush_test/hush-vars/readonly0.tests index 3845f76ac..3ace9b767 100755 --- a/shell/hush_test/hush-vars/readonly0.tests +++ b/shell/hush_test/hush-vars/readonly0.tests @@ -1,10 +1,12 @@ +unset a b + readonly a=A b=B readonly b -# readonly on already readonly var is harmless +# readonly on already readonly var is harmless: readonly b a readonly | grep '^readonly [ab]=' -# this should work +# this should work: export a b export -n a b echo Ok:$? @@ -12,13 +14,23 @@ env | grep -e^a= -e^b= # shows nothing # these should all fail (despite the same value being assigned) # bash does not abort even in non-interactive more (in script) -true -a=A +true; a=A +echo Fail:$? +true; readonly a=A +echo Fail:$? + +# in bash, assignment in export fails, but export succeeds! :) +# we don't mimic that! +true; export a=Z echo Fail:$?; true -readonly a=A -echo Fail:$?; true -export a=A -echo Fail:$?; true -a=A echo Visible:$? # command still runs +#env | grep '^a=' +#echo "^^^a is exported" +export -n a # undo that bashism, if it happens + +export b +# this fails to both set and export a: +a=Z env | grep '^[ab]=' # command still runs +echo "^^^a is not exported" + unset a echo Fail:$?; true