]>
Commit | Line | Data |
---|---|---|
39cb2ba7 AM |
1 | BASH PATCH REPORT |
2 | ================= | |
3 | ||
4 | Bash-Release: 4.0 | |
5 | Patch-ID: bash40-007 | |
6 | ||
7 | Bug-Reported-by: AnMaster <anmaster@tele2.se> | |
8 | Bug-Reference-ID: <49A41C18.80807@tele2.se> | |
9 | Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2009-02/msg00188.html | |
10 | ||
11 | Bug-Description: | |
12 | ||
13 | Bash had a number of problems parsing associative array subscripts containing | |
14 | special characters. The subscripts are supposed to be read as if they are | |
15 | enclosed between double quotes. | |
16 | ||
17 | Patch: | |
18 | ||
19 | *** ../bash-4.0/parse.y 2009-01-08 08:29:12.000000000 -0500 | |
20 | --- parse.y 2009-02-25 17:25:56.000000000 -0500 | |
21 | *************** | |
22 | *** 2919,2922 **** | |
23 | --- 2919,2923 ---- | |
24 | #define P_COMMAND 0x08 /* parsing a command, so look for comments */ | |
25 | #define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */ | |
26 | + #define P_ARRAYSUB 0x20 /* parsing a [...] array subscript for assignment */ | |
27 | ||
28 | /* Lexical state while parsing a grouping construct or $(...). */ | |
29 | *************** | |
30 | *** 3134,3137 **** | |
31 | --- 3134,3139 ---- | |
32 | FREE (nestret); | |
33 | } | |
34 | + else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */ | |
35 | + goto parse_dollar_word; | |
36 | } | |
37 | /* Parse an old-style command substitution within double quotes as a | |
38 | *************** | |
39 | *** 3150,3153 **** | |
40 | --- 3150,3154 ---- | |
41 | /* check for $(), $[], or ${} inside quoted string. */ | |
42 | { | |
43 | + parse_dollar_word: | |
44 | if (open == ch) /* undo previous increment */ | |
45 | count--; | |
46 | *************** | |
47 | *** 4277,4281 **** | |
48 | (token_index == 0 && (parser_state&PST_COMPASSIGN)))) | |
49 | { | |
50 | ! ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0); | |
51 | if (ttok == &matched_pair_error) | |
52 | return -1; /* Bail immediately. */ | |
53 | --- 4277,4281 ---- | |
54 | (token_index == 0 && (parser_state&PST_COMPASSIGN)))) | |
55 | { | |
56 | ! ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB); | |
57 | if (ttok == &matched_pair_error) | |
58 | return -1; /* Bail immediately. */ | |
59 | *** ../bash-4.0/arrayfunc.c 2009-01-04 14:32:21.000000000 -0500 | |
60 | --- arrayfunc.c 2009-02-25 07:58:54.000000000 -0500 | |
61 | *************** | |
62 | *** 605,666 **** | |
63 | } | |
64 | ||
65 | ! /* This function assumes s[i] == '['; returns with s[ret] == ']' if | |
66 | ! an array subscript is correctly parsed. */ | |
67 | ! int | |
68 | ! skipsubscript (s, i) | |
69 | ! const char *s; | |
70 | ! int i; | |
71 | ! { | |
72 | ! int count, c; | |
73 | ! #if defined (HANDLE_MULTIBYTE) | |
74 | ! mbstate_t state, state_bak; | |
75 | ! size_t slength, mblength; | |
76 | ! #endif | |
77 | ! | |
78 | ! #if defined (HANDLE_MULTIBYTE) | |
79 | ! memset (&state, '\0', sizeof (mbstate_t)); | |
80 | ! slength = strlen (s + i); | |
81 | ! #endif | |
82 | ! | |
83 | ! count = 1; | |
84 | ! while (count) | |
85 | ! { | |
86 | ! /* Advance one (possibly multibyte) character in S starting at I. */ | |
87 | ! #if defined (HANDLE_MULTIBYTE) | |
88 | ! if (MB_CUR_MAX > 1) | |
89 | ! { | |
90 | ! state_bak = state; | |
91 | ! mblength = mbrlen (s + i, slength, &state); | |
92 | ! | |
93 | ! if (MB_INVALIDCH (mblength)) | |
94 | ! { | |
95 | ! state = state_bak; | |
96 | ! i++; | |
97 | ! slength--; | |
98 | ! } | |
99 | ! else if (MB_NULLWCH (mblength)) | |
100 | ! return i; | |
101 | ! else | |
102 | ! { | |
103 | ! i += mblength; | |
104 | ! slength -= mblength; | |
105 | ! } | |
106 | ! } | |
107 | ! else | |
108 | ! #endif | |
109 | ! ++i; | |
110 | ! | |
111 | ! c = s[i]; | |
112 | ! | |
113 | ! if (c == 0) | |
114 | ! break; | |
115 | ! else if (c == '[') | |
116 | ! count++; | |
117 | ! else if (c == ']') | |
118 | ! count--; | |
119 | ! } | |
120 | ! | |
121 | ! return i; | |
122 | ! } | |
123 | ||
124 | /* This function is called with SUB pointing to just after the beginning | |
125 | --- 605,609 ---- | |
126 | } | |
127 | ||
128 | ! /* skipsubscript moved to subst.c to use private functions. 2009/02/24. */ | |
129 | ||
130 | /* This function is called with SUB pointing to just after the beginning | |
131 | *** ../bash-4.0/subst.c 2009-01-28 14:34:12.000000000 -0500 | |
132 | --- subst.c 2009-02-25 09:18:33.000000000 -0500 | |
133 | *************** | |
134 | *** 223,226 **** | |
135 | --- 223,227 ---- | |
136 | static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int)); | |
137 | static char *extract_dollar_brace_string __P((char *, int *, int, int)); | |
138 | + static int skip_matched_pair __P((const char *, int, int, int, int)); | |
139 | ||
140 | static char *pos_params __P((char *, int, int, int)); | |
141 | *************** | |
142 | *** 1375,1378 **** | |
143 | --- 1376,1480 ---- | |
144 | #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0) | |
145 | ||
146 | + /* This function assumes s[i] == open; returns with s[ret] == close; used to | |
147 | + parse array subscripts. FLAGS currently unused. */ | |
148 | + static int | |
149 | + skip_matched_pair (string, start, open, close, flags) | |
150 | + const char *string; | |
151 | + int start, open, close, flags; | |
152 | + { | |
153 | + int i, pass_next, backq, si, c, count; | |
154 | + size_t slen; | |
155 | + char *temp, *ss; | |
156 | + DECLARE_MBSTATE; | |
157 | + | |
158 | + slen = strlen (string + start) + start; | |
159 | + no_longjmp_on_fatal_error = 1; | |
160 | + | |
161 | + i = start + 1; /* skip over leading bracket */ | |
162 | + count = 1; | |
163 | + pass_next = backq = 0; | |
164 | + ss = (char *)string; | |
165 | + while (c = string[i]) | |
166 | + { | |
167 | + if (pass_next) | |
168 | + { | |
169 | + pass_next = 0; | |
170 | + if (c == 0) | |
171 | + CQ_RETURN(i); | |
172 | + ADVANCE_CHAR (string, slen, i); | |
173 | + continue; | |
174 | + } | |
175 | + else if (c == '\\') | |
176 | + { | |
177 | + pass_next = 1; | |
178 | + i++; | |
179 | + continue; | |
180 | + } | |
181 | + else if (backq) | |
182 | + { | |
183 | + if (c == '`') | |
184 | + backq = 0; | |
185 | + ADVANCE_CHAR (string, slen, i); | |
186 | + continue; | |
187 | + } | |
188 | + else if (c == '`') | |
189 | + { | |
190 | + backq = 1; | |
191 | + i++; | |
192 | + continue; | |
193 | + } | |
194 | + else if (c == open) | |
195 | + { | |
196 | + count++; | |
197 | + i++; | |
198 | + continue; | |
199 | + } | |
200 | + else if (c == close) | |
201 | + { | |
202 | + count--; | |
203 | + if (count == 0) | |
204 | + break; | |
205 | + i++; | |
206 | + continue; | |
207 | + } | |
208 | + else if (c == '\'' || c == '"') | |
209 | + { | |
210 | + i = (c == '\'') ? skip_single_quoted (ss, slen, ++i) | |
211 | + : skip_double_quoted (ss, slen, ++i); | |
212 | + /* no increment, the skip functions increment past the closing quote. */ | |
213 | + } | |
214 | + else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE)) | |
215 | + { | |
216 | + si = i + 2; | |
217 | + if (string[si] == '\0') | |
218 | + CQ_RETURN(si); | |
219 | + | |
220 | + if (string[i+1] == LPAREN) | |
221 | + temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */ | |
222 | + else | |
223 | + temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC); | |
224 | + i = si; | |
225 | + if (string[i] == '\0') /* don't increment i past EOS in loop */ | |
226 | + break; | |
227 | + i++; | |
228 | + continue; | |
229 | + } | |
230 | + else | |
231 | + ADVANCE_CHAR (string, slen, i); | |
232 | + } | |
233 | + | |
234 | + CQ_RETURN(i); | |
235 | + } | |
236 | + | |
237 | + #if defined (ARRAY_VARS) | |
238 | + int | |
239 | + skipsubscript (string, start) | |
240 | + const char *string; | |
241 | + int start; | |
242 | + { | |
243 | + return (skip_matched_pair (string, start, '[', ']', 0)); | |
244 | + } | |
245 | + #endif | |
246 | + | |
247 | /* Skip characters in STRING until we find a character in DELIMS, and return | |
248 | the index of that character. START is the index into string at which we | |
249 | *** ../bash-4.0/patchlevel.h 2009-01-04 14:32:40.000000000 -0500 | |
250 | --- patchlevel.h 2009-02-22 16:11:31.000000000 -0500 | |
251 | *************** | |
252 | *** 26,30 **** | |
253 | looks for to find the patch level (for the sccs version string). */ | |
254 | ||
255 | ! #define PATCHLEVEL 6 | |
256 | ||
257 | #endif /* _PATCHLEVEL_H_ */ | |
258 | --- 26,30 ---- | |
259 | looks for to find the patch level (for the sccs version string). */ | |
260 | ||
261 | ! #define PATCHLEVEL 7 | |
262 | ||
263 | #endif /* _PATCHLEVEL_H_ */ |