1
0
forked from aniani/vim

patch 9.0.0873: using freed memory when executing mapclear at more prompt

Problem:    Using freed memory when executing mapclear at the more prompt.
Solution:   Do not clear mappings while listing them. (closes #11438)
This commit is contained in:
Bram Moolenaar 2022-11-13 20:43:19 +00:00
parent 623e94e138
commit bf533e4e88
4 changed files with 63 additions and 1 deletions

View File

@ -3333,3 +3333,5 @@ EXTERN char e_argument_nr_trying_to_modify_const_str[]
EXTERN char e_cannot_resize_window_in_another_tab_page[]
INIT(= N_("E1308: Cannot resize a window in another tab page"));
#endif
EXTERN char e_cannot_change_mappings_while_listing[]
INIT(= N_("E1309: Cannot change mappings while listing"));

View File

@ -24,6 +24,10 @@ static mapblock_T *first_abbr = NULL; // first entry in abbrlist
static mapblock_T *(maphash[256]);
static int maphash_valid = FALSE;
// When non-zero then no mappings can be added or removed. Prevents mappings
// to change while listing them.
static int map_locked = 0;
/*
* Make a hash value for a mapping.
* "mode" is the lower 4 bits of the State for the mapping.
@ -150,11 +154,15 @@ showmap(
if (message_filtered(mp->m_keys) && message_filtered(mp->m_str))
return;
// Prevent mappings to be cleared while at the more prompt.
// Must jump to "theend" instead of returning.
++map_locked;
if (msg_didout || msg_silent != 0)
{
msg_putchar('\n');
if (got_int) // 'q' typed at MORE prompt
return;
goto theend;
}
mapchars = map_mode_to_chars(mp->m_mode);
@ -200,6 +208,9 @@ showmap(
#endif
msg_clr_eos();
out_flush(); // show one line at a time
theend:
--map_locked;
}
static int
@ -298,6 +309,9 @@ list_mappings(
int mode,
int *did_local)
{
// Prevent mappings to be cleared while at the more prompt.
++map_locked;
if (p_verbose > 0 && keyround == 1 && seenModifyOtherKeys)
msg_puts(_("Seen modifyOtherKeys: true"));
@ -337,6 +351,8 @@ list_mappings(
}
}
}
--map_locked;
}
/*
@ -954,6 +970,21 @@ map_clear(
map_clear_mode(curbuf, mode, local, abbr);
}
/*
* If "map_locked" is set then give an error and return TRUE.
* Otherwise return FALSE.
*/
static int
is_map_locked(void)
{
if (map_locked > 0)
{
emsg(_(e_cannot_change_mappings_while_listing));
return TRUE;
}
return FALSE;
}
/*
* Clear all mappings in "mode".
*/
@ -968,6 +999,9 @@ map_clear_mode(
int hash;
int new_hash;
if (is_map_locked())
return;
validate_maphash();
for (hash = 0; hash < 256; ++hash)

View File

@ -1774,5 +1774,29 @@ func Test_using_past_typeahead()
nunmap :00
endfunc
func Test_mapclear_while_listing()
CheckRunVimInTerminal
let lines =<< trim END
set nocompatible
mapclear
for i in range(1, 999)
exe 'map ' .. 'foo' .. i .. ' bar'
endfor
au CmdlineLeave : call timer_start(0, {-> execute('mapclear')})
END
call writefile(lines, 'Xmapclear', 'D')
let buf = RunVimInTerminal('-S Xmapclear', {'rows': 10})
" this was using freed memory
call term_sendkeys(buf, ":map\<CR>")
call TermWait(buf, 50)
call term_sendkeys(buf, "G")
call TermWait(buf, 50)
call term_sendkeys(buf, "\<CR>")
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
873,
/**/
872,
/**/