1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
From: Markus Koschany <apo@debian.org>
Date: Sun, 23 Oct 2022 16:31:29 +0200
Subject: CVE-2022-0261
Origin: https://github.com/vim/vim/commit/9f8c304c8a390ade133bac29963dc8e56ab14cbc
---
src/ops.c | 41 ++++++++++++++++++++++++++---------------
src/testdir/test_visual.vim | 10 ++++++++++
src/version.c | 2 ++
3 files changed, 38 insertions(+), 15 deletions(-)
--- a/src/ops.c
+++ b/src/ops.c
@@ -636,22 +636,26 @@ 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;
}
-
- newp = alloc_check((unsigned)(STRLEN(oldp)) + s_len + count + 1);
+ // Make sure the allocated size matches what is actually copied below.
+ newp = alloc_check((unsigned)(STRLEN(oldp)) + spaces + s_len
+ + (spaces > 0 && !bdp->is_short ? p_ts - 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 */
@@ -661,14 +665,21 @@ block_insert(
mch_memmove(newp + offset + spaces, 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)(p_ts - 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)(p_ts - 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)
@@ -2702,7 +2713,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)
{
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -397,3 +397,13 @@ func Test_Visual_paragraph_textobject()
bwipe!
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
+
--- a/src/version.c
+++ b/src/version.c
@@ -792,6 +792,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4120,
+/**/
1401,
/**/
1382,
|