Skip to content

GHSA-47gw-8gc3-mgcm

CVE Information

Out-of-bounds Read in Terminal Screen Snapshot in Vim < 9.2.565

Date: 30.05.2026 Severity: Medium CVE: CVE-2026-52859 CWE: Out-of-bounds Read (CWE-125)

Summary

The update_snapshot() function in src/terminal.c copies the visible terminal screen into the scrollback buffer when a snapshot is taken. For each screen cell it walks the cell's chars[] array with no upper bound, stopping only when it encounters a NUL terminator. When a cell legitimately fills all VTERM_MAX_CHARS_PER_CELL (6) slots — a base character plus five combining marks — the bundled libvterm returns the array without a terminating NUL, so the loop reads past the fixed six-element array and appends the out-of-bounds values to a buffer reserved for only six characters. A program whose output is rendered inside a :terminal window can trigger this with a short byte sequence and no Vim scripting, leading to a crash.

Description

update_snapshot() is invoked whenever the terminal's visible screen is snapshotted into the scrollback buffer, for example when the user enters Terminal-Normal mode with CTRL-W N, or when the terminal job exits. For each cell it retrieves the cell with vterm_screen_get_cell() and emits its characters with:

for (i = 0; (c = cell.chars[i]) > 0 || i == 0; ++i) ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c, (char_u *)ga.ga_data + ga.ga_len);

The loop has no i < VTERM_MAX_CHARS_PER_CELL guard and relies on the array being NUL-terminated. The bundled libvterm fills cell.chars[] with up to VTERM_MAX_CHARS_PER_CELL entries and only writes a terminator when fewer than that many characters are present. A cell holding a base glyph plus five combining marks therefore fills all six slots and is returned unterminated, so the loop reads cell.chars[6] and beyond — past the end of the array — and appends each out-of-bounds value to the snapshot buffer, which was grown for only VTERM_MAX_CHARS_PER_CELL characters.

Impact

A program running inside a :terminal window normally controls only its own output and cannot affect the parent Vim process's memory. By emitting a single cell that fills all six character slots, such a program causes Vim to read past a fixed-size array and append attacker-influenced, out-of-bounds values to a buffer sized for only six characters. The reliably reproduced outcome is an out-of-bounds read leading to a crash (denial of service) of the editor.

Mitigation

The issue is fixed as of Vim patch v9.2.0565, which bounds the loop in update_snapshot() with i < VTERM_MAX_CHARS_PER_CELL, mirroring the existing bound in handle_pushline().

Acknowledgements

The Vim project would like to thank github user andrejtomci for reporting and analyzing the issue and suggesting a fix.

References

The issue has been fixed as of Vim patch v9.2.565. - Commit - Github Security Advisory