0010-bash50-010.patch 6.4 KB

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