diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 724c8b6642..8ee2ccbb4f 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -1902,7 +1902,7 @@ stcsign: int width = vim_strsize(out); if (maxwidth > 0 && width > maxwidth && (!stcp || width > MAX_STCWIDTH)) { // Result is too long, must truncate somewhere. - int item_idx = 0; + int item_idx = evalstart; char *trunc_p; // If there are no items, truncate from beginning @@ -1912,8 +1912,7 @@ stcsign: // Otherwise, look for the truncation item } else { // Default to truncating at the first item - trunc_p = stl_items[0].start; - item_idx = 0; + trunc_p = stl_items[item_idx].start; for (int i = evalstart; i < itemcnt + evalstart; i++) { if (stl_items[i].type == Trunc) { diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua index da3c914816..5cea1443fc 100644 --- a/test/functional/ui/statusline_spec.lua +++ b/test/functional/ui/statusline_spec.lua @@ -802,6 +802,28 @@ describe('statusline', function() | ]]) end) + + it('truncation inside nested nvim_eval_statusline does not crash #36616', function() + exec_lua(function() + function _G.statusline_truncating() + local win = vim.api.nvim_get_current_win() + local res = vim.api.nvim_eval_statusline('%f', { winid = win, maxwidth = 5 }) + return res.str + end + vim.o.laststatus = 2 + vim.o.statusline = '%#Special#B:%{%v:lua.statusline_truncating()%}' + end) + local truncated = exec_lua(function() + return vim.api.nvim_eval_statusline('%f', { maxwidth = 5 }).str + end) + local rendered = exec_lua(function() + return vim.api.nvim_eval_statusline( + vim.o.statusline, + { winid = vim.api.nvim_get_current_win() } + ).str + end) + eq('B:' .. truncated, rendered) + end) end) describe('default statusline', function()