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
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.
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
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 */
28 /* Lexical state while parsing a grouping construct or $(...). */
34 + else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
35 + goto parse_dollar_word;
37 /* Parse an old-style command substitution within double quotes as a
41 /* check for $(), $[], or ${} inside quoted string. */
44 if (open == ch) /* undo previous increment */
48 (token_index == 0 && (parser_state&PST_COMPASSIGN))))
50 ! ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
51 if (ttok == &matched_pair_error)
52 return -1; /* Bail immediately. */
54 (token_index == 0 && (parser_state&PST_COMPASSIGN))))
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
65 ! /* This function assumes s[i] == '['; returns with s[ret] == ']' if
66 ! an array subscript is correctly parsed. */
68 ! skipsubscript (s, i)
73 ! #if defined (HANDLE_MULTIBYTE)
74 ! mbstate_t state, state_bak;
75 ! size_t slength, mblength;
78 ! #if defined (HANDLE_MULTIBYTE)
79 ! memset (&state, '\0', sizeof (mbstate_t));
80 ! slength = strlen (s + i);
86 ! /* Advance one (possibly multibyte) character in S starting at I. */
87 ! #if defined (HANDLE_MULTIBYTE)
91 ! mblength = mbrlen (s + i, slength, &state);
93 ! if (MB_INVALIDCH (mblength))
99 ! else if (MB_NULLWCH (mblength))
104 ! slength -= mblength;
124 /* This function is called with SUB pointing to just after the beginning
128 ! /* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
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
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));
140 static char *pos_params __P((char *, int, int, int));
144 #define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
146 + /* This function assumes s[i] == open; returns with s[ret] == close; used to
147 + parse array subscripts. FLAGS currently unused. */
149 + skip_matched_pair (string, start, open, close, flags)
150 + const char *string;
151 + int start, open, close, flags;
153 + int i, pass_next, backq, si, c, count;
158 + slen = strlen (string + start) + start;
159 + no_longjmp_on_fatal_error = 1;
161 + i = start + 1; /* skip over leading bracket */
163 + pass_next = backq = 0;
164 + ss = (char *)string;
165 + while (c = string[i])
172 + ADVANCE_CHAR (string, slen, i);
175 + else if (c == '\\')
185 + ADVANCE_CHAR (string, slen, i);
194 + else if (c == open)
200 + else if (c == close)
208 + else if (c == '\'' || c == '"')
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. */
214 + else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
217 + if (string[si] == '\0')
220 + if (string[i+1] == LPAREN)
221 + temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
223 + temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
225 + if (string[i] == '\0') /* don't increment i past EOS in loop */
231 + ADVANCE_CHAR (string, slen, i);
237 + #if defined (ARRAY_VARS)
239 + skipsubscript (string, start)
240 + const char *string;
243 + return (skip_matched_pair (string, start, '[', ']', 0));
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
253 looks for to find the patch level (for the sccs version string). */
255 ! #define PATCHLEVEL 6
257 #endif /* _PATCHLEVEL_H_ */
259 looks for to find the patch level (for the sccs version string). */
261 ! #define PATCHLEVEL 7
263 #endif /* _PATCHLEVEL_H_ */