You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							172 lines
						
					
					
						
							6.3 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							172 lines
						
					
					
						
							6.3 KiB
						
					
					
				| 			     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'): | |
| 
 | |
| *** ../bash-5.0-patched/variables.c	2018-12-18 11:07:21.000000000 -0500 | |
| --- 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; | |
|    | |
| *** ../bash-5.0-patched/tests/varenv.right	2018-12-17 15:39:48.000000000 -0500 | |
| --- 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 | |
| *** ../bash-5.0/patchlevel.h	2016-06-22 14:51:03.000000000 -0400 | |
| --- 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_ */
 | |
| 
 |