]>
Commit | Line | Data |
---|---|---|
415fb8b5 PM |
1 | BASH PATCH REPORT |
2 | ================= | |
3 | ||
4 | Bash-Release: 5.0 | |
5 | Patch-ID: bash50-010 | |
6 | ||
7 | Bug-Reported-by: Thorsten Glaser <tg@mirbsd.de> | |
8 | Bug-Reference-ID: <156622962831.19438.16374961114836556294.reportbug@tglase.lan.tarent.de> | |
9 | Bug-Reference-URL: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=935115 | |
10 | ||
11 | Bug-Description: | |
12 | ||
13 | Bash-5.0 changed the way assignment statements preceding special builtins | |
14 | and shell functions were handled in posix mode. They automatically created | |
15 | or modified global variables instead of modifying existing local variables | |
16 | as in bash-4.4. | |
17 | ||
18 | The bash-4.4 posix-mode semantics were buggy, and resulted in creating | |
19 | local variables where they were not intended and modifying global variables | |
20 | and local variables simultaneously. | |
21 | ||
22 | The bash-5.0 changes were intended to fix this issue, but did not preserve | |
23 | enough backwards compatibility. The posix standard also changed what it | |
24 | required in these cases, so bash-5.0 is not bound by the strict conformance | |
25 | requirements that existed in previous issues of the standard. | |
26 | ||
27 | This patch modifies the bash-5.0 posix mode behavior in an effort to restore | |
28 | some backwards compatibility and rationalize the behavior in the presence of | |
29 | local variables. It | |
30 | ||
31 | 1. Changes the assignment semantics to be more similar to standalone assignment | |
32 | statements: assignments preceding a function call or special builtin while | |
33 | executing in a shell function will modify the value of a local variable | |
34 | with the same name for the duration of the function's execution; | |
35 | ||
36 | 2. Changes assignments preceding shell function calls or special builtins | |
37 | from within a shell function to no longer create or modify global variables | |
38 | in the presence of a local variable with the same name; | |
39 | ||
40 | 3. Assignment statements preceding a shell function call or special builtin | |
41 | at the global scope continue to modify the (global) calling environment, | |
42 | but are unaffected by assignments preceding function calls or special | |
43 | builtins within a function, as described in item 2. This is also similar | |
44 | to the behavior of a standalone assignment statement. | |
45 | ||
46 | Patch (apply with `patch -p0'): | |
47 | ||
48 | *** ../bash-5.0-patched/variables.c 2018-12-18 11:07:21.000000000 -0500 | |
49 | --- variables.c 2019-08-22 10:53:44.000000000 -0400 | |
50 | *************** | |
51 | *** 4461,4467 **** | |
52 | ||
53 | /* Take a variable from an assignment statement preceding a posix special | |
54 | ! builtin (including `return') and create a global variable from it. This | |
55 | ! is called from merge_temporary_env, which is only called when in posix | |
56 | ! mode. */ | |
57 | static void | |
58 | push_posix_temp_var (data) | |
59 | --- 4461,4467 ---- | |
60 | ||
61 | /* Take a variable from an assignment statement preceding a posix special | |
62 | ! builtin (including `return') and create a variable from it as if a | |
63 | ! standalone assignment statement had been performed. This is called from | |
64 | ! merge_temporary_env, which is only called when in posix mode. */ | |
65 | static void | |
66 | push_posix_temp_var (data) | |
67 | *************** | |
68 | *** 4473,4486 **** | |
69 | var = (SHELL_VAR *)data; | |
70 | ||
71 | ! binding_table = global_variables->table; | |
72 | ! if (binding_table == 0) | |
73 | ! binding_table = global_variables->table = hash_create (VARIABLES_HASH_BUCKETS); | |
74 | ! | |
75 | ! v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, ASS_FORCE|ASS_NOLONGJMP); | |
76 | ||
77 | /* global variables are no longer temporary and don't need propagating. */ | |
78 | ! var->attributes &= ~(att_tempvar|att_propagate); | |
79 | if (v) | |
80 | ! v->attributes |= var->attributes; | |
81 | ||
82 | if (find_special_var (var->name) >= 0) | |
83 | --- 4473,4497 ---- | |
84 | var = (SHELL_VAR *)data; | |
85 | ||
86 | ! /* Just like do_assignment_internal(). This makes assignments preceding | |
87 | ! special builtins act like standalone assignment statements when in | |
88 | ! posix mode, satisfying the posix requirement that this affect the | |
89 | ! "current execution environment." */ | |
90 | ! v = bind_variable (var->name, value_cell (var), ASS_FORCE|ASS_NOLONGJMP); | |
91 | ! | |
92 | ! /* If this modifies an existing local variable, v->context will be non-zero. | |
93 | ! If it comes back with v->context == 0, we bound at the global context. | |
94 | ! Set binding_table appropriately. It doesn't matter whether it's correct | |
95 | ! if the variable is local, only that it's not global_variables->table */ | |
96 | ! binding_table = v->context ? shell_variables->table : global_variables->table; | |
97 | ||
98 | /* global variables are no longer temporary and don't need propagating. */ | |
99 | ! if (binding_table == global_variables->table) | |
100 | ! var->attributes &= ~(att_tempvar|att_propagate); | |
101 | ! | |
102 | if (v) | |
103 | ! { | |
104 | ! v->attributes |= var->attributes; | |
105 | ! v->attributes &= ~att_tempvar; /* not a temp var now */ | |
106 | ! } | |
107 | ||
108 | if (find_special_var (var->name) >= 0) | |
109 | *************** | |
110 | *** 4576,4587 **** | |
111 | { | |
112 | int i; | |
113 | ||
114 | tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1); | |
115 | tempvar_list[tvlist_ind = 0] = 0; | |
116 | ! | |
117 | ! hash_flush (temporary_env, pushf); | |
118 | ! hash_dispose (temporary_env); | |
119 | temporary_env = (HASH_TABLE *)NULL; | |
120 | ||
121 | tempvar_list[tvlist_ind] = 0; | |
122 | ||
123 | --- 4587,4601 ---- | |
124 | { | |
125 | int i; | |
126 | + HASH_TABLE *disposer; | |
127 | ||
128 | tempvar_list = strvec_create (HASH_ENTRIES (temporary_env) + 1); | |
129 | tempvar_list[tvlist_ind = 0] = 0; | |
130 | ! | |
131 | ! disposer = temporary_env; | |
132 | temporary_env = (HASH_TABLE *)NULL; | |
133 | ||
134 | + hash_flush (disposer, pushf); | |
135 | + hash_dispose (disposer); | |
136 | + | |
137 | tempvar_list[tvlist_ind] = 0; | |
138 | ||
139 | *** ../bash-5.0-patched/tests/varenv.right 2018-12-17 15:39:48.000000000 -0500 | |
140 | --- tests/varenv.right 2019-08-22 16:05:25.000000000 -0400 | |
141 | *************** | |
142 | *** 147,153 **** | |
143 | outside: declare -- var="one" | |
144 | inside: declare -x var="value" | |
145 | ! outside: declare -x var="value" | |
146 | ! inside: declare -- var="local" | |
147 | ! outside: declare -x var="global" | |
148 | foo=<unset> environment foo= | |
149 | foo=foo environment foo=foo | |
150 | --- 147,153 ---- | |
151 | outside: declare -- var="one" | |
152 | inside: declare -x var="value" | |
153 | ! outside: declare -- var="outside" | |
154 | ! inside: declare -x var="global" | |
155 | ! outside: declare -- var="outside" | |
156 | foo=<unset> environment foo= | |
157 | foo=foo environment foo=foo | |
158 | *** ../bash-5.0/patchlevel.h 2016-06-22 14:51:03.000000000 -0400 | |
159 | --- patchlevel.h 2016-10-01 11:01:28.000000000 -0400 | |
160 | *************** | |
161 | *** 26,30 **** | |
162 | looks for to find the patch level (for the sccs version string). */ | |
163 | ||
164 | ! #define PATCHLEVEL 9 | |
165 | ||
166 | #endif /* _PATCHLEVEL_H_ */ | |
167 | --- 26,30 ---- | |
168 | looks for to find the patch level (for the sccs version string). */ | |
169 | ||
170 | ! #define PATCHLEVEL 10 | |
171 | ||
172 | #endif /* _PATCHLEVEL_H_ */ |