vim-patch:8.0.0582: illegal memory access with z= command

Problem:    Illegal memory access with z= command. (Dominique Pelle)
Solution:   Avoid case folded text to be longer than the original text.  Use
            MB_PTR2LEN() instead of MB_BYTE2LEN().

5b276aa80e
This commit is contained in:
Justin M. Keyes 2018-01-13 19:26:30 +01:00
parent 9ddeb6e187
commit 8eb0888a5d
2 changed files with 30 additions and 19 deletions

View File

@ -2568,7 +2568,7 @@ static bool spell_iswordp(char_u *p, win_T *wp)
int c; int c;
if (has_mbyte) { if (has_mbyte) {
l = MB_BYTE2LEN(*p); l = MB_PTR2LEN(p);
s = p; s = p;
if (l == 1) { if (l == 1) {
// be quick for ASCII // be quick for ASCII
@ -3141,6 +3141,12 @@ spell_find_suggest (
STRLCPY(su->su_badword, su->su_badptr, su->su_badlen + 1); STRLCPY(su->su_badword, su->su_badptr, su->su_badlen + 1);
(void)spell_casefold(su->su_badptr, su->su_badlen, (void)spell_casefold(su->su_badptr, su->su_badlen,
su->su_fbadword, MAXWLEN); su->su_fbadword, MAXWLEN);
// TODO(vim): make this work if the case-folded text is longer than the
// original text. Currently an illegal byte causes wrong pointer
// computations.
su->su_fbadword[su->su_badlen] = NUL;
// get caps flags for bad word // get caps flags for bad word
su->su_badflags = badword_captype(su->su_badptr, su->su_badflags = badword_captype(su->su_badptr,
su->su_badptr + su->su_badlen); su->su_badptr + su->su_badlen);
@ -4110,10 +4116,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
&& goodword_ends) { && goodword_ends) {
int l; int l;
if (has_mbyte) l = MB_PTR2LEN(fword + sp->ts_fidx);
l = MB_BYTE2LEN(fword[sp->ts_fidx]);
else
l = 1;
if (fword_ends) { if (fword_ends) {
// Copy the skipped character to preword. // Copy the skipped character to preword.
memmove(preword + sp->ts_prewordlen, memmove(preword + sp->ts_prewordlen,
@ -4259,8 +4262,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Correct ts_fidx for the byte length of the // Correct ts_fidx for the byte length of the
// character (we didn't check that before). // character (we didn't check that before).
sp->ts_fidx = sp->ts_fcharstart sp->ts_fidx = sp->ts_fcharstart
+ MB_BYTE2LEN( + MB_PTR2LEN(fword + sp->ts_fcharstart);
fword[sp->ts_fcharstart]);
// For changing a composing character adjust // For changing a composing character adjust
// the score from SCORE_SUBST to // the score from SCORE_SUBST to
@ -4366,7 +4368,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// results. // results.
if (has_mbyte) { if (has_mbyte) {
c = mb_ptr2char(fword + sp->ts_fidx); c = mb_ptr2char(fword + sp->ts_fidx);
stack[depth].ts_fidx += MB_BYTE2LEN(fword[sp->ts_fidx]); stack[depth].ts_fidx += MB_PTR2LEN(fword + sp->ts_fidx);
if (enc_utf8 && utf_iscomposing(c)) if (enc_utf8 && utf_iscomposing(c))
stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP; stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP;
else if (c == mb_ptr2char(fword + stack[depth].ts_fidx)) else if (c == mb_ptr2char(fword + stack[depth].ts_fidx))
@ -4552,9 +4554,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Undo the STATE_SWAP swap: "21" -> "12". // Undo the STATE_SWAP swap: "21" -> "12".
p = fword + sp->ts_fidx; p = fword + sp->ts_fidx;
if (has_mbyte) { if (has_mbyte) {
n = MB_BYTE2LEN(*p); n = MB_PTR2LEN(p);
c = mb_ptr2char(p + n); c = mb_ptr2char(p + n);
memmove(p + MB_BYTE2LEN(p[n]), p, n); memmove(p + MB_PTR2LEN(p + n), p, n);
mb_char2bytes(c, p); mb_char2bytes(c, p);
} else { } else {
c = *p; c = *p;
@ -4627,11 +4629,11 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Undo STATE_SWAP3: "321" -> "123" // Undo STATE_SWAP3: "321" -> "123"
p = fword + sp->ts_fidx; p = fword + sp->ts_fidx;
if (has_mbyte) { if (has_mbyte) {
n = MB_BYTE2LEN(*p); n = MB_PTR2LEN(p);
c2 = mb_ptr2char(p + n); c2 = mb_ptr2char(p + n);
fl = MB_BYTE2LEN(p[n]); fl = MB_PTR2LEN(p + n);
c = mb_ptr2char(p + n + fl); c = mb_ptr2char(p + n + fl);
tl = MB_BYTE2LEN(p[n + fl]); tl = MB_PTR2LEN(p + n + fl);
memmove(p + fl + tl, p, n); memmove(p + fl + tl, p, n);
mb_char2bytes(c, p); mb_char2bytes(c, p);
mb_char2bytes(c2, p + tl); mb_char2bytes(c2, p + tl);
@ -4690,10 +4692,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Undo ROT3L: "231" -> "123" // Undo ROT3L: "231" -> "123"
p = fword + sp->ts_fidx; p = fword + sp->ts_fidx;
if (has_mbyte) { if (has_mbyte) {
n = MB_BYTE2LEN(*p); n = MB_PTR2LEN(p);
n += MB_BYTE2LEN(p[n]); n += MB_PTR2LEN(p + n);
c = mb_ptr2char(p + n); c = mb_ptr2char(p + n);
tl = MB_BYTE2LEN(p[n]); tl = MB_PTR2LEN(p + n);
memmove(p + tl, p, n); memmove(p + tl, p, n);
mb_char2bytes(c, p); mb_char2bytes(c, p);
} else { } else {
@ -4743,9 +4745,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
p = fword + sp->ts_fidx; p = fword + sp->ts_fidx;
if (has_mbyte) { if (has_mbyte) {
c = mb_ptr2char(p); c = mb_ptr2char(p);
tl = MB_BYTE2LEN(*p); tl = MB_PTR2LEN(p);
n = MB_BYTE2LEN(p[tl]); n = MB_PTR2LEN(p + tl);
n += MB_BYTE2LEN(p[tl + n]); n += MB_PTR2LEN(p + tl + n);
memmove(p, p + tl, n); memmove(p, p + tl, n);
mb_char2bytes(c, p + n); mb_char2bytes(c, p + n);
} else { } else {

View File

@ -18,3 +18,12 @@ func Test_wrap_search()
bwipe! bwipe!
set nospell set nospell
endfunc endfunc
func Test_z_equal_on_invalid_utf8_word()
split
set spell
call setline(1, "\xff")
norm z=
set nospell
bwipe!
endfunc