mirror of
https://github.com/vim/vim.git
synced 2025-09-06 21:53:38 -04:00
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:
parent
623e94e138
commit
bf533e4e88
@ -3333,3 +3333,5 @@ EXTERN char e_argument_nr_trying_to_modify_const_str[]
|
|||||||
EXTERN char e_cannot_resize_window_in_another_tab_page[]
|
EXTERN char e_cannot_resize_window_in_another_tab_page[]
|
||||||
INIT(= N_("E1308: Cannot resize a window in another tab page"));
|
INIT(= N_("E1308: Cannot resize a window in another tab page"));
|
||||||
#endif
|
#endif
|
||||||
|
EXTERN char e_cannot_change_mappings_while_listing[]
|
||||||
|
INIT(= N_("E1309: Cannot change mappings while listing"));
|
||||||
|
36
src/map.c
36
src/map.c
@ -24,6 +24,10 @@ static mapblock_T *first_abbr = NULL; // first entry in abbrlist
|
|||||||
static mapblock_T *(maphash[256]);
|
static mapblock_T *(maphash[256]);
|
||||||
static int maphash_valid = FALSE;
|
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.
|
* Make a hash value for a mapping.
|
||||||
* "mode" is the lower 4 bits of the State for the 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))
|
if (message_filtered(mp->m_keys) && message_filtered(mp->m_str))
|
||||||
return;
|
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)
|
if (msg_didout || msg_silent != 0)
|
||||||
{
|
{
|
||||||
msg_putchar('\n');
|
msg_putchar('\n');
|
||||||
if (got_int) // 'q' typed at MORE prompt
|
if (got_int) // 'q' typed at MORE prompt
|
||||||
return;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapchars = map_mode_to_chars(mp->m_mode);
|
mapchars = map_mode_to_chars(mp->m_mode);
|
||||||
@ -200,6 +208,9 @@ showmap(
|
|||||||
#endif
|
#endif
|
||||||
msg_clr_eos();
|
msg_clr_eos();
|
||||||
out_flush(); // show one line at a time
|
out_flush(); // show one line at a time
|
||||||
|
|
||||||
|
theend:
|
||||||
|
--map_locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -298,6 +309,9 @@ list_mappings(
|
|||||||
int mode,
|
int mode,
|
||||||
int *did_local)
|
int *did_local)
|
||||||
{
|
{
|
||||||
|
// Prevent mappings to be cleared while at the more prompt.
|
||||||
|
++map_locked;
|
||||||
|
|
||||||
if (p_verbose > 0 && keyround == 1 && seenModifyOtherKeys)
|
if (p_verbose > 0 && keyround == 1 && seenModifyOtherKeys)
|
||||||
msg_puts(_("Seen modifyOtherKeys: true"));
|
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);
|
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".
|
* Clear all mappings in "mode".
|
||||||
*/
|
*/
|
||||||
@ -968,6 +999,9 @@ map_clear_mode(
|
|||||||
int hash;
|
int hash;
|
||||||
int new_hash;
|
int new_hash;
|
||||||
|
|
||||||
|
if (is_map_locked())
|
||||||
|
return;
|
||||||
|
|
||||||
validate_maphash();
|
validate_maphash();
|
||||||
|
|
||||||
for (hash = 0; hash < 256; ++hash)
|
for (hash = 0; hash < 256; ++hash)
|
||||||
|
@ -1774,5 +1774,29 @@ func Test_using_past_typeahead()
|
|||||||
nunmap :00
|
nunmap :00
|
||||||
endfunc
|
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
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
873,
|
||||||
/**/
|
/**/
|
||||||
872,
|
872,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user