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