diff options
author | Sean Dewar <seandewar@users.noreply.github.com> | 2022-02-03 01:10:33 +0000 |
---|---|---|
committer | Sean Dewar <seandewar@users.noreply.github.com> | 2022-02-14 17:29:49 +0000 |
commit | e662d86e8d3198ea77e1a6d0b9be7c09255de520 (patch) | |
tree | 203262ec6ba152bedcc82a89f05ad42fa678c4cc | |
parent | f8b75e582215be5ed07aebb02cdbe69de8cad393 (diff) | |
download | rneovim-e662d86e8d3198ea77e1a6d0b9be7c09255de520.tar.gz rneovim-e662d86e8d3198ea77e1a6d0b9be7c09255de520.tar.bz2 rneovim-e662d86e8d3198ea77e1a6d0b9be7c09255de520.zip |
vim-patch:8.2.4120: block insert goes over the end of the line
Problem: Block insert goes over the end of the line.
Solution: Handle invalid byte better. Fix inserting the wrong text.
https://github.com/vim/vim/commit/9f8c304c8a390ade133bac29963dc8e56ab14cbc
-rw-r--r-- | src/nvim/ops.c | 38 | ||||
-rw-r--r-- | src/nvim/testdir/test_visual.vim | 9 |
2 files changed, 33 insertions, 14 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 68ce9824c7..e712aa18b3 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -573,19 +573,24 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def // Avoid starting halfway through a multi-byte character. if (b_insert) { off = utf_head_off(oldp, oldp + offset + spaces); + spaces -= off; + count -= off; } else { - off = mb_off_next(oldp, oldp + offset); - offset += off; + // spaces fill the gap, the character that's at the edge moves + // right + off = utf_head_off(oldp, oldp + offset); + offset -= off; } - spaces -= off; - count -= off; } if (spaces < 0) { // can happen when the cursor was moved spaces = 0; } assert(count >= 0); - newp = (char_u *)xmalloc(STRLEN(oldp) + s_len + (size_t)count + 1); + // Make sure the allocated size matches what is actually copied below. + newp = xmalloc(STRLEN(oldp) + (size_t)spaces + s_len + + (spaces > 0 && !bdp->is_short ? (size_t)p_ts - (size_t)spaces : 0) + + (size_t)count + 1); // copy up to shifted part memmove(newp, oldp, (size_t)offset); @@ -600,14 +605,19 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def offset += (int)s_len; int skipped = 0; - if (spaces && !bdp->is_short) { - // insert post-padding - memset(newp + offset + spaces, ' ', (size_t)(p_ts - spaces)); - // We're splitting a TAB, don't copy it. - oldp++; - // We allowed for that TAB, remember this now - count++; - skipped = 1; + if (spaces > 0 && !bdp->is_short) { + if (*oldp == TAB) { + // insert post-padding + memset(newp + offset + spaces, ' ', (size_t)(p_ts - spaces)); + // We're splitting a TAB, don't copy it. + oldp++; + // We allowed for that TAB, remember this now + count++; + skipped = 1; + } else { + // Not a TAB, no extra spaces + count = spaces; + } } if (spaces > 0) { @@ -2329,7 +2339,7 @@ void op_insert(oparg_T *oap, long count1) pre_textlen -= t - oap->start_vcol; oap->start_vcol = t; } else if (oap->op_type == OP_APPEND - && oap->end.col + oap->end.coladd + && oap->start.col + oap->start.coladd >= curbuf->b_op_start_orig.col + curbuf->b_op_start_orig.coladd) { oap->start.col = curbuf->b_op_start_orig.col; diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim index f95801cab5..a2c93bd573 100644 --- a/src/nvim/testdir/test_visual.vim +++ b/src/nvim/testdir/test_visual.vim @@ -1242,6 +1242,15 @@ func Test_visual_block_ctrl_w_f() au! BufNew endfunc +func Test_visual_block_append_invalid_char() + " this was going over the end of the line + new + call setline(1, [' let xxx', 'xxxxx', 'xxxxxxxxxxx']) + exe "normal 0\<C-V>jjA-\<Esc>" + call assert_equal([' - let xxx', 'xxxxx -', 'xxxxxxxx-xxx'], getline(1, 3)) + bwipe! +endfunc + func Test_visual_reselect_with_count() " this was causing an illegal memory access let lines =<< trim END |