From 0519ce00394474055bd58c089ea90a19986443eb Mon Sep 17 00:00:00 2001 From: zeertzjq 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 and . + /* Make special keys and C0 control characters in <> form, also . * Use 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 foo call assert_equal(['n foo'], \ execute('nmap ')->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 = '' + call assert_equal('', &pastetoggle) + call assert_equal("\n pastetoggle=", 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