mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(tui): make a copy of data->params before unibi_format() (#21643)
Problem: When unibi_format() modifies params and data->buf overflows, unibi_format() is called again, causing the params to be modified twice. This can happen for escapes sequences that use the %i terminfo format specifier (e.g. cursor_address), which makes unibi_format() increase the param by 1. Solution: Make a copy of data->params before calling unibi_format().
This commit is contained in:
parent
1bd6e4469b
commit
89232b8b48
@ -1635,11 +1635,13 @@ static void unibi_goto(UI *ui, int row, int col)
|
||||
} \
|
||||
if (str) { \
|
||||
unibi_var_t vars[26 + 26]; \
|
||||
unibi_var_t params[9]; \
|
||||
size_t orig_pos = data->bufpos; \
|
||||
memset(&vars, 0, sizeof(vars)); \
|
||||
data->cork = true; \
|
||||
retry: \
|
||||
unibi_format(vars, vars + 26, str, data->params, out, ui, pad, ui); \
|
||||
memcpy(params, data->params, sizeof(params)); \
|
||||
unibi_format(vars, vars + 26, str, params, out, ui, pad, ui); \
|
||||
if (data->overflow) { \
|
||||
data->bufpos = orig_pos; \
|
||||
flush_buf(ui); \
|
||||
|
@ -13,6 +13,7 @@ local feed_command = helpers.feed_command
|
||||
local feed_data = thelpers.feed_data
|
||||
local clear = helpers.clear
|
||||
local command = helpers.command
|
||||
local dedent = helpers.dedent
|
||||
local exec = helpers.exec
|
||||
local testprg = helpers.testprg
|
||||
local retry = helpers.retry
|
||||
@ -1443,6 +1444,31 @@ describe('TUI', function()
|
||||
child_session:request('nvim_call_function', 'setcellwidths', {{{0x2103, 0x2103, 1}}})
|
||||
screen:expect(singlewidth_screen, attrs)
|
||||
end)
|
||||
|
||||
it('draws correctly when cursor_address overflows #21643', function()
|
||||
helpers.skip(helpers.is_ci('github'), 'FIXME: flaky on GitHub CI')
|
||||
screen:try_resize(75, 60)
|
||||
-- The composing character takes 3 bytes.
|
||||
local composing = ('a︠'):sub(2)
|
||||
-- The composed character takes 1 + 5 * 3 = 16 bytes.
|
||||
local c = 'a' .. composing:rep(5)
|
||||
-- Going to top-left corner needs 3 bytes.
|
||||
-- With screen width 75, 4088 characters need 54 full screen lines.
|
||||
-- Drawing each full screen line needs 75 * 16 + 2 = 1202 bytes (2 bytes for CR LF).
|
||||
-- The incomplete screen line needs 38 * 16 + 8 + 3 = 619 bytes.
|
||||
-- The whole line needs 3 + 54 * 1202 + 619 = 65530 bytes.
|
||||
-- The cursor_address that comes after will overflow the 65535-byte buffer.
|
||||
local line = c:rep(4088) .. ('b'):rep(8) .. '℃'
|
||||
child_session:request('nvim_buf_set_lines', 0, 0, -1, true, {line, 'c'})
|
||||
screen:expect(
|
||||
'{1:' .. c .. '}' .. c:rep(74) .. '|\n' .. (c:rep(75) .. '|\n'):rep(53)
|
||||
.. c:rep(38) .. ('b'):rep(8) .. '℃' .. (' '):rep(28) .. '|\n' .. dedent([[
|
||||
c |
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
|
|
||||
{3:-- TERMINAL --} |]]))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('TUI', function()
|
||||
|
Loading…
Reference in New Issue
Block a user