Blame SOURCES/0001-patch-8.2.4120-block-insert-goes-over-the-end-of-the.patch

13ea7f
diff --git a/src/ops.c b/src/ops.c
13ea7f
index d8e96ff..88992b6 100644
13ea7f
--- a/src/ops.c
13ea7f
+++ b/src/ops.c
13ea7f
@@ -534,22 +534,27 @@ block_insert(
13ea7f
 	    if (b_insert)
13ea7f
 	    {
13ea7f
 		off = (*mb_head_off)(oldp, oldp + offset + spaces);
13ea7f
+		spaces -= off;
13ea7f
+		count -= off;
13ea7f
 	    }
13ea7f
 	    else
13ea7f
 	    {
13ea7f
-		off = (*mb_off_next)(oldp, oldp + offset);
13ea7f
-		offset += off;
13ea7f
+		// spaces fill the gap, the character that's at the edge moves
13ea7f
+		// right
13ea7f
+		off = (*mb_head_off)(oldp, oldp + offset);
13ea7f
+		offset -= off;
13ea7f
 	    }
13ea7f
-	    spaces -= off;
13ea7f
-	    count -= off;
13ea7f
 	}
13ea7f
 
13ea7f
-	newp = alloc(STRLEN(oldp) + s_len + count + 1);
13ea7f
+	// Make sure the allocated size matches what is actually copied below.
13ea7f
+	newp = alloc(STRLEN(oldp) + spaces + s_len
13ea7f
+		    + (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0)
13ea7f
+								  + count + 1);
13ea7f
 	if (newp == NULL)
13ea7f
 	    continue;
13ea7f
 
13ea7f
 	// copy up to shifted part
13ea7f
-	mch_memmove(newp, oldp, (size_t)(offset));
13ea7f
+	mch_memmove(newp, oldp, (size_t)offset);
13ea7f
 	oldp += offset;
13ea7f
 
13ea7f
 	// insert pre-padding
13ea7f
@@ -560,14 +565,21 @@ block_insert(
13ea7f
 	mch_memmove(newp + startcol, s, (size_t)s_len);
13ea7f
 	offset += s_len;
13ea7f
 
13ea7f
-	if (spaces && !bdp->is_short)
13ea7f
+	if (spaces > 0 && !bdp->is_short)
13ea7f
 	{
13ea7f
-	    // insert post-padding
13ea7f
-	    vim_memset(newp + offset + spaces, ' ', (size_t)(ts_val - spaces));
13ea7f
-	    // We're splitting a TAB, don't copy it.
13ea7f
-	    oldp++;
13ea7f
-	    // We allowed for that TAB, remember this now
13ea7f
-	    count++;
13ea7f
+	    if (*oldp == TAB)
13ea7f
+	    {
13ea7f
+		// insert post-padding
13ea7f
+		vim_memset(newp + offset + spaces, ' ',
13ea7f
+						    (size_t)(ts_val - spaces));
13ea7f
+		// we're splitting a TAB, don't copy it
13ea7f
+		oldp++;
13ea7f
+		// We allowed for that TAB, remember this now
13ea7f
+		count++;
13ea7f
+	    }
13ea7f
+	    else
13ea7f
+		// Not a TAB, no extra spaces
13ea7f
+		count = spaces;
13ea7f
 	}
13ea7f
 
13ea7f
 	if (spaces > 0)
13ea7f
@@ -1574,7 +1586,7 @@ op_insert(oparg_T *oap, long count1)
13ea7f
 		oap->start_vcol = t;
13ea7f
 	    }
13ea7f
 	    else if (oap->op_type == OP_APPEND
13ea7f
-		      && oap->end.col + oap->end.coladd
13ea7f
+		      && oap->start.col + oap->start.coladd
13ea7f
 			>= curbuf->b_op_start_orig.col
13ea7f
 					      + curbuf->b_op_start_orig.coladd)
13ea7f
 	    {
13ea7f
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
13ea7f
index 7c5f973..dc8e376 100644
13ea7f
--- a/src/testdir/test_visual.vim
13ea7f
+++ b/src/testdir/test_visual.vim
13ea7f
@@ -967,4 +967,13 @@ func Test_visual_put_in_block()
13ea7f
   bwipe!
13ea7f
 endfunc
13ea7f
 
13ea7f
+func Test_visual_block_append_invalid_char()
13ea7f
+  " this was going over the end of the line
13ea7f
+  new
13ea7f
+  call setline(1, ['	   let xxx', 'xxxxxˆ', 'xxxxxxxxxxx'])
13ea7f
+  exe "normal 0\<C-V>jjA-\<Esc>"
13ea7f
+  call assert_equal(['	-   let xxx', 'xxxxx   -ˆ', 'xxxxxxxx-xxx'], getline(1, 3))
13ea7f
+  bwipe!
13ea7f
+endfunc
13ea7f
+
13ea7f
 " vim: shiftwidth=2 sts=2 expandtab