patch 9.2.0362: division by zero with smoothscroll and small windows
Commit:
https://github.com/vim/vim/commit/0e31fb024c846e36bb0d26d01ff179a0d1b3eae4
Author: Jaehwang Jung <
tomt...@gmail.com>
Date: Sun Apr 19 18:32:55 2026 +0000
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: #20012
AI-assisted: Codex
Signed-off-by: Jaehwang Jung <
tomt...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/charset.c b/src/charset.c
index 8ad768d35..bf7c59620 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1468,7 +1468,8 @@ win_lbr_chartabsize(
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/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim
index 390a8b59a..6ece601f7 100644
--- a/src/testdir/test_scroll_opt.vim
+++ b/src/testdir/test_scroll_opt.vim
@@ -2090,4 +2090,42 @@ func Test_scrolloffpad_with_folds()
call StopVimInTerminal(buf)
let &termwinsize = save_termwinsize
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\<C-E>"
+ 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\<CR>")
+ 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
diff --git a/src/version.c b/src/version.c
index 4a4b69288..7d09dfddd 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 362,
/**/
361,
/**/