From 79a7a4abe11f9b678cbf7073a4464fbe8631d57a Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Sun, 19 Apr 2026 02:16:31 +0900 Subject: [PATCH 1/2] fix(smoothscroll): crash when resizing to textoff with showbreak vim-patch:9.2.0362: division by zero with smoothscroll and small windows Problem: Resizing a smoothscrolled wrapped window to its textoff width with 'showbreak' can leave wrapped continuation lines with zero text width. win_lbr_chartabsize() still runs the partial max_head_vcol calculation in that state and divides by width2, crashing during redraw. Solution: Skip that partial head calculation when the wrapped continuation width is zero, matching the other width2 guards in charset.c (Jaehwang Jung) closes: vim/vim#20012 AI-assisted: Codex https://github.com/vim/vim/commit/0e31fb024c846e36bb0d26d01ff179a0d1b3eae4 --- src/nvim/plines.c | 2 +- test/functional/legacy/scroll_opt_spec.lua | 18 ++++++++++ test/old/testdir/test_scroll_opt.vim | 38 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/nvim/plines.c b/src/nvim/plines.c index 1fafdf2206..12b40c1a5a 100644 --- a/src/nvim/plines.c +++ b/src/nvim/plines.c @@ -269,7 +269,7 @@ CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vco if (max_head_vcol == 0 || vcol + size + added < max_head_vcol) { head += cnt * head_mid; - } else if (max_head_vcol > vcol + head_prev + prev_rem) { + } else if (width2 > 0 && max_head_vcol > vcol + head_prev + prev_rem) { head += (max_head_vcol - (vcol + head_prev + prev_rem) + width2 - 1) / width2 * head_mid; } else if (max_head_vcol < 0) { diff --git a/test/functional/legacy/scroll_opt_spec.lua b/test/functional/legacy/scroll_opt_spec.lua index 427a69ca01..16f061a5c7 100644 --- a/test/functional/legacy/scroll_opt_spec.lua +++ b/test/functional/legacy/scroll_opt_spec.lua @@ -1127,6 +1127,24 @@ describe('smoothscroll', function() screen:expect(screen_l_top) end) + -- oldtest: Test_smoothscroll_textoff_showbreak() + it('does not crash when resizing to textoff with showbreak', function() + exec([[ + set noswapfile scrolloff=0 + + call setline(1, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') + set number wrap smoothscroll showbreak=> + vsplit + + let textoff = getwininfo(win_getid())[0].textoff + execute "normal! 0\" + redraw + execute 'vertical resize' textoff + redraw + ]]) + assert_alive() + end) + it('works with virt_lines above and below', function() screen:try_resize(55, 7) exec([=[ diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim index 4db7db2a49..7c65afa38b 100644 --- a/test/old/testdir/test_scroll_opt.vim +++ b/test/old/testdir/test_scroll_opt.vim @@ -1443,4 +1443,42 @@ func Test_smoothscroll_listchars_eol() bwipe! endfunc + +" Resizing to "textoff" after 'smoothscroll' skips part of a wrapped line must +" not crash. +func Test_smoothscroll_textoff_showbreak() + CheckOption smoothscroll + + let donefile = 'XTest_crash_textoff_showbreak_done' + defer delete(donefile) + let lines =<< trim END + set noswapfile + + set scrolloff=0 + set lines=12 columns=40 + + call setline(1, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') + set number wrap smoothscroll showbreak=> + vsplit + + let textoff = getwininfo(win_getid())[0].textoff + execute "normal! 0\" + redraw + execute 'vertical resize' textoff + redraw + call writefile(['done'], 'XTest_crash_textoff_showbreak_done') + END + call writefile(lines, 'XTest_crash_textoff_showbreak', 'D') + + let buf = 0 + let buf = term_start([GetVimProg(), '--clean'], #{term_rows: 24, term_cols: 80}) + call TermWait(buf, 200) + call term_sendkeys(buf, ":source XTest_crash_textoff_showbreak\") + call WaitForAssert({-> assert_true(filereadable(donefile))}) + let status = term_getstatus(buf) + call assert_equal('running', status) + call assert_true(filereadable(donefile)) + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab From 2ee25ba41be465f36e4b67bf45f75d6563754d39 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 20 Apr 2026 09:31:22 +0800 Subject: [PATCH 2/2] vim-patch:9.2.0364: tests: test_smoothscroll_textoff_showbreak() fails Problem: tests: test_smoothscroll_textoff_showbreak() fails (after v9.2.0363) Solution: Add missing CheckRunVimInTerminal related: vim/vim#20011 https://github.com/vim/vim/commit/618a327ce6f6c7a47bdbf2a4f5d1c329d97e6037 Co-authored-by: Christian Brabandt --- test/old/testdir/test_scroll_opt.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim index 7c65afa38b..e5e5067b54 100644 --- a/test/old/testdir/test_scroll_opt.vim +++ b/test/old/testdir/test_scroll_opt.vim @@ -1448,6 +1448,7 @@ endfunc " not crash. func Test_smoothscroll_textoff_showbreak() CheckOption smoothscroll + CheckRunVimInTerminal let donefile = 'XTest_crash_textoff_showbreak_done' defer delete(donefile)