# HG changeset patch # User Bram Moolenaar # Date 1652095803 -7200 # Node ID fea88e555652a84fa8c7ccf7c20bfec6c9ddd8df # Parent 6f38b93c86836db1b063532a4e5a3bc75449c3e1 patch 8.2.4924: maparg() may return a string that cannot be reused Commit: https://github.com/vim/vim/commit/0519ce00394474055bd58c089ea90a19986443eb Author: zeertzjq Date: Mon May 9 12:16:19 2022 +0100 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) diff --git a/src/message.c b/src/message.c --- 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 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 --- 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 --- a/src/testdir/test_map_functions.vim +++ b/src/testdir/test_map_functions.vim @@ -58,6 +58,20 @@ func Test_maparg() map abc yy 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 + call assert_equal('', 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 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -502,6 +502,13 @@ func Test_list_mappings() 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 + " map to CTRL-V exe "nmap ,k \" call assert_equal(['n ,k '], diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim --- 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 = '' + 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:') diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4924, +/**/ 4923, /**/ 4922,