commit d6d1bfd20da05e8bd40441ecdc0ac75af66f77eb
parent ed7ff848a02d37975dd56c2d67e0fe23e75f68dd
Author: Gabriel Ford <gabe@fordltc.net>
Date: Mon, 30 Jun 2025 09:22:42 -0400
fix(term): terminal attr index may exceed TERM_ATTRS_MAX #34318
Problem: Currently terminal highlight attribute buffers are statically allocated
be the size of `TERM_ATTRS_MAX`. This unique case isn't respected in
some places in the ui_compositor. Due to this, when a terminal window
has lines longer them `TERM_ATTRS_MAX`, the compositor will go past the
end of the buffer causing a crash due to out of bounds access.
Solution: Add check to ensure we don't query terminal highlight attrs
past `TERM_ATTRS_MAX` in `win_line()`.
Fixes #30374
Diffstat:
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
@@ -2266,7 +2266,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b
}
if (wp->w_buffer->terminal) {
- wlv.char_attr = hl_combine_attr(term_attrs[wlv.vcol], wlv.char_attr);
+ wlv.char_attr = hl_combine_attr(wlv.vcol < TERM_ATTRS_MAX ? term_attrs[wlv.vcol] : 0,
+ wlv.char_attr);
}
// we don't want linebreak to apply for lines that start with
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
@@ -3,6 +3,7 @@ local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local tt = require('test.functional.testterm')
+local assert_alive = n.assert_alive
local feed, clear = n.feed, n.clear
local api = n.api
local testprg, command = n.testprg, n.command
@@ -407,4 +408,21 @@ describe(':terminal', function()
|*6
]])
end)
+
+ it('zoomout with large horizontal output #30374', function()
+ skip(is_os('win'))
+
+ -- Start terminal smaller.
+ local screen = Screen.new(50, 50, { rgb = false })
+ feed([[:terminal<cr>]])
+
+ -- Generate very wide output.
+ feed('ifor i in $(seq 1 10000); do echo -n $i; done\r\n')
+
+ -- Make terminal big.
+ screen:try_resize(5000, 5000)
+ command('call jobresize(b:terminal_job_id, 5000, 5000)')
+
+ assert_alive()
+ end)
end)