| BASH PATCH REPORT |
| ================= |
| |
| Bash-Release: 4.2 |
| Patch-ID: bash42-003 |
| |
| Bug-Reported-by: Clark J. Wang <dearvoid@gmail.com> |
| Bug-Reference-ID: <AANLkTikZ_rVV-frR8Fh0PzhXnMKnm5XsUR-F3qtPPs5G@mail.gmail.com> |
| Bug-Reference-URL: http://lists.gnu.org/archive/html/bug-bash/2011-02/msg00136.html |
| |
| Bug-Description: |
| |
| When using the pattern replacement and pattern removal word expansions, bash |
| miscalculates the possible match length in the presence of an unescaped left |
| bracket without a closing right bracket, resulting in a failure to match |
| the pattern. |
| |
| Patch (apply with `patch -p0'): |
| |
| *** ../bash-4.2-patched/lib/glob/gmisc.c 2011-02-05 16:11:17.000000000 -0500 |
| --- ./lib/glob/gmisc.c 2011-02-18 23:53:42.000000000 -0500 |
| *************** |
| *** 78,83 **** |
| size_t wmax; |
| { |
| ! wchar_t wc, *wbrack; |
| ! int matlen, t, in_cclass, in_collsym, in_equiv; |
| |
| if (*wpat == 0) |
| --- 78,83 ---- |
| size_t wmax; |
| { |
| ! wchar_t wc; |
| ! int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; |
| |
| if (*wpat == 0) |
| *************** |
| *** 119,123 **** |
| case L'[': |
| /* scan for ending `]', skipping over embedded [:...:] */ |
| ! wbrack = wpat; |
| wc = *wpat++; |
| do |
| --- 119,123 ---- |
| case L'[': |
| /* scan for ending `]', skipping over embedded [:...:] */ |
| ! bracklen = 1; |
| wc = *wpat++; |
| do |
| *************** |
| *** 125,140 **** |
| if (wc == 0) |
| { |
| ! matlen += wpat - wbrack - 1; /* incremented below */ |
| ! break; |
| } |
| else if (wc == L'\\') |
| { |
| ! wc = *wpat++; |
| ! if (*wpat == 0) |
| ! break; |
| } |
| else if (wc == L'[' && *wpat == L':') /* character class */ |
| { |
| wpat++; |
| in_cclass = 1; |
| } |
| --- 125,148 ---- |
| if (wc == 0) |
| { |
| ! wpat--; /* back up to NUL */ |
| ! matlen += bracklen; |
| ! goto bad_bracket; |
| } |
| else if (wc == L'\\') |
| { |
| ! /* *wpat == backslash-escaped character */ |
| ! bracklen++; |
| ! /* If the backslash or backslash-escape ends the string, |
| ! bail. The ++wpat skips over the backslash escape */ |
| ! if (*wpat == 0 || *++wpat == 0) |
| ! { |
| ! matlen += bracklen; |
| ! goto bad_bracket; |
| ! } |
| } |
| else if (wc == L'[' && *wpat == L':') /* character class */ |
| { |
| wpat++; |
| + bracklen++; |
| in_cclass = 1; |
| } |
| *************** |
| *** 142,145 **** |
| --- 150,154 ---- |
| { |
| wpat++; |
| + bracklen++; |
| in_cclass = 0; |
| } |
| *************** |
| *** 147,152 **** |
| { |
| wpat++; |
| if (*wpat == L']') /* right bracket can appear as collating symbol */ |
| ! wpat++; |
| in_collsym = 1; |
| } |
| --- 156,165 ---- |
| { |
| wpat++; |
| + bracklen++; |
| if (*wpat == L']') /* right bracket can appear as collating symbol */ |
| ! { |
| ! wpat++; |
| ! bracklen++; |
| ! } |
| in_collsym = 1; |
| } |
| *************** |
| *** 154,157 **** |
| --- 167,171 ---- |
| { |
| wpat++; |
| + bracklen++; |
| in_collsym = 0; |
| } |
| *************** |
| *** 159,164 **** |
| { |
| wpat++; |
| if (*wpat == L']') /* right bracket can appear as equivalence class */ |
| ! wpat++; |
| in_equiv = 1; |
| } |
| --- 173,182 ---- |
| { |
| wpat++; |
| + bracklen++; |
| if (*wpat == L']') /* right bracket can appear as equivalence class */ |
| ! { |
| ! wpat++; |
| ! bracklen++; |
| ! } |
| in_equiv = 1; |
| } |
| *************** |
| *** 166,174 **** |
| --- 184,196 ---- |
| { |
| wpat++; |
| + bracklen++; |
| in_equiv = 0; |
| } |
| + else |
| + bracklen++; |
| } |
| while ((wc = *wpat++) != L']'); |
| matlen++; /* bracket expression can only match one char */ |
| + bad_bracket: |
| break; |
| } |
| *************** |
| *** 214,219 **** |
| size_t max; |
| { |
| ! char c, *brack; |
| ! int matlen, t, in_cclass, in_collsym, in_equiv; |
| |
| if (*pat == 0) |
| --- 236,241 ---- |
| size_t max; |
| { |
| ! char c; |
| ! int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; |
| |
| if (*pat == 0) |
| *************** |
| *** 255,259 **** |
| case '[': |
| /* scan for ending `]', skipping over embedded [:...:] */ |
| ! brack = pat; |
| c = *pat++; |
| do |
| --- 277,281 ---- |
| case '[': |
| /* scan for ending `]', skipping over embedded [:...:] */ |
| ! bracklen = 1; |
| c = *pat++; |
| do |
| *************** |
| *** 261,276 **** |
| if (c == 0) |
| { |
| ! matlen += pat - brack - 1; /* incremented below */ |
| ! break; |
| } |
| else if (c == '\\') |
| { |
| ! c = *pat++; |
| ! if (*pat == 0) |
| ! break; |
| } |
| else if (c == '[' && *pat == ':') /* character class */ |
| { |
| pat++; |
| in_cclass = 1; |
| } |
| --- 283,306 ---- |
| if (c == 0) |
| { |
| ! pat--; /* back up to NUL */ |
| ! matlen += bracklen; |
| ! goto bad_bracket; |
| } |
| else if (c == '\\') |
| { |
| ! /* *pat == backslash-escaped character */ |
| ! bracklen++; |
| ! /* If the backslash or backslash-escape ends the string, |
| ! bail. The ++pat skips over the backslash escape */ |
| ! if (*pat == 0 || *++pat == 0) |
| ! { |
| ! matlen += bracklen; |
| ! goto bad_bracket; |
| ! } |
| } |
| else if (c == '[' && *pat == ':') /* character class */ |
| { |
| pat++; |
| + bracklen++; |
| in_cclass = 1; |
| } |
| *************** |
| *** 278,281 **** |
| --- 308,312 ---- |
| { |
| pat++; |
| + bracklen++; |
| in_cclass = 0; |
| } |
| *************** |
| *** 283,288 **** |
| { |
| pat++; |
| if (*pat == ']') /* right bracket can appear as collating symbol */ |
| ! pat++; |
| in_collsym = 1; |
| } |
| --- 314,323 ---- |
| { |
| pat++; |
| + bracklen++; |
| if (*pat == ']') /* right bracket can appear as collating symbol */ |
| ! { |
| ! pat++; |
| ! bracklen++; |
| ! } |
| in_collsym = 1; |
| } |
| *************** |
| *** 290,293 **** |
| --- 325,329 ---- |
| { |
| pat++; |
| + bracklen++; |
| in_collsym = 0; |
| } |
| *************** |
| *** 295,300 **** |
| { |
| pat++; |
| if (*pat == ']') /* right bracket can appear as equivalence class */ |
| ! pat++; |
| in_equiv = 1; |
| } |
| --- 331,340 ---- |
| { |
| pat++; |
| + bracklen++; |
| if (*pat == ']') /* right bracket can appear as equivalence class */ |
| ! { |
| ! pat++; |
| ! bracklen++; |
| ! } |
| in_equiv = 1; |
| } |
| *************** |
| *** 302,310 **** |
| --- 342,354 ---- |
| { |
| pat++; |
| + bracklen++; |
| in_equiv = 0; |
| } |
| + else |
| + bracklen++; |
| } |
| while ((c = *pat++) != ']'); |
| matlen++; /* bracket expression can only match one char */ |
| + bad_bracket: |
| break; |
| } |
| *** ../bash-4.2-patched/patchlevel.h Sat Jun 12 20:14:48 2010 |
| --- ./patchlevel.h Thu Feb 24 21:41:34 2011 |
| *************** |
| *** 26,30 **** |
| looks for to find the patch level (for the sccs version string). */ |
| |
| ! #define PATCHLEVEL 2 |
| |
| #endif /* _PATCHLEVEL_H_ */ |
| --- 26,30 ---- |
| looks for to find the patch level (for the sccs version string). */ |
| |
| ! #define PATCHLEVEL 3 |
| |
| #endif /* _PATCHLEVEL_H_ */ |