]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.4924: maparg() may return a string that cannot be reused v8.2.4924
authorzeertzjq <zeertzjq@outlook.com>
Mon, 9 May 2022 11:16:19 +0000 (12:16 +0100)
committerBram Moolenaar <Bram@vim.org>
Mon, 9 May 2022 11:16:19 +0000 (12:16 +0100)
Problem:    maparg() may return a string that cannot be reused.
Solution:   use msg_outtrans_special() instead of str2special().
            (closes #10384)

src/message.c
src/option.c
src/testdir/test_map_functions.vim
src/testdir/test_mapping.vim
src/testdir/test_options.vim
src/version.c

index 005a48b1cf0ca0920a72d7802e9a25cb48a4065e..6e21d665ddc3ad5f633593ab461c716a7dfae8ba 100644 (file)
@@ -1721,6 +1721,9 @@ msg_outtrans_special(
        }
        else
            text = (char *)str2special(&str, from);
+       if (text[0] != NUL && text[1] == NUL)
+           // single-byte character or illegal byte
+           text = (char *)transchar_byte((char_u)text[0]);
        len = vim_strsize((char_u *)text);
        if (maxlen > 0 && retval + len >= maxlen)
            break;
@@ -1755,6 +1758,7 @@ str2special_save(
 
 /*
  * Return the printable string for the key codes at "*sp".
+ * On illegal byte return a string with only that byte.
  * Used for translating the lhs or rhs of a mapping to printable chars.
  * Advances "sp" to the next code.
  */
@@ -1798,38 +1802,28 @@ str2special(
            special = TRUE;
     }
 
-    if (has_mbyte && !IS_SPECIAL(c))
+    if (has_mbyte && !IS_SPECIAL(c) && MB_BYTE2LEN(c) > 1)
     {
        char_u  *p;
 
        *sp = str;
        // Try to un-escape a multi-byte character after modifiers.
        p = mb_unescape(sp);
-
-       if (p == NULL)
-       {
-           int len = (*mb_ptr2len)(str);
-
-           // Check for an illegal byte.
-           if (MB_BYTE2LEN(*str) > len)
-           {
-               transchar_nonprint(curbuf, buf, c);
-               *sp = str + 1;
-               return buf;
-           }
-           *sp = str + len;
-           p = str;
-       }
-       // Since 'special' is TRUE the multi-byte character 'c' will be
-       // processed by get_special_key_name()
-       c = (*mb_ptr2char)(p);
+       if (p != NULL)
+           // Since 'special' is TRUE the multi-byte character 'c' will be
+           // processed by get_special_key_name()
+           c = (*mb_ptr2char)(p);
+       else
+           // illegal byte
+           *sp = str + 1;
     }
     else
+       // single-byte character or illegal byte
        *sp = str + 1;
 
-    // Make unprintable characters in <> form, also <M-Space> and <Tab>.
+    // Make special keys and C0 control characters in <> form, also <M-Space>.
     // Use <Space> only for lhs of a mapping.
-    if (special || char2cells(c) > 1 || (from && c == ' '))
+    if (special || c < ' ' || (from && c == ' '))
        return get_special_key_name(c, modifiers);
     buf[0] = c;
     buf[1] = NUL;
index 33bb641b3049de4376aea7b10eb9fe048ef626cb..e93c14cf41bc5bea5372bb307aafcabb5184a785 100644 (file)
@@ -4017,6 +4017,8 @@ get_option_value(
            if ((char_u **)varp == &curbuf->b_p_key
                                                && **(char_u **)(varp) != NUL)
                *stringval = vim_strsave((char_u *)"*****");
+           else if ((char_u **)varp == &p_pt)  // 'pastetoggle'
+               *stringval = str2special_save(*(char_u **)(varp), FALSE);
            else
 #endif
                *stringval = vim_strsave(*(char_u **)(varp));
index 21c899048a1988a7cce85fac180551646b1ecb86..e1380764770c10a70797983a87c689e0359b854a 100644 (file)
@@ -58,6 +58,20 @@ func Test_maparg()
   map abc y<S-char-114>y
   call assert_equal("yRy", maparg('abc'))
 
+  " character with K_SPECIAL byte
+  nmap abc …
+  call assert_equal('…', maparg('abc'))
+
+  " modified character with K_SPECIAL byte
+  nmap abc <M-…>
+  call assert_equal('<M-…>', maparg('abc'))
+
+  " illegal bytes
+  let str = ":\x7f:\x80:\x90:\xd0:"
+  exe 'nmap abc ' .. str
+  call assert_equal(str, maparg('abc'))
+  unlet str
+
   omap { w
   let d = maparg('{', 'o', 0, 1)
   call assert_equal(['{', 'w', 'o'], [d.lhs, d.rhs, d.mode])
index e886424fb1bdc85a2a332ded6626aad04277380f..2b5613b889c06c5aee20e5740e465436d040efce 100644 (file)
@@ -502,6 +502,13 @@ func Test_list_mappings()
   call assert_equal(['n  <M-…>         foo'],
         \ execute('nmap <M-…>')->trim()->split("\n"))
 
+  " illegal bytes
+  let str = ":\x7f:\x80:\x90:\xd0:"
+  exe 'nmap foo ' .. str
+  call assert_equal(['n  foo           ' .. strtrans(str)],
+        \ execute('nmap foo')->trim()->split("\n"))
+  unlet str
+
   " map to CTRL-V
   exe "nmap ,k \<C-V>"
   call assert_equal(['n  ,k            <Nop>'],
index 410d9461e3beb9c79e210b9354bb9ab8e5890939..8854ffd24000df1681668272da76ad4518e9196d 100644 (file)
@@ -48,6 +48,26 @@ func Test_isfname()
   set isfname&
 endfunc
 
+" Test for getting the value of 'pastetoggle'
+func Test_pastetoggle()
+  " character with K_SPECIAL byte
+  let &pastetoggle = '…'
+  call assert_equal('…', &pastetoggle)
+  call assert_equal("\n  pastetoggle=…", execute('set pastetoggle?'))
+
+  " modified character with K_SPECIAL byte
+  let &pastetoggle = '<M-…>'
+  call assert_equal('<M-…>', &pastetoggle)
+  call assert_equal("\n  pastetoggle=<M-…>", execute('set pastetoggle?'))
+
+  " illegal bytes
+  let str = ":\x7f:\x80:\x90:\xd0:"
+  let &pastetoggle = str
+  call assert_equal(str, &pastetoggle)
+  call assert_equal("\n  pastetoggle=" .. strtrans(str), execute('set pastetoggle?'))
+  unlet str
+endfunc
+
 func Test_wildchar()
   " Empty 'wildchar' used to access invalid memory.
   call assert_fails('set wildchar=', 'E521:')
index f2e0d317dd9fa2aadad208766d8873e8e359c945..d790a754035f7ad9e9a603b0567660fbf2165246 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4924,
 /**/
     4923,
 /**/