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;
if (has_mbyte) {
l = MB_BYTE2LEN(*p);
l = MB_PTR2LEN(p);
s = p;
if (l == 1) {
// be quick for ASCII
@ -3141,6 +3141,12 @@ spell_find_suggest (
STRLCPY(su->su_badword, su->su_badptr, su->su_badlen + 1);
(void)spell_casefold(su->su_badptr, su->su_badlen,
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
su->su_badflags = badword_captype(su->su_badptr,
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) {
int l;
if (has_mbyte)
l = MB_BYTE2LEN(fword[sp->ts_fidx]);
else
l = 1;
l = MB_PTR2LEN(fword + sp->ts_fidx);
if (fword_ends) {
// Copy the skipped character to preword.
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
// character (we didn't check that before).
sp->ts_fidx = sp->ts_fcharstart
+ MB_BYTE2LEN(
fword[sp->ts_fcharstart]);
+ MB_PTR2LEN(fword + sp->ts_fcharstart);
// For changing a composing character adjust
// 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.
if (has_mbyte) {
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))
stack[depth].ts_score -= SCORE_DEL - SCORE_DELCOMP;
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".
p = fword + sp->ts_fidx;
if (has_mbyte) {
n = MB_BYTE2LEN(*p);
n = MB_PTR2LEN(p);
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);
} else {
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"
p = fword + sp->ts_fidx;
if (has_mbyte) {
n = MB_BYTE2LEN(*p);
n = MB_PTR2LEN(p);
c2 = mb_ptr2char(p + n);
fl = MB_BYTE2LEN(p[n]);
fl = MB_PTR2LEN(p + n);
c = mb_ptr2char(p + n + fl);
tl = MB_BYTE2LEN(p[n + fl]);
tl = MB_PTR2LEN(p + n + fl);
memmove(p + fl + tl, p, n);
mb_char2bytes(c, p);
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"
p = fword + sp->ts_fidx;
if (has_mbyte) {
n = MB_BYTE2LEN(*p);
n += MB_BYTE2LEN(p[n]);
n = MB_PTR2LEN(p);
n += MB_PTR2LEN(p + n);
c = mb_ptr2char(p + n);
tl = MB_BYTE2LEN(p[n]);
tl = MB_PTR2LEN(p + n);
memmove(p + tl, p, n);
mb_char2bytes(c, p);
} 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;
if (has_mbyte) {
c = mb_ptr2char(p);
tl = MB_BYTE2LEN(*p);
n = MB_BYTE2LEN(p[tl]);
n += MB_BYTE2LEN(p[tl + n]);
tl = MB_PTR2LEN(p);
n = MB_PTR2LEN(p + tl);
n += MB_PTR2LEN(p + tl + n);
memmove(p, p + tl, n);
mb_char2bytes(c, p + n);
} else {

View File

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