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.

Raspunde prin e-mail lui