aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-05-09 19:44:31 +0800
committerGitHub <noreply@github.com>2022-05-09 19:44:31 +0800
commitf0135d9cd969efa0148566937b5edcad06b1a56c (patch)
tree7678419391e69208de255f1f5b28e8140c4c6a19
parent41ce7b07e2946bdde0061d7af5b4446efafa5089 (diff)
parentdb506d991d80eb12016564eb62b5f636e7c8c836 (diff)
downloadrneovim-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.c33
-rw-r--r--src/nvim/option.c6
-rw-r--r--src/nvim/testdir/test_maparg.vim14
-rw-r--r--src/nvim/testdir/test_mapping.vim7
-rw-r--r--src/nvim/testdir/test_options.vim20
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:')