]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0362: division by zero with smoothscroll and small windows v9.2.0362
authorJaehwang Jung <tomtomjhj@gmail.com>
Sun, 19 Apr 2026 18:32:55 +0000 (18:32 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 19 Apr 2026 18:32:55 +0000 (18:32 +0000)
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 <tomtomjhj@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/charset.c
src/testdir/test_scroll_opt.vim
src/version.c

index 8ad768d35490d40bdd944ba12ef433fe3d64641e..bf7c59620f1bee79c21d1139a7a8b6c7b94cb78c 100644 (file)
@@ -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)
index 390a8b59a2f4fd6352738bd71bdf3f37e156430c..6ece601f7adef6097eeece090bed75629db5d765 100644 (file)
@@ -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
index 4a4b69288b35f8c0076349583d2359255097b62a..7d09dfddd1448bf88c061daa2c612a3a72514f21 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    362,
 /**/
     361,
 /**/