]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0565: [security]: out-of-bounds read in update_snapshot() v9.2.0565
authorChristian Brabandt <cb@256bit.org>
Sat, 30 May 2026 16:34:40 +0000 (16:34 +0000)
committerChristian Brabandt <cb@256bit.org>
Sat, 30 May 2026 16:34:40 +0000 (16:34 +0000)
Problem:  Out-of-bounds read in update_snapshot() when a terminal cell
          fills all VTERM_MAX_CHARS_PER_CELL slots (a base character
          plus five combining marks): the loop over cell.chars[] has no
          upper bound and libvterm leaves the array unterminated when full, so
          it reads past the array and appends out-of-bounds values to a
          buffer sized for only VTERM_MAX_CHARS_PER_CELL characters.
Solution: Bound the loop with i < VTERM_MAX_CHARS_PER_CELL, mirroring
          the loop in handle_pushline() (Christian Brabandt).

Signed-off-by: Christian Brabandt <cb@256bit.org>
src/terminal.c
src/testdir/samples/combining_chars.txt [new file with mode: 0644]
src/testdir/test_terminal3.vim
src/version.c

index b843f22da34eeb6bfeaf586dd38e3e777843907a..b748ed35f1bfe4782e6da0f40dd06c35d6358ba3 100644 (file)
@@ -2265,7 +2265,8 @@ update_snapshot(term_T *term)
                            int     i;
                            int     c;
 
-                           for (i = 0; (c = cell.chars[i]) > 0 || i == 0; ++i)
+                           for (i = 0; i < VTERM_MAX_CHARS_PER_CELL &&
+                                   ((c = cell.chars[i]) > 0 || i == 0); ++i)
                                ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
                                             (char_u *)ga.ga_data + ga.ga_len);
                        }
diff --git a/src/testdir/samples/combining_chars.txt b/src/testdir/samples/combining_chars.txt
new file mode 100644 (file)
index 0000000..d9a3c17
--- /dev/null
@@ -0,0 +1,200 @@
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
index 04c7c925e37606ee8964813d0c1775fd7716a7f6..738a4c628425ad6ef7a2466829d53bba9935337f 100644 (file)
@@ -1241,4 +1241,19 @@ func Test_terminal_csi_args_overflow()
   call StopVimInTerminal(buf)
 endfunc
 
+func Test_terminal_output_combining_chars()
+  CheckUnix
+  new
+  let cmd = "cat samples/combining_chars.txt"
+  let buf = term_start(cmd, {'curwin': 1, 'term_finish': 'open', 'term_rows': 10, 'term_cols': 30})
+  call WaitForAssert({-> assert_match('finished', term_getstatus(buf))})
+  call TermWait(buf)
+  let lines = getbufline(buf, 1, '$')
+  " get byte lengths to confirm combining chars present
+  let lens = map(copy(lines), 'len(v:val)')
+  let expected = repeat([11], 190) + repeat([14], 10)
+  call assert_equal(expected, lens)
+  bw!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index 31d5a230597764562e2dc84606ec2b3d7a37e2be..7c9c18a7db45155acb56a922d55ff5839f632714 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    565,
 /**/
     564,
 /**/