diff --git a/assignment-preceding-builtin.patch b/assignment-preceding-builtin.patch new file mode 100644 index 00000000..72ac06d9 --- /dev/null +++ b/assignment-preceding-builtin.patch @@ -0,0 +1,137 @@ +From: Chet Ramey +Subject: Re: [bug-bash] bash-5.0: problem with variable scoping in posix-mode + +> > Description: +> > +> > There is a problem with variable scoping when variable is created from +> > assignment statement preceding function call in posix-mode. See an +> > example below. +> > +> > +> > Repeat-By: +> > +> > $ cat test.sh +> > #!/bin/sh +> > +> > myecho() { +> > echo $var +> > } +> > +> > foo() { +> > local var="foo: FAIL" +> > var="foo: bar" myecho +> > } +> > +> > foo +> > +> > $ bash test.sh +> > foo: bar +> > $ bash --posix test.sh +> > foo: FAIL +> +> This is a consequence of a combination of two POSIX features. First, POSIX +> requires assignment statements preceding special builtins to create global +> variables (POSIX has no local variables) that persist in the shell context +> after the special builtin completes. Second, POSIX requires* that +> assignment statements preceding function calls have the same variable- +> assignment behavior as special builtins. +> +> So the variable assignment preceding the function call creates a global +> variable, and the local variable is found before that global when `myecho' +> is executed according to the standard bash dynamic scoping rules. If you +> add an `echo $var' after the call to foo, you'll see this behavior. +> +> (*) The most recent version of the standard has removed this requirement +> for shell functions, and I will change that behavior for the next release +> of bash. Until then, the old behavior persists. + +This behavior is not quite backwards-compatible with bash-4.4. Here is a +patch that implements a portion of the proposed bash-5.1 behavior. It +changes the variable assignment semantics so that variable assignments +preceding builtins and shell functions act more like standalone assignment +statements and modify the "current execution environment" (in POSIX terms) +instead of unconditionally modifying the global variable scope. + +This means that assignments preceding shell functions and special builtins +will modify existing local variables and modifications to local variables +will not propagate to the calling environment, and will create global +variables if there is not an existing local variable with that name. This +is compatible with other POSIX shells that implement local variables. + +It is not completely compatible with bash-4.4, since the bash-4.4 behavior +wasn't fully POSIX-conformant and had variable scoping bugs as well. + +The original discussion concerning this is at + +http://lists.gnu.org/archive/html/bug-bash/2018-05/msg00002.html + +Chet + +--- + variables.c | 35 ++++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +--- variables.c ++++ variables.c 2019-03-21 08:21:21.777597991 +0000 +@@ -4507,16 +4507,38 @@ push_posix_temp_var (data) + + var = (SHELL_VAR *)data; + ++#if 1 /* TAG:bash-5.1 */ ++ /* 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; ++#else + 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); ++#endif + + /* global variables are no longer temporary and don't need propagating. */ +- var->attributes &= ~(att_tempvar|att_propagate); ++ if (binding_table == global_variables->table) ++ var->attributes &= ~(att_tempvar|att_propagate); ++ + if (v) +- v->attributes |= var->attributes; ++ { ++ v->attributes |= var->attributes; ++ v->attributes &= ~att_tempvar; /* not a temp var now */ ++#if 0 /* TAG:bash-5.1 code doesn't need this, disable for bash-5.1 */ ++ v->context = (binding_table == global_variables->table) ? 0 : shell_variables->scope; ++#endif ++ } + + if (find_special_var (var->name) >= 0) + tempvar_list[tvlist_ind++] = savestring (var->name); +@@ -4610,14 +4632,17 @@ dispose_temporary_env (pushf) + sh_free_func_t *pushf; + { + int i; ++ HASH_TABLE *disposer; + + tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1); + tempvar_list[tvlist_ind = 0] = 0; +- +- hash_flush (temporary_env, pushf); +- hash_dispose (temporary_env); ++ ++ disposer = temporary_env; + temporary_env = (HASH_TABLE *)NULL; + ++ hash_flush (disposer, pushf); ++ hash_dispose (disposer); ++ + tempvar_list[tvlist_ind] = 0; + + array_needs_making = 1; diff --git a/bash-5.0-patches.tar.bz2 b/bash-5.0-patches.tar.bz2 index e9c58eec..4768086a 100644 --- a/bash-5.0-patches.tar.bz2 +++ b/bash-5.0-patches.tar.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33cf9f650dd932d8a2fdf23073741d7e2b2816b6d396fa7190fcfefa5d034315 -size 4261 +oid sha256:6baeefb72f30dbf93b0ba72d1fa7898c09c6082087684563e656524844a69435 +size 4752 diff --git a/bash.changes b/bash.changes index 6e0ce813..1cbc95a8 100644 --- a/bash.changes +++ b/bash.changes @@ -1,3 +1,20 @@ +------------------------------------------------------------------- +Thu Apr 4 07:18:57 UTC 2019 - Dr. Werner Fink + +- Add temporary fix from upstream for boo#1128936 + +------------------------------------------------------------------- +Thu Mar 21 08:24:11 UTC 2019 - Dr. Werner Fink + +- Add patch assignment-preceding-builtin.patch from upstream + mailing list. Note that this break backward behaviour with + bash-4.4 but implies that POSIX mode is more correct + +------------------------------------------------------------------- +Thu Mar 21 07:57:41 UTC 2019 - Dr. Werner Fink + +- Replace the temporary patch with official bash50-003 + ------------------------------------------------------------------- Mon Mar 11 07:20:37 UTC 2019 - Dr. Werner Fink diff --git a/bash.spec b/bash.spec index 4fa94d44..1136ebcf 100644 --- a/bash.spec +++ b/bash.spec @@ -72,6 +72,8 @@ Patch47: bash-4.3-perl522.patch Patch48: bash-4.3-extra-import-func.patch # PATCH-EXTEND-SUSE Allow root to clean file system if filled up Patch49: bash-4.3-pathtemp.patch +# PATCH-EXTEND-UPSTREAM bash-5.0: problem with variable scoping in posix-mode +Patch100: assignment-preceding-builtin.patch BuildRequires: audit-devel BuildRequires: autoconf BuildRequires: bison @@ -235,6 +237,7 @@ done %patch48 -b .eif %endif %patch49 -p0 -b .pthtmp +%patch100 -p0 -b .posix %patch0 -p0 -b .0 # This has to be always the same version as included in the bash its self