From d6d1bfd20da05e8bd40441ecdc0ac75af66f77eb Mon Sep 17 00:00:00 2001 From: Gabriel Ford Date: Mon, 30 Jun 2025 09:22:42 -0400 Subject: [PATCH] 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 --- src/nvim/drawline.c | 3 ++- test/functional/terminal/highlight_spec.lua | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 39ae755bf1..2539390be0 100644 --- 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 index 42dbee02c8..2560e57341 100644 --- 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]]) + + -- 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)