aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-04-04 21:14:28 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-04-04 21:14:28 +0200
commit61407807ab6b9505041a74ad96ffb4aeab937d36 (patch)
treeeda659ec46e2d275d91ac9784dbd2095fb96da57
parent759ca8a4cb57f797e92e02db84673057ce447125 (diff)
downloadbusybox-w32-61407807ab6b9505041a74ad96ffb4aeab937d36.tar.gz
busybox-w32-61407807ab6b9505041a74ad96ffb4aeab937d36.tar.bz2
busybox-w32-61407807ab6b9505041a74ad96ffb4aeab937d36.zip
hush: fix for readonly vars in "ro=A ro=B cmd" case
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c26
-rw-r--r--shell/hush_test/hush-vars/readonly3.right4
-rwxr-xr-xshell/hush_test/hush-vars/readonly3.tests4
3 files changed, 21 insertions, 13 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 335107283..641531209 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2134,7 +2134,7 @@ static const char* FAST_FUNC get_local_var_value(const char *name)
2134#define SETFLAG_LOCAL_SHIFT 3 2134#define SETFLAG_LOCAL_SHIFT 3
2135static int set_local_var(char *str, unsigned flags) 2135static int set_local_var(char *str, unsigned flags)
2136{ 2136{
2137 struct variable **var_pp; 2137 struct variable **cur_pp;
2138 struct variable *cur; 2138 struct variable *cur;
2139 char *free_me = NULL; 2139 char *free_me = NULL;
2140 char *eq_sign; 2140 char *eq_sign;
@@ -2155,10 +2155,10 @@ static int set_local_var(char *str, unsigned flags)
2155 } 2155 }
2156#endif 2156#endif
2157 2157
2158 var_pp = &G.top_var; 2158 cur_pp = &G.top_var;
2159 while ((cur = *var_pp) != NULL) { 2159 while ((cur = *cur_pp) != NULL) {
2160 if (strncmp(cur->varstr, str, name_len) != 0) { 2160 if (strncmp(cur->varstr, str, name_len) != 0) {
2161 var_pp = &cur->next; 2161 cur_pp = &cur->next;
2162 continue; 2162 continue;
2163 } 2163 }
2164 2164
@@ -2182,7 +2182,7 @@ static int set_local_var(char *str, unsigned flags)
2182 * and existing one is global, or local 2182 * and existing one is global, or local
2183 * from enclosing function. 2183 * from enclosing function.
2184 * Remove and save old one: */ 2184 * Remove and save old one: */
2185 *var_pp = cur->next; 2185 *cur_pp = cur->next;
2186 cur->next = *G.shadowed_vars_pp; 2186 cur->next = *G.shadowed_vars_pp;
2187 *G.shadowed_vars_pp = cur; 2187 *G.shadowed_vars_pp = cur;
2188 /* bash 3.2.33(1) and exported vars: 2188 /* bash 3.2.33(1) and exported vars:
@@ -2226,8 +2226,8 @@ static int set_local_var(char *str, unsigned flags)
2226 /* Not found - create new variable struct */ 2226 /* Not found - create new variable struct */
2227 cur = xzalloc(sizeof(*cur)); 2227 cur = xzalloc(sizeof(*cur));
2228 IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;) 2228 IF_HUSH_LOCAL(cur->func_nest_level = local_lvl;)
2229 cur->next = *var_pp; 2229 cur->next = *cur_pp;
2230 *var_pp = cur; 2230 *cur_pp = cur;
2231 2231
2232 set_str_and_exp: 2232 set_str_and_exp:
2233 cur->varstr = str; 2233 cur->varstr = str;
@@ -2272,7 +2272,7 @@ static void set_pwd_var(unsigned flag)
2272static int unset_local_var_len(const char *name, int name_len) 2272static int unset_local_var_len(const char *name, int name_len)
2273{ 2273{
2274 struct variable *cur; 2274 struct variable *cur;
2275 struct variable **var_pp; 2275 struct variable **cur_pp;
2276 2276
2277 if (!name) 2277 if (!name)
2278 return EXIT_SUCCESS; 2278 return EXIT_SUCCESS;
@@ -2286,14 +2286,14 @@ static int unset_local_var_len(const char *name, int name_len)
2286 G.lineno_var = NULL; 2286 G.lineno_var = NULL;
2287#endif 2287#endif
2288 2288
2289 var_pp = &G.top_var; 2289 cur_pp = &G.top_var;
2290 while ((cur = *var_pp) != NULL) { 2290 while ((cur = *cur_pp) != NULL) {
2291 if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') { 2291 if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
2292 if (cur->flg_read_only) { 2292 if (cur->flg_read_only) {
2293 bb_error_msg("%s: readonly variable", name); 2293 bb_error_msg("%s: readonly variable", name);
2294 return EXIT_FAILURE; 2294 return EXIT_FAILURE;
2295 } 2295 }
2296 *var_pp = cur->next; 2296 *cur_pp = cur->next;
2297 debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr); 2297 debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
2298 bb_unsetenv(cur->varstr); 2298 bb_unsetenv(cur->varstr);
2299 if (name_len == 3 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S') 2299 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)
2303 free(cur); 2303 free(cur);
2304 return EXIT_SUCCESS; 2304 return EXIT_SUCCESS;
2305 } 2305 }
2306 var_pp = &cur->next; 2306 cur_pp = &cur->next;
2307 } 2307 }
2308 return EXIT_SUCCESS; 2308 return EXIT_SUCCESS;
2309} 2309}
@@ -2402,8 +2402,8 @@ static struct variable *set_vars_and_save_old(char **strings)
2402 } 2402 }
2403 set_local_var(*s, SETFLAG_EXPORT); 2403 set_local_var(*s, SETFLAG_EXPORT);
2404 } 2404 }
2405 next:
2406 s++; 2405 s++;
2406 next: ;
2407 } 2407 }
2408 return old; 2408 return old;
2409} 2409}
diff --git a/shell/hush_test/hush-vars/readonly3.right b/shell/hush_test/hush-vars/readonly3.right
new file mode 100644
index 000000000..acd931243
--- /dev/null
+++ b/shell/hush_test/hush-vars/readonly3.right
@@ -0,0 +1,4 @@
1hush: v=2: readonly variable
2hush: v=3: readonly variable
31
4Ok:1
diff --git a/shell/hush_test/hush-vars/readonly3.tests b/shell/hush_test/hush-vars/readonly3.tests
new file mode 100755
index 000000000..17780cfda
--- /dev/null
+++ b/shell/hush_test/hush-vars/readonly3.tests
@@ -0,0 +1,4 @@
1readonly v=1
2# there was a bug causing second assignment to be not checked
3v=2 v=3 echo $v
4echo Ok:$v