diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 8ea60a39..be4ffecf 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13881,3 +13881,27 @@ lib/readline/text.c Fixes a fuzzing bug - rl_exchange_point_and_mark: don't do anything if the mark is already less than 0 + + 5/12 + ---- +lib/readline/rlmbutil.h + - wchar_t: make sure this is defined as int if multibyte characters + aren't supported + +lib/readline/text.c + - _rl_change_case: don't force use of ascii toupper and tolower if + isascii returns true; it's not defined to work on characters outside + the 0..255 (really 0..127) range. Bug reported by + Eduardo Bustamante + + 5/14 + ---- +lib/readline/text.c + - rl_change_case: handle case where the old and new characters (after + the case change) are not the same number of bytes. Pointed out in + http://lists.gnu.org/archive/html/bug-bash/2015-01/msg00091.html + +lib/readline/display.c + - expand_prompt: use `ret' as first parameter to _rl_find_prev_mbchar + since that needs the base of the array. Bug from fuzzing reported by + Eduardo Bustamante diff --git a/MANIFEST b/MANIFEST index f72e0e73..b283adc6 100644 --- a/MANIFEST +++ b/MANIFEST @@ -652,6 +652,7 @@ examples/INDEX.html f #examples/obashdb/bashdb f #examples/obashdb/bashdb.el f examples/complete/bash_completion f +examples/complete/bash-completion-2.5.tar.xz f examples/complete/cdfunc f examples/complete/complete-examples f #examples/complete/complete.ianmac f diff --git a/examples/complete/bash-completion-2.5.tar.xz b/examples/complete/bash-completion-2.5.tar.xz new file mode 100644 index 00000000..f5b90790 Binary files /dev/null and b/examples/complete/bash-completion-2.5.tar.xz differ diff --git a/lib/readline/display.c b/lib/readline/display.c index ff317606..a4a9abd2 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -466,7 +466,7 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp) { #if defined (HANDLE_MULTIBYTE) if (mb_cur_max > 1 && rl_byte_oriented == 0) - new = _rl_find_prev_mbchar (r, r - ret, MB_FIND_ANY); + new = _rl_find_prev_mbchar (ret, r - ret, MB_FIND_ANY); else #endif new = r - ret - (physchars - bound); /* XXX */ diff --git a/lib/readline/rlmbutil.h b/lib/readline/rlmbutil.h index 2d083b9f..8b88de40 100644 --- a/lib/readline/rlmbutil.h +++ b/lib/readline/rlmbutil.h @@ -200,6 +200,10 @@ _rl_wcwidth (wc) #define UTF8_SINGLEBYTE(c) (1) +#if !defined (HAVE_WCHAR_T) && !defined (wchar_t) +# define wchar_t int +#endif + #endif /* !HANDLE_MULTIBYTE */ extern int rl_byte_oriented; diff --git a/lib/readline/text.c b/lib/readline/text.c index e4328588..86a13b10 100644 --- a/lib/readline/text.c +++ b/lib/readline/text.c @@ -1327,7 +1327,8 @@ static int rl_change_case (int count, int op) { int start, next, end; - int inword, c, nc, nop; + int inword, nc, nop; + wchar_t c; #if defined (HANDLE_MULTIBYTE) wchar_t wc, nwc; char mb[MB_LEN_MAX+1]; @@ -1377,7 +1378,10 @@ rl_change_case (int count, int op) } else nop = op; - if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii ((unsigned char)c)) + /* Can't check isascii here; some languages (e.g, Turkish) have + multibyte upper and lower case equivalents of single-byte ascii + characters */ + if (MB_CUR_MAX == 1 || rl_byte_oriented) { nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c); rl_line_buffer[start] = nc; @@ -1393,11 +1397,35 @@ rl_change_case (int count, int op) nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc); if (nwc != wc) /* just skip unchanged characters */ { + char *s, *e; mlen = wcrtomb (mb, nwc, &mps); if (mlen > 0) mb[mlen] = '\0'; - /* Assume the same width */ - strncpy (rl_line_buffer + start, mb, mlen); + /* what to do if m != mlen? adjust below */ + /* m == length of old char, mlen == length of new char */ + s = rl_line_buffer + start; + e = rl_line_buffer + rl_end; + if (m == mlen) + memcpy (s, mb, mlen); + else if (m > mlen) + { + memcpy (s, mb, mlen); + memmove (s + mlen, s + m, (e - s) - m); + next -= m - mlen; /* next char changes */ + end -= m - mlen; /* end of word changes */ + rl_end -= m - mlen; /* end of line changes */ + rl_line_buffer[rl_end] = 0; + } + else if (m < mlen) + { + rl_extend_line_buffer (mlen - m + 1); + memmove (s + mlen, s + m, (e - s) - m); + memcpy (s, mb, mlen); + next += mlen - m; /* next char changes */ + end += mlen - m; /* end of word changes */ + rl_end += mlen - m; /* end of line changes */ + rl_line_buffer[rl_end] = 0; + } } } #endif