patch 9.1.0365: Crash when typing many keys with D- modifier Commit: https://github.com/vim/vim/commit/6b13e3d4e46393b3a35eed7c27ae020bcbd46a9b Author: zeertzjq <zeert...@outlook.com> Date: Mon Apr 22 21:04:29 2024 +0200
patch 9.1.0365: Crash when typing many keys with D- modifier Problem: Crash when typing many keys with D- modifier (after 9.1.0227). Solution: Don't treat a 0x80 byte inside a special sequence as the start of a special sequence (zeertzjq). closes: #14613 Signed-off-by: zeertzjq <zeert...@outlook.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/src/getchar.c b/src/getchar.c index 4e1c48c52..1c544da63 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -1286,12 +1286,11 @@ del_typebuf(int len, int offset) */ typedef struct { - int prev_c; char_u buf[MB_MAXBYTES * 3 + 4]; + int prev_c; size_t buflen; - unsigned pending; - int in_special; - int in_mbyte; + unsigned pending_special; + unsigned pending_mbyte; } gotchars_state_T; /* @@ -1303,32 +1302,29 @@ gotchars_add_byte(gotchars_state_T *state, char_u byte) { int c = state->buf[state->buflen++] = byte; int retval = FALSE; + int in_special = state->pending_special > 0; + int in_mbyte = state->pending_mbyte > 0; - if (state->pending > 0) - state->pending--; - - // When receiving a special key sequence, store it until we have all - // the bytes and we can decide what to do with it. - if ((state->pending == 0 || state->in_mbyte) - && (c == K_SPECIAL + if (in_special) + state->pending_special--; + else if (c == K_SPECIAL #ifdef FEAT_GUI || c == CSI #endif - )) - { - state->pending += 2; - if (!state->in_mbyte) - state->in_special = TRUE; - } + ) + // When receiving a special key sequence, store it until we have all + // the bytes and we can decide what to do with it. + state->pending_special = 2; - if (state->pending > 0) + if (state->pending_special > 0) goto ret_false; - if (!state->in_mbyte) + if (in_mbyte) + state->pending_mbyte--; + else { - if (state->in_special) + if (in_special) { - state->in_special = FALSE; if (state->prev_c == KS_MODIFIER) // When receiving a modifier, wait for the modified key. goto ret_false; @@ -1341,16 +1337,11 @@ gotchars_add_byte(gotchars_state_T *state, char_u byte) // When receiving a multibyte character, store it until we have all // the bytes, so that it won't be split between two buffer blocks, // and delete_buff_tail() will work properly. - state->pending = MB_BYTE2LEN_CHECK(c) - 1; - if (state->pending > 0) - { - state->in_mbyte = TRUE; - goto ret_false; - } + state->pending_mbyte = MB_BYTE2LEN_CHECK(c) - 1; } - else - // Stored all bytes of a multibyte character. - state->in_mbyte = FALSE; + + if (state->pending_mbyte > 0) + goto ret_false; retval = TRUE; ret_false: diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index c98d5bf33..117531046 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -248,21 +248,25 @@ func Test_map_meta_multibyte() endfunc func Test_map_super_quotes() - if has('gui_gtk') || has('gui_gtk3') || has("macos") - imap <D-"> foo - call feedkeys("Go-\<*D-\">-\<Esc>", "xt") - call assert_equal("-foo-", getline('$')) - set nomodified - iunmap <D-"> + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' endif + + imap <D-"> foo + call feedkeys("Go-\<*D-\">-\<Esc>", "xt") + call assert_equal("-foo-", getline('$')) + set nomodified + iunmap <D-"> endfunc func Test_map_super_multibyte() - if has('gui_gtk') || has('gui_gtk3') || has("macos") - imap <D-á> foo - call assert_match('i <D-á>\s*foo', execute('imap')) - iunmap <D-á> + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' endif + + imap <D-á> foo + call assert_match('i <D-á>\s*foo', execute('imap')) + iunmap <D-á> endfunc func Test_abbr_after_line_join() diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim index 1d377bdd4..b2261d4d6 100644 --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -261,6 +261,19 @@ func Test_zz_recording_with_select_mode_utf8_gui() call Run_test_recording_with_select_mode_utf8() endfunc +func Test_recording_with_super_mod() + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' + endif + + nnoremap <D-j> <Ignore> + let s = repeat("\<D-j>", 1000) + " This used to crash Vim + call feedkeys($'qr{s}q', 'tx') + call assert_equal(s, @r) + nunmap <D-j> +endfunc + " Test for executing the last used register (@) func Test_last_used_exec_reg() " Test for the @: command diff --git a/src/version.c b/src/version.c index c67ee48b2..a863838db 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 365, /**/ 364, /**/ -- -- 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 vim_dev+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/E1ryz88-008ow0-1H%40256bit.org.