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 | 36 +++++++++++++----------------- src/option.c | 2 ++ src/testdir/test_map_functions.vim | 14 ++++++++++++ src/testdir/test_mapping.vim | 7 ++++++ src/testdir/test_options.vim | 20 +++++++++++++++++ src/version.c | 2 ++ 6 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/message.c b/src/message.c index 005a48b1c..6e21d665d 100644 --- a/src/message.c +++ b/src/message.c @@ -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; diff --git a/src/option.c b/src/option.c index 33bb641b3..e93c14cf4 100644 --- a/src/option.c +++ b/src/option.c @@ -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)); diff --git a/src/testdir/test_map_functions.vim b/src/testdir/test_map_functions.vim index 21c899048..e13807647 100644 --- a/src/testdir/test_map_functions.vim +++ b/src/testdir/test_map_functions.vim @@ -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]) diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index e886424fb..2b5613b88 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -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>'], diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 410d9461e..8854ffd24 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -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:') diff --git a/src/version.c b/src/version.c index f2e0d317d..d790a7540 100644 --- a/src/version.c +++ b/src/version.c @@ -746,6 +746,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 4924, /**/ 4923, /**/ -- 2.40.0