From: Christian Brabandt Date: Mon, 23 Feb 2026 20:29:43 +0000 (+0000) Subject: patch 9.2.0076: [security]: buffer-overflow in terminal handling X-Git-Tag: v9.2.0076^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bb6de2105b160e729c340631435cd62f3e69bd32;p=thirdparty%2Fvim.git patch 9.2.0076: [security]: buffer-overflow in terminal handling 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 --- diff --git a/src/terminal.c b/src/terminal.c index 0753c2892a..02ca5d6d95 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -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 index 0000000000..a4f508d547 --- /dev/null +++ b/src/testdir/samples/terminal_max_combining_chars.txt @@ -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𐀀󠄀󠄁󠄂󠄃󠄄 diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim index b637a66528..7deb0eaaf8 100644 --- a/src/testdir/test_terminal3.vim +++ b/src/testdir/test_terminal3.vim @@ -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\" + 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 diff --git a/src/version.c b/src/version.c index f2809216a5..21a1f3207c 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 76, /**/ 75, /**/