Commit: patch 9.2.0989: libvterm: hang when rendering REP with no preceding char
Christian Brabandt <[email protected]>
| Newsgroups | gmane.editors.vim.devel |
|---|---|
| Message-ID | <[email protected]> |
patch 9.2.0989: libvterm: hang when rendering REP with no preceding char Commit: https://github.com/vim/vim/commit/785bb3e9b271eb377dbd4157ce281eac7f16a021 Author: Christian Brabandt <[email protected]> Date: Thu Aug 20 20:46:08 2026 +0000 patch 9.2.0989: libvterm: hang when rendering REP with no preceding char Problem: When libvterm receives the REP control (CSI b) it repeats the preceding graphic character by advancing the cursor by "combine_width". When a graphic char was yet not printed, this resulted in an endless loop (Vadím Sukhomlínov). Solution: Ignore REP when no graphic character was printed yet, like xterm does. related: #21099 Signed-off-by: Christian Brabandt <[email protected]> Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> diff --git a/src/libvterm/src/state.c b/src/libvterm/src/state.c index 70bce0a23..7a9732b58 100644 --- a/src/libvterm/src/state.c +++ b/src/libvterm/src/state.c @@ -1323,6 +1323,13 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha case 0x62: { // REP - ECMA-48 8.3.103 const int row_width = THISROWWIDTH(state); + + // ECMA-48 repeats the preceding graphic character; when none was + // printed yet "combine_width" is zero and the loop below would never + // advance the cursor. Ignore the control then, like xterm does. + if(state->combine_width < 1) + break; + count = CSI_ARG_COUNT(args[0]); col = state->pos.col + count; UBOUND(col, row_width); diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim index 7d67d6f68..263e9ee34 100644 --- a/src/testdir/test_terminal3.vim +++ b/src/testdir/test_terminal3.vim @@ -1396,4 +1396,27 @@ func Test_terminal_negative_col_oob() endfor endfunc +" This caused a hang +func Test_terminal_rep_no_preceding_char() + CheckUnix + CheckExecutable printf + + " REP repeats the preceding graphic character. When none was printed yet + " the repeat width in libvterm is zero, so the cursor never reached the end + " column and Vim looped forever while rendering the sequence. + let buf = term_start([&shell, &shellcmdflag, 'printf "%s" ' .. shellescape("\<ESC>[9b")], + \ #{term_rows: 10, term_cols: 40}) + call TermWait(buf) + " Getting here without a hang is the test. + call assert_true(bufexists(buf)) + exe 'bwipe! ' .. buf + + " REP after a graphic character still repeats it. + let buf = term_start([&shell, &shellcmdflag, 'printf "%s" ' .. shellescape("X\<ESC>[4b")], + \ #{term_rows: 10, term_cols: 40}) + call TermWait(buf) + call WaitForAssert({-> assert_equal('XXXXX', term_getline(buf, 1))}) + exe 'bwipe! ' .. buf +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index a8698a9fd..840e5cf8b 100644 --- a/src/version.c +++ b/src/version.c @@ -763,6 +763,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 989, /**/ 988, /**/ -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1wxAKs-00E7PI-3X%40256bit.org.