patch 9.2.0565: [security]: out-of-bounds read in update_snapshot()

Commit: 
https://github.com/vim/vim/commit/63680c6d3d52477817b49cd1a66e7aabe8a7aa19
Author: Christian Brabandt <[email protected]>
Date:   Sat May 30 16:34:40 2026 +0000

    patch 9.2.0565: [security]: out-of-bounds read in update_snapshot()
    
    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 <[email protected]>

diff --git a/src/terminal.c b/src/terminal.c
index b843f22da..b748ed35f 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -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
index 000000000..d9a3c171f
--- /dev/null
+++ b/src/testdir/samples/combining_chars.txt
@@ -0,0 +1,200 @@
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
+á́́́́ጁ
diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim
index 04c7c925e..738a4c628 100644
--- a/src/testdir/test_terminal3.vim
+++ b/src/testdir/test_terminal3.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 31d5a2305..7c9c18a7d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    565,
 /**/
     564,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1wTN2a-00EcSu-NE%40256bit.org.

Raspunde prin e-mail lui