hush: do not assign to readonly VAR in "VAR=VAL CMD" syntax too

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2017-07-18 02:44:06 +02:00
parent 38ef39a1ab
commit 5b2cc0aaee
3 changed files with 33 additions and 12 deletions

View File

@ -2089,6 +2089,8 @@ static int set_local_var(char *str, unsigned flags)
if (cur->flg_read_only) { if (cur->flg_read_only) {
bb_error_msg("%s: readonly variable", str); bb_error_msg("%s: readonly variable", str);
free(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; return -1;
} }
if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ? if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
@ -2283,8 +2285,12 @@ static struct variable *set_vars_and_save_old(char **strings)
if (eq) { if (eq) {
var_pp = get_ptr_to_local_var(*s, eq - *s); var_pp = get_ptr_to_local_var(*s, eq - *s);
if (var_pp) { if (var_pp) {
/* Remove variable from global linked list */
var_p = *var_pp; 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); debug_printf_env("%s: removing '%s'\n", __func__, var_p->varstr);
*var_pp = var_p->next; *var_pp = var_p->next;
/* Add it to returned list */ /* 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); set_local_var(*s, SETFLAG_EXPORT);
} }
next:
s++; s++;
} }
return old; return old;

View File

@ -5,8 +5,10 @@ hush: a=A: readonly variable
Fail:1 Fail:1
hush: a=A: readonly variable hush: a=A: readonly variable
Fail:1 Fail:1
hush: a=A: readonly variable hush: a=Z: readonly variable
Fail:1 Fail:1
Visible:0 hush: a=Z: readonly variable
b=B
^^^a is not exported
hush: a: readonly variable hush: a: readonly variable
Fail:1 Fail:1

View File

@ -1,10 +1,12 @@
unset a b
readonly a=A readonly a=A
b=B b=B
readonly b readonly b
# readonly on already readonly var is harmless # readonly on already readonly var is harmless:
readonly b a readonly b a
readonly | grep '^readonly [ab]=' readonly | grep '^readonly [ab]='
# this should work # this should work:
export a b export a b
export -n a b export -n a b
echo Ok:$? echo Ok:$?
@ -12,13 +14,23 @@ env | grep -e^a= -e^b= # shows nothing
# these should all fail (despite the same value being assigned) # these should all fail (despite the same value being assigned)
# bash does not abort even in non-interactive more (in script) # bash does not abort even in non-interactive more (in script)
true true; a=A
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 echo Fail:$?; true
readonly a=A #env | grep '^a='
echo Fail:$?; true #echo "^^^a is exported"
export a=A export -n a # undo that bashism, if it happens
echo Fail:$?; true
a=A echo Visible:$? # command still runs 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 unset a
echo Fail:$?; true echo Fail:$?; true