]> granicus.if.org Git - vim/commitdiff
patch 8.2.4120: block insert goes over the end of the line v8.2.4120
authorBram Moolenaar <Bram@vim.org>
Mon, 17 Jan 2022 17:30:21 +0000 (17:30 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 17 Jan 2022 17:30:21 +0000 (17:30 +0000)
Problem:    Block insert goes over the end of the line.
Solution:   Handle invalid byte better.  Fix inserting the wrong text.

src/ops.c
src/testdir/test_visual.vim
src/version.c

index 6a378442c875b26f5f40266e897adbad8c9bbd9f..a9968024901ec1dc8ff2e5cf7eeaeb7c2e1edb0b 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -536,24 +536,29 @@ block_insert(
            if (b_insert)
            {
                off = (*mb_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 = (*mb_head_off)(oldp, oldp + offset);
+               offset -= off;
            }
-           spaces -= off;
-           count -= off;
        }
        if (spaces < 0)  // can happen when the cursor was moved
            spaces = 0;
 
-       newp = alloc(STRLEN(oldp) + s_len + count + 1);
+       // Make sure the allocated size matches what is actually copied below.
+       newp = alloc(STRLEN(oldp) + spaces + s_len
+                   + (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0)
+                                                                 + count + 1);
        if (newp == NULL)
            continue;
 
        // copy up to shifted part
-       mch_memmove(newp, oldp, (size_t)(offset));
+       mch_memmove(newp, oldp, (size_t)offset);
        oldp += offset;
 
        // insert pre-padding
@@ -564,14 +569,21 @@ block_insert(
        mch_memmove(newp + startcol, s, (size_t)s_len);
        offset += s_len;
 
-       if (spaces && !bdp->is_short)
+       if (spaces > 0 && !bdp->is_short)
        {
-           // insert post-padding
-           vim_memset(newp + offset + spaces, ' ', (size_t)(ts_val - spaces));
-           // We're splitting a TAB, don't copy it.
-           oldp++;
-           // We allowed for that TAB, remember this now
-           count++;
+           if (*oldp == TAB)
+           {
+               // insert post-padding
+               vim_memset(newp + offset + spaces, ' ',
+                                                   (size_t)(ts_val - spaces));
+               // we're splitting a TAB, don't copy it
+               oldp++;
+               // We allowed for that TAB, remember this now
+               count++;
+           }
+           else
+               // Not a TAB, no extra spaces
+               count = spaces;
        }
 
        if (spaces > 0)
@@ -1598,7 +1610,7 @@ op_insert(oparg_T *oap, long count1)
                    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)
                {
index e40be5dede98f7cb95c0a47bb7cdae305ccb9f51..9ca0fa9c8e742c2dba3511602bf4519709954588 100644 (file)
@@ -1278,6 +1278,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\88', 'xxxxxxxxxxx'])
+  exe "normal 0\<C-V>jjA-\<Esc>"
+  call assert_equal([' -   let xxx', 'xxxxx   -\88', 'xxxxxxxx-xxx'], getline(1, 3))
+  bwipe!
+endfunc
+
 func Test_visual_reselect_with_count()
   " this was causing an illegal memory access
   let lines =<< trim END
index 01b8e5d3dc79be11ad5d2b9b45edb74ff9cd2bc6..6fda77e93257b0b27eb43f570f7ce61953943378 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4120,
 /**/
     4119,
 /**/