2
1

bash32-014 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. BASH PATCH REPORT
  2. =================
  3. Bash-Release: 3.2
  4. Patch-ID: bash32-014
  5. Bug-Reported-by: Brett Stahlman <brettstahlman@comcast.net>
  6. Bug-Reference-ID: <000701c72d29$a227e0e0$5ec7cf47@computerroom>
  7. Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2006-12/msg00065.html
  8. Bug-Description:
  9. Bash mishandles word splitting under certain circumstances when IFS is
  10. null (IFS=). Constructs affected include ${param/pat/sub} and others
  11. when expanding arrays (array[@]).
  12. Patch:
  13. *** ../bash-3.2-patched/array.c Wed Jun 1 16:39:22 2005
  14. --- bash-3.2/array.c Mon Jan 15 22:58:00 2007
  15. ***************
  16. *** 121,125 ****
  17. }
  18. - #ifdef INCLUDE_UNUSED
  19. /*
  20. * Make and return a new array composed of the elements in array A from
  21. --- 121,124 ----
  22. ***************
  23. *** 142,146 ****
  24. n = array_create_element (element_index(p), element_value(p));
  25. ADD_BEFORE(a->head, n);
  26. ! mi = element_index(ae);
  27. }
  28. a->num_elements = i;
  29. --- 141,145 ----
  30. n = array_create_element (element_index(p), element_value(p));
  31. ADD_BEFORE(a->head, n);
  32. ! mi = element_index(n);
  33. }
  34. a->num_elements = i;
  35. ***************
  36. *** 148,152 ****
  37. return a;
  38. }
  39. - #endif
  40. /*
  41. --- 147,150 ----
  42. ***************
  43. *** 301,304 ****
  44. --- 299,319 ----
  45. }
  46. + ARRAY *
  47. + array_quote_escapes(array)
  48. + ARRAY *array;
  49. + {
  50. + ARRAY_ELEMENT *a;
  51. + char *t;
  52. +
  53. + if (array == 0 || array_head(array) == 0 || array_empty(array))
  54. + return (ARRAY *)NULL;
  55. + for (a = element_forw(array->head); a != array->head; a = element_forw(a)) {
  56. + t = quote_escapes (a->value);
  57. + FREE(a->value);
  58. + a->value = t;
  59. + }
  60. + return array;
  61. + }
  62. +
  63. /*
  64. * Return a string whose elements are the members of array A beginning at
  65. ***************
  66. *** 312,318 ****
  67. int starsub, quoted;
  68. {
  69. ARRAY_ELEMENT *h, *p;
  70. arrayind_t i;
  71. ! char *ifs, sep[2];
  72. p = a ? array_head (a) : 0;
  73. --- 327,334 ----
  74. int starsub, quoted;
  75. {
  76. + ARRAY *a2;
  77. ARRAY_ELEMENT *h, *p;
  78. arrayind_t i;
  79. ! char *ifs, sep[2], *t;
  80. p = a ? array_head (a) : 0;
  81. ***************
  82. *** 337,340 ****
  83. --- 353,363 ----
  84. ;
  85. + a2 = array_slice(a, h, p);
  86. +
  87. + if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
  88. + array_quote(a2);
  89. + else
  90. + array_quote_escapes(a2);
  91. +
  92. if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) {
  93. ifs = getifs();
  94. ***************
  95. *** 344,348 ****
  96. sep[1] = '\0';
  97. ! return (array_to_string_internal (h, p, sep, quoted));
  98. }
  99. --- 367,374 ----
  100. sep[1] = '\0';
  101. ! t = array_to_string (a2, sep, 0);
  102. ! array_dispose(a2);
  103. !
  104. ! return t;
  105. }
  106. ***************
  107. *** 368,372 ****
  108. if (mflags & MATCH_QUOTED)
  109. ! array_quote (a2);
  110. if (mflags & MATCH_STARSUB) {
  111. ifs = getifs();
  112. --- 394,400 ----
  113. if (mflags & MATCH_QUOTED)
  114. ! array_quote(a2);
  115. ! else
  116. ! array_quote_escapes(a2);
  117. if (mflags & MATCH_STARSUB) {
  118. ifs = getifs();
  119. *** ../bash-3.2-patched/array.h Sun Jun 1 15:50:30 2003
  120. --- bash-3.2/array.h Mon Jan 15 22:35:35 2007
  121. ***************
  122. *** 56,59 ****
  123. --- 56,60 ----
  124. extern int array_shift_element __P((ARRAY *, char *));
  125. extern ARRAY *array_quote __P((ARRAY *));
  126. + extern ARRAY *array_quote_escapes __P((ARRAY *));
  127. extern char *array_subrange __P((ARRAY *, arrayind_t, arrayind_t, int, int));
  128. *** ../bash-3.2-patched/subst.c Fri Mar 2 16:20:50 2007
  129. --- bash-3.2/subst.c Tue Mar 6 11:40:55 2007
  130. ***************
  131. *** 1888,1892 ****
  132. --- 1889,1899 ----
  133. #endif
  134. + /* XXX -- why call quote_list if ifs == 0? we can get away without doing
  135. + it now that quote_escapes quotes spaces */
  136. + #if 0
  137. tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
  138. + #else
  139. + tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
  140. + #endif
  141. ? quote_list (list)
  142. : list_quote_escapes (list);
  143. ***************
  144. *** 2922,2926 ****
  145. /* Quote escape characters in string s, but no other characters. This is
  146. used to protect CTLESC and CTLNUL in variable values from the rest of
  147. ! the word expansion process after the variable is expanded. */
  148. char *
  149. quote_escapes (string)
  150. --- 2935,2944 ----
  151. /* Quote escape characters in string s, but no other characters. This is
  152. used to protect CTLESC and CTLNUL in variable values from the rest of
  153. ! the word expansion process after the variable is expanded. If IFS is
  154. ! null, we quote spaces as well, just in case we split on spaces later
  155. ! (in the case of unquoted $@, we will eventually attempt to split the
  156. ! entire word on spaces). Corresponding code exists in dequote_escapes.
  157. ! Even if we don't end up splitting on spaces, quoting spaces is not a
  158. ! problem. */
  159. char *
  160. quote_escapes (string)
  161. ***************
  162. *** 2930,2933 ****
  163. --- 2948,2952 ----
  164. size_t slen;
  165. char *result, *send;
  166. + int quote_spaces;
  167. DECLARE_MBSTATE;
  168. ***************
  169. *** 2935,2938 ****
  170. --- 2954,2958 ----
  171. send = string + slen;
  172. + quote_spaces = (ifs_value && *ifs_value == 0);
  173. t = result = (char *)xmalloc ((slen * 2) + 1);
  174. s = string;
  175. ***************
  176. *** 2940,2944 ****
  177. while (*s)
  178. {
  179. ! if (*s == CTLESC || *s == CTLNUL)
  180. *t++ = CTLESC;
  181. COPY_CHAR_P (t, s, send);
  182. --- 2960,2964 ----
  183. while (*s)
  184. {
  185. ! if (*s == CTLESC || *s == CTLNUL || (quote_spaces && *s == ' '))
  186. *t++ = CTLESC;
  187. COPY_CHAR_P (t, s, send);
  188. ***************
  189. *** 2982,2985 ****
  190. --- 3002,3006 ----
  191. size_t slen;
  192. char *result, *send;
  193. + int quote_spaces;
  194. DECLARE_MBSTATE;
  195. ***************
  196. *** 2996,3002 ****
  197. return (strcpy (result, s));
  198. while (*s)
  199. {
  200. ! if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
  201. {
  202. s++;
  203. --- 3017,3024 ----
  204. return (strcpy (result, s));
  205. + quote_spaces = (ifs_value && *ifs_value == 0);
  206. while (*s)
  207. {
  208. ! if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
  209. {
  210. s++;
  211. ***************
  212. *** 4462,4466 ****
  213. RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
  214. ! if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
  215. istring[istring_index++] = CTLESC;
  216. --- 4498,4510 ----
  217. RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
  218. ! /* This is essentially quote_string inline */
  219. ! if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
  220. ! istring[istring_index++] = CTLESC;
  221. ! /* Escape CTLESC and CTLNUL in the output to protect those characters
  222. ! from the rest of the word expansions (word splitting and globbing.)
  223. ! This is essentially quote_escapes inline. */
  224. ! else if (c == CTLESC)
  225. ! istring[istring_index++] = CTLESC;
  226. ! else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
  227. istring[istring_index++] = CTLESC;
  228. ***************
  229. *** 5552,5555 ****
  230. --- 5610,5616 ----
  231. rely on array_subrange to understand how to deal with them). */
  232. tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
  233. + #if 0
  234. + /* array_subrange now calls array_quote_escapes as appropriate, so the
  235. + caller no longer needs to. */
  236. if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
  237. {
  238. ***************
  239. *** 5558,5561 ****
  240. --- 5619,5623 ----
  241. }
  242. else
  243. + #endif
  244. temp = tt;
  245. break;
  246. ***************
  247. *** 5808,5811 ****
  248. --- 5870,5876 ----
  249. case VT_ARRAYVAR:
  250. temp = array_patsub (array_cell (v), p, rep, mflags);
  251. + #if 0
  252. + /* Don't need to do this anymore; array_patsub calls array_quote_escapes
  253. + as appropriate before adding the space separators. */
  254. if (temp && (mflags & MATCH_QUOTED) == 0)
  255. {
  256. ***************
  257. *** 5814,5817 ****
  258. --- 5879,5883 ----
  259. temp = tt;
  260. }
  261. + #endif
  262. break;
  263. #endif
  264. *** ../bash-3.2/patchlevel.h Thu Apr 13 08:31:04 2006
  265. --- bash-3.2/patchlevel.h Mon Oct 16 14:22:54 2006
  266. ***************
  267. *** 26,30 ****
  268. looks for to find the patch level (for the sccs version string). */
  269. ! #define PATCHLEVEL 13
  270. #endif /* _PATCHLEVEL_H_ */
  271. --- 26,30 ----
  272. looks for to find the patch level (for the sccs version string). */
  273. ! #define PATCHLEVEL 14
  274. #endif /* _PATCHLEVEL_H_ */