]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0076: [security]: buffer-overflow in terminal handling v9.2.0076
authorChristian Brabandt <cb@256bit.org>
Mon, 23 Feb 2026 20:29:43 +0000 (20:29 +0000)
committerChristian Brabandt <cb@256bit.org>
Fri, 27 Feb 2026 20:51:55 +0000 (20:51 +0000)
Problem:  When processing terminal output with many combining characters
          from supplementary planes (4-byte UTF-8), a heap-buffer
          overflow occurs. Additionally, the loop iterating over
          cell characters can read past the end of the vterm array
          (ehdgks0627, un3xploitable).
Solution: Use VTERM_MAX_CHARS_PER_CELL * 4 for ga_grow() to ensure
          sufficient space. Add a boundary check to the character
          loop to prevent index out-of-bounds access.

Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-rvj2-jrf9-2phg

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

index 0753c2892a7d76024b14d3007e31a6196da88a55..02ca5d6d95b798335358e91c84d2af6aed7bb300 100644 (file)
@@ -3570,12 +3570,13 @@ handle_pushline(int cols, const VTermScreenCell *cells, void *user)
     {
        for (col = 0; col < len; col += cells[col].width)
        {
-           if (ga_grow(&ga, MB_MAXBYTES) == FAIL)
+           if (ga_grow(&ga, VTERM_MAX_CHARS_PER_CELL * 4) == FAIL)
            {
                ga.ga_len = 0;
                break;
            }
-           for (i = 0; (c = cells[col].chars[i]) > 0 || i == 0; ++i)
+           for (i = 0; i < VTERM_MAX_CHARS_PER_CELL &&
+                   ((c = cells[col].chars[i]) > 0 || i == 0); ++i)
                ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
                        (char_u *)ga.ga_data + ga.ga_len);
            cell2cellattr(&cells[col], &p[col]);
diff --git a/src/testdir/samples/terminal_max_combining_chars.txt b/src/testdir/samples/terminal_max_combining_chars.txt
new file mode 100644 (file)
index 0000000..a4f508d
--- /dev/null
@@ -0,0 +1,80 @@
+padding line 000
+padding line 001
+padding line 002
+padding line 003
+padding line 004
+padding line 005
+padding line 006
+padding line 007
+padding line 008
+padding line 009
+padding line 010
+padding line 011
+padding line 012
+padding line 013
+padding line 014
+padding line 015
+padding line 016
+padding line 017
+padding line 018
+padding line 019
+padding line 020
+padding line 021
+padding line 022
+padding line 023
+padding line 024
+padding line 025
+padding line 026
+padding line 027
+padding line 028
+padding line 029
+padding line 030
+padding line 031
+padding line 032
+padding line 033
+padding line 034
+padding line 035
+padding line 036
+padding line 037
+padding line 038
+padding line 039
+padding line 040
+padding line 041
+padding line 042
+padding line 043
+padding line 044
+padding line 045
+padding line 046
+padding line 047
+padding line 048
+padding line 049
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
+AAAAAAAAAAAAAAAAAAAAAAAAAAAA𐀀󠄀󠄁󠄂󠄃󠄄
index b637a665282f6ee70dca22ae7d97b18d65ff613d..7deb0eaaf8194b6df45df18d0ce4467a02f99300 100644 (file)
@@ -1148,4 +1148,18 @@ func Test_terminal_split_utf8()
   exe buf .. "bwipe!"
 endfunc
 
+func Test_terminal_max_combining_chars()
+  " somehow doesn't work on MS-Windows
+  CheckUnix
+  let cmd = "cat samples/terminal_max_combining_chars.txt\<CR>"
+  let buf = Run_shell_in_terminal({'term_rows': 15, 'term_cols': 35})
+  call TermWait(buf)
+  call term_sendkeys(buf, cmd)
+  " last char is a space with many combining chars
+  call WaitForAssert({-> assert_match("AAAAAAAAAAAAAAAAAAAAAAAAAAAA.", term_getline(buf, 14))})
+
+  call term_sendkeys(buf, "exit\r")
+  exe buf . "bwipe!"
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index f2809216a54d8f57f6f861e2f4cb9e1efb60a683..21a1f3207c80b2b938b9aca0d7b30229c617bf25 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    76,
 /**/
     75,
 /**/