aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-09-17 10:20:06 +0800
committerGitHub <noreply@github.com>2022-09-17 10:20:06 +0800
commit72e1041429565c3a592dedc36e8b3004a24cdcc4 (patch)
treeb4db84978b45e24710361242d5276bf7c9374c77
parent26b54d5c169d7d4afeb5433355b29eee78c12add (diff)
downloadrneovim-72e1041429565c3a592dedc36e8b3004a24cdcc4.tar.gz
rneovim-72e1041429565c3a592dedc36e8b3004a24cdcc4.tar.bz2
rneovim-72e1041429565c3a592dedc36e8b3004a24cdcc4.zip
vim-patch:9.0.0483: illegal memory access when replacing in virtualedit mode (#20225)
Problem: Illegal memory access when replacing in virtualedit mode. Solution: Check for replacing NUL after Tab. https://github.com/vim/vim/commit/c249913edc35c0e666d783bfc21595cf9f7d9e0d Cherry-pick Test_virtualedit_mouse() from patch 9.0.0177.
-rw-r--r--src/nvim/ops.c12
-rw-r--r--src/nvim/testdir/test_virtualedit.vim49
2 files changed, 59 insertions, 2 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 83484859ed..6391644f83 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1961,6 +1961,8 @@ static int op_replace(oparg_T *oap, int c)
// TODO(bfredl): we could batch all the splicing
// done on the same line, at least
while (ltoreq(curwin->w_cursor, oap->end)) {
+ bool done = false;
+
n = gchar_cursor();
if (n != NUL) {
int new_byte_len = utf_char2len(c);
@@ -1973,6 +1975,7 @@ static int op_replace(oparg_T *oap, int c)
oap->end.col += new_byte_len - old_byte_len;
}
replace_character(c);
+ done = true;
} else {
if (n == TAB) {
int end_vcol = 0;
@@ -1988,9 +1991,14 @@ static int op_replace(oparg_T *oap, int c)
getvpos(&oap->end, end_vcol);
}
}
- pbyte(curwin->w_cursor, c);
+ // with "coladd" set may move to just after a TAB
+ if (gchar_cursor() != NUL) {
+ pbyte(curwin->w_cursor, c);
+ done = true;
+ }
}
- } else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum) {
+ }
+ if (!done && virtual_op && curwin->w_cursor.lnum == oap->end.lnum) {
int virtcols = oap->end.coladd;
if (curwin->w_cursor.lnum == oap->start.lnum
diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim
index 522ca17675..e712896562 100644
--- a/src/nvim/testdir/test_virtualedit.vim
+++ b/src/nvim/testdir/test_virtualedit.vim
@@ -481,4 +481,53 @@ func Test_global_local_virtualedit()
set virtualedit&
endfunc
+func Test_virtualedit_mouse()
+ let save_mouse = &mouse
+ set mouse=a
+ set virtualedit=all
+ new
+
+ call setline(1, ["text\tword"])
+ redraw
+ call Ntest_setmouse(1, 4)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 4, 0, 4], getcurpos())
+ call Ntest_setmouse(1, 5)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 5, 0, 5], getcurpos())
+ call Ntest_setmouse(1, 6)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 5, 1, 6], getcurpos())
+ call Ntest_setmouse(1, 7)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 5, 2, 7], getcurpos())
+ call Ntest_setmouse(1, 8)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 5, 3, 8], getcurpos())
+ call Ntest_setmouse(1, 9)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 6, 0, 9], getcurpos())
+ call Ntest_setmouse(1, 15)
+ call feedkeys("\<LeftMouse>", "xt")
+ call assert_equal([0, 1, 10, 2, 15], getcurpos())
+
+ bwipe!
+ let &mouse = save_mouse
+ set virtualedit&
+endfunc
+
+" this was replacing the NUL at the end of the line
+func Test_virtualedit_replace_after_tab()
+ new
+ s/\v/ 0
+ set ve=all
+ let @" = ''
+ sil! norm vPvr0
+
+ call assert_equal("\t0", getline(1))
+ set ve&
+ bwipe!
+endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab