diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-05-09 19:44:31 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-09 19:44:31 +0800 |
commit | f0135d9cd969efa0148566937b5edcad06b1a56c (patch) | |
tree | 7678419391e69208de255f1f5b28e8140c4c6a19 | |
parent | 41ce7b07e2946bdde0061d7af5b4446efafa5089 (diff) | |
parent | db506d991d80eb12016564eb62b5f636e7c8c836 (diff) | |
download | rneovim-f0135d9cd969efa0148566937b5edcad06b1a56c.tar.gz rneovim-f0135d9cd969efa0148566937b5edcad06b1a56c.tar.bz2 rneovim-f0135d9cd969efa0148566937b5edcad06b1a56c.zip |
Merge pull request #18491 from zeertzjq/vim-8.2.4924
vim-patch:8.2.4924: maparg() may return a string that cannot be reused
-rw-r--r-- | src/nvim/message.c | 33 | ||||
-rw-r--r-- | src/nvim/option.c | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_maparg.vim | 14 | ||||
-rw-r--r-- | src/nvim/testdir/test_mapping.vim | 7 | ||||
-rw-r--r-- | src/nvim/testdir/test_options.vim | 20 |
5 files changed, 62 insertions, 18 deletions
diff --git a/src/nvim/message.c b/src/nvim/message.c index 47bc5893f2..f4ef91d1b7 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1618,6 +1618,10 @@ int msg_outtrans_special(const char_u *strstart, bool from, int maxlen) } else { text = str2special((const char **)&str, from, false); } + if (text[0] != NUL && text[1] == NUL) { + // single-byte character or illegal byte + text = (char *)transchar_byte((uint8_t)text[0]); + } const int len = vim_strsize((char_u *)text); if (maxlen > 0 && retval + len >= maxlen) { break; @@ -1666,6 +1670,7 @@ char *str2special_save(const char *const str, const bool replace_spaces, const b /// @return Converted key code, in a static buffer. Buffer is always one and the /// same, so save converted string somewhere before running str2special /// for the second time. +/// On illegal byte return a string with only that byte. const char *str2special(const char **const sp, const bool replace_spaces, const bool replace_lt) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET { @@ -1699,32 +1704,26 @@ const char *str2special(const char **const sp, const bool replace_spaces, const } } - if (!IS_SPECIAL(c)) { + if (!IS_SPECIAL(c) && MB_BYTE2LEN(c) > 1) { *sp = str; // Try to un-escape a multi-byte character after modifiers. const char *p = mb_unescape(sp); - - if (p == NULL) { - const int len = utf_ptr2len(str); - // Check for an illegal byte. - if (MB_BYTE2LEN((uint8_t)(*str)) > len) { - transchar_nonprint(curbuf, (char_u *)buf, c); - *sp = str + 1; - return buf; - } - *sp = str + len; - p = str; + if (p != NULL) { + // Since 'special' is true the multi-byte character 'c' will be + // processed by get_special_key_name(). + c = utf_ptr2char(p); + } else { + // illegal byte + *sp = str + 1; } - // Since 'special' is true the multi-byte character 'c' will be - // processed by get_special_key_name(). - c = utf_ptr2char(p); } 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>. if (special - || char2cells(c) > 1 + || c < ' ' || (replace_spaces && c == ' ') || (replace_lt && c == '<')) { return (const char *)get_special_key_name(c, modifiers); diff --git a/src/nvim/option.c b/src/nvim/option.c index ff742ea10a..e738c6c3b9 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -4980,7 +4980,11 @@ int get_option_value(const char *name, long *numval, char **stringval, int opt_f return -2; } if (stringval != NULL) { - *stringval = xstrdup(*(char **)varp); + if ((char_u **)varp == &p_pt) { // 'pastetoggle' + *stringval = str2special_save(*(char **)(varp), false, false); + } else { + *stringval = xstrdup(*(char **)(varp)); + } } return 0; } diff --git a/src/nvim/testdir/test_maparg.vim b/src/nvim/testdir/test_maparg.vim index cebde89996..f9429a8020 100644 --- a/src/nvim/testdir/test_maparg.vim +++ b/src/nvim/testdir/test_maparg.vim @@ -42,6 +42,20 @@ function 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]) diff --git a/src/nvim/testdir/test_mapping.vim b/src/nvim/testdir/test_mapping.vim index b5158295b4..995511cddf 100644 --- a/src/nvim/testdir/test_mapping.vim +++ b/src/nvim/testdir/test_mapping.vim @@ -488,6 +488,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>'], diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim index d16d89ec2e..8f67b1732e 100644 --- a/src/nvim/testdir/test_options.vim +++ b/src/nvim/testdir/test_options.vim @@ -31,6 +31,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:') |