vim/backport-patch-8.2.4924-maparg-may-return-a-string-that-canno.patch
shixuantong de9879591c fix CVE-2022-2264 CVE-2022-2257 CVE-2022-2286 CVE-2022-2287
(cherry picked from commit abed0f93104ac6dbfb93cee247292b9f7e4036e3)
2022-07-13 14:58:40 +08:00

154 lines
4.9 KiB
Diff

From 0519ce00394474055bd58c089ea90a19986443eb Mon Sep 17 00:00:00 2001
From: zeertzjq <zeertzjq@outlook.com>
Date: Mon, 9 May 2022 12:16:19 +0100
Subject: [PATCH] patch 8.2.4924: maparg() may return a string that cannot be
reused
Problem: maparg() may return a string that cannot be reused.
Solution: use msg_outtrans_special() instead of str2special().
(closes #10384)
---
src/message.c | 35 +++++++++++++++--------------------
src/option.c | 2 ++
src/testdir/test_mapping.vim | 7 +++++++
src/testdir/test_options.vim | 20 ++++++++++++++++++++
4 files changed, 44 insertions(+), 20 deletions(-)
diff --git a/src/message.c b/src/message.c
index 0898d90..363dbe1 100644
--- a/src/message.c
+++ b/src/message.c
@@ -1637,6 +1637,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;
@@ -1671,6 +1674,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.
*/
@@ -1714,7 +1718,7 @@ str2special(
special = TRUE;
}
- if (has_mbyte && !IS_SPECIAL(c))
+ if (has_mbyte && !IS_SPECIAL(c) && MB_BYTE2LEN(c) > 1)
{
char_u *p;
@@ -1722,30 +1726,21 @@ str2special(
// 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;
diff --git a/src/option.c b/src/option.c
index eb610dd..6a93a7b 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3878,6 +3878,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));
diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim
index 58c284d..9e32b38 100644
--- a/src/testdir/test_mapping.vim
+++ b/src/testdir/test_mapping.vim
@@ -480,6 +480,13 @@ func Test_list_mappings()
nmap <M-…> foo
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
endfunc
diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim
index 7584465..e494cd9 100644
--- a/src/testdir/test_options.vim
+++ b/src/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:')
--
1.8.3.1