hush: fix for readonly vars in "ro=A ro=B cmd" case

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-04-04 21:14:28 +02:00
parent 759ca8a4cb
commit 61407807ab
3 changed files with 21 additions and 13 deletions

View File

@ -2134,7 +2134,7 @@ static const char* FAST_FUNC get_local_var_value(const char *name)
#define SETFLAG_LOCAL_SHIFT 3 #define SETFLAG_LOCAL_SHIFT 3
static int set_local_var(char *str, unsigned flags) static int set_local_var(char *str, unsigned flags)
{ {
struct variable **var_pp; struct variable **cur_pp;
struct variable *cur; struct variable *cur;
char *free_me = NULL; char *free_me = NULL;
char *eq_sign; char *eq_sign;
@ -2155,10 +2155,10 @@ static int set_local_var(char *str, unsigned flags)
} }
#endif #endif
var_pp = &G.top_var; cur_pp = &G.top_var;
while ((cur = *var_pp) != NULL) { while ((cur = *cur_pp) != NULL) {
if (strncmp(cur->varstr, str, name_len) != 0) { if (strncmp(cur->varstr, str, name_len) != 0) {
var_pp = &cur->next; cur_pp = &cur->next;
continue; continue;
} }
@ -2182,7 +2182,7 @@ static int set_local_var(char *str, unsigned flags)
* and existing one is global, or local * and existing one is global, or local
* from enclosing function. * from enclosing function.
* Remove and save old one: */ * Remove and save old one: */
*var_pp = cur->next; *cur_pp = cur->next;
cur->next = *G.shadowed_vars_pp; cur->next = *G.shadowed_vars_pp;
*G.shadowed_vars_pp = cur; *G.shadowed_vars_pp = cur;
/* bash 3.2.33(1) and exported vars: /* bash 3.2.33(1) and exported vars:
@ -2226,8 +2226,8 @@ static int set_local_var(char *str, unsigned flags)
/* Not found - create new variable struct */ /* Not found - create new variable struct */
cur = xzalloc(sizeof(*cur)); cur = xzalloc(sizeof(*cur));
IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;) IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;)
cur->next = *var_pp; cur->next = *cur_pp;
*var_pp = cur; *cur_pp = cur;
set_str_and_exp: set_str_and_exp:
cur->varstr = str; cur->varstr = str;
@ -2272,7 +2272,7 @@ static void set_pwd_var(unsigned flag)
static int unset_local_var_len(const char *name, int name_len) static int unset_local_var_len(const char *name, int name_len)
{ {
struct variable *cur; struct variable *cur;
struct variable **var_pp; struct variable **cur_pp;
if (!name) if (!name)
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -2286,14 +2286,14 @@ static int unset_local_var_len(const char *name, int name_len)
G.lineno_var = NULL; G.lineno_var = NULL;
#endif #endif
var_pp = &G.top_var; cur_pp = &G.top_var;
while ((cur = *var_pp) != NULL) { while ((cur = *cur_pp) != NULL) {
if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
if (cur->flg_read_only) { if (cur->flg_read_only) {
bb_error_msg("%s: readonly variable", name); bb_error_msg("%s: readonly variable", name);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
*var_pp = cur->next; *cur_pp = cur->next;
debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr); debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
bb_unsetenv(cur->varstr); bb_unsetenv(cur->varstr);
if (name_len == 3 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S') if (name_len == 3 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
@ -2303,7 +2303,7 @@ static int unset_local_var_len(const char *name, int name_len)
free(cur); free(cur);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
var_pp = &cur->next; cur_pp = &cur->next;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
@ -2402,8 +2402,8 @@ 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++;
next: ;
} }
return old; return old;
} }

View File

@ -0,0 +1,4 @@
hush: v=2: readonly variable
hush: v=3: readonly variable
1
Ok:1

View File

@ -0,0 +1,4 @@
readonly v=1
# there was a bug causing second assignment to be not checked
v=2 v=3 echo $v
echo Ok:$v