|
|
- BASH PATCH REPORT
- =================
-
- Bash-Release: 5.0
- Patch-ID: bash50-010
-
- Bug-Reported-by: Thorsten Glaser <tg@mirbsd.de>
- Bug-Reference-ID: <156622962831.19438.16374961114836556294.reportbug@tglase.lan.tarent.de>
- Bug-Reference-URL: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=935115
-
- Bug-Description:
-
- Bash-5.0 changed the way assignment statements preceding special builtins
- and shell functions were handled in posix mode. They automatically created
- or modified global variables instead of modifying existing local variables
- as in bash-4.4.
-
- The bash-4.4 posix-mode semantics were buggy, and resulted in creating
- local variables where they were not intended and modifying global variables
- and local variables simultaneously.
-
- The bash-5.0 changes were intended to fix this issue, but did not preserve
- enough backwards compatibility. The posix standard also changed what it
- required in these cases, so bash-5.0 is not bound by the strict conformance
- requirements that existed in previous issues of the standard.
-
- This patch modifies the bash-5.0 posix mode behavior in an effort to restore
- some backwards compatibility and rationalize the behavior in the presence of
- local variables. It
-
- 1. Changes the assignment semantics to be more similar to standalone assignment
- statements: assignments preceding a function call or special builtin while
- executing in a shell function will modify the value of a local variable
- with the same name for the duration of the function's execution;
-
- 2. Changes assignments preceding shell function calls or special builtins
- from within a shell function to no longer create or modify global variables
- in the presence of a local variable with the same name;
-
- 3. Assignment statements preceding a shell function call or special builtin
- at the global scope continue to modify the (global) calling environment,
- but are unaffected by assignments preceding function calls or special
- builtins within a function, as described in item 2. This is also similar
- to the behavior of a standalone assignment statement.
-
- Patch (apply with `patch -p0'):
-
- *** a/variables.c 2018-12-18 11:07:21.000000000 -0500
- --- b/variables.c 2019-08-22 10:53:44.000000000 -0400
- ***************
- *** 4461,4467 ****
-
- /* Take a variable from an assignment statement preceding a posix special
- ! builtin (including `return') and create a global variable from it. This
- ! is called from merge_temporary_env, which is only called when in posix
- ! mode. */
- static void
- push_posix_temp_var (data)
- --- 4461,4467 ----
-
- /* Take a variable from an assignment statement preceding a posix special
- ! builtin (including `return') and create a variable from it as if a
- ! standalone assignment statement had been performed. This is called from
- ! merge_temporary_env, which is only called when in posix mode. */
- static void
- push_posix_temp_var (data)
- ***************
- *** 4473,4486 ****
- var = (SHELL_VAR *)data;
-
- ! binding_table = global_variables->table;
- ! if (binding_table == 0)
- ! binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS);
- !
- ! v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP);
-
- /* global variables are no longer temporary and don't need propagating. */
- ! var->attributes &= ~(att_tempvar|att_propagate);
- if (v)
- ! v->attributes |= var->attributes;
-
- if (find_special_var (var->name) >= 0)
- --- 4473,4497 ----
- var = (SHELL_VAR *)data;
-
- ! /* Just like do_assignment_internal(). This makes assignments preceding
- ! special builtins act like standalone assignment statements when in
- ! posix mode, satisfying the posix requirement that this affect the
- ! "current execution environment." */
- ! v = bind_variable (var->name, value_cell (var), ASS_FORCE|ASS_NOLONGJMP);
- !
- ! /* If this modifies an existing local variable, v->context will be non-zero.
- ! If it comes back with v->context == 0, we bound at the global context.
- ! Set binding_table appropriately. It doesn't matter whether it's correct
- ! if the variable is local, only that it's not global_variables->table */
- ! binding_table = v->context ? shell_variables->table : global_variables->table;
-
- /* global variables are no longer temporary and don't need propagating. */
- ! if (binding_table == global_variables->table)
- ! var->attributes &= ~(att_tempvar|att_propagate);
- !
- if (v)
- ! {
- ! v->attributes |= var->attributes;
- ! v->attributes &= ~att_tempvar; /* not a temp var now */
- ! }
-
- if (find_special_var (var->name) >= 0)
- ***************
- *** 4576,4587 ****
- {
- int i;
-
- tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
- tempvar_list[tvlist_ind = 0] = 0;
- !
- ! hash_flush (temporary_env, pushf);
- ! hash_dispose (temporary_env);
- temporary_env = (HASH_TABLE *)NULL;
-
- tempvar_list[tvlist_ind] = 0;
-
- --- 4587,4601 ----
- {
- int i;
- + HASH_TABLE *disposer;
-
- tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1);
- tempvar_list[tvlist_ind = 0] = 0;
- !
- ! disposer = temporary_env;
- temporary_env = (HASH_TABLE *)NULL;
-
- + hash_flush (disposer, pushf);
- + hash_dispose (disposer);
- +
- tempvar_list[tvlist_ind] = 0;
-
- *** a/tests/varenv.right 2018-12-17 15:39:48.000000000 -0500
- --- b/tests/varenv.right 2019-08-22 16:05:25.000000000 -0400
- ***************
- *** 147,153 ****
- outside: declare -- var="one"
- inside: declare -x var="value"
- ! outside: declare -x var="value"
- ! inside: declare -- var="local"
- ! outside: declare -x var="global"
- foo=<unset> environment foo=
- foo=foo environment foo=foo
- --- 147,153 ----
- outside: declare -- var="one"
- inside: declare -x var="value"
- ! outside: declare -- var="outside"
- ! inside: declare -x var="global"
- ! outside: declare -- var="outside"
- foo=<unset> environment foo=
- foo=foo environment foo=foo
- *** a/patchlevel.h 2016-06-22 14:51:03.000000000 -0400
- --- b/patchlevel.h 2016-10-01 11:01:28.000000000 -0400
- ***************
- *** 26,30 ****
- looks for to find the patch level (for the sccs version string). */
-
- ! #define PATCHLEVEL 9
-
- #endif /* _PATCHLEVEL_H_ */
- --- 26,30 ----
- looks for to find the patch level (for the sccs version string). */
-
- ! #define PATCHLEVEL 10
-
- #endif /* _PATCHLEVEL_H_ */
|