mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 06:28:35 +00:00
fix(ui): avoid recursiveness and invalid memory access #28578
Problem: Calling :redraw from vim.ui_attach() callback results in recursive cmdline/message events. Solution: Avoid recursiveness where possible and replace global "call_buf" with separate, temporary buffers for each event so that when a Lua callback for one event fires another event, that does not result in invalid memory access.
This commit is contained in:
@@ -71,8 +71,6 @@ static bool has_mouse = false;
|
||||
static int pending_has_mouse = -1;
|
||||
static bool pending_default_colors = false;
|
||||
|
||||
static Array call_buf = ARRAY_DICT_INIT;
|
||||
|
||||
#ifdef NVIM_LOG_DEBUG
|
||||
static size_t uilog_seen = 0;
|
||||
static const char *uilog_last_event = NULL;
|
||||
@@ -128,14 +126,11 @@ void ui_init(void)
|
||||
default_grid.handle = 1;
|
||||
msg_grid_adj.target = &default_grid;
|
||||
ui_comp_init();
|
||||
kv_ensure_space(call_buf, 16);
|
||||
}
|
||||
|
||||
#ifdef EXITFREE
|
||||
void ui_free_all_mem(void)
|
||||
{
|
||||
kv_destroy(call_buf);
|
||||
|
||||
UIEventCallback *event_cb;
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
free_ui_event_callback(event_cb);
|
||||
@@ -197,11 +192,9 @@ void ui_refresh(void)
|
||||
int width = INT_MAX;
|
||||
int height = INT_MAX;
|
||||
bool ext_widgets[kUIExtCount];
|
||||
for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
|
||||
ext_widgets[i] = ui_active();
|
||||
}
|
||||
|
||||
bool inclusive = ui_override();
|
||||
memset(ext_widgets, ui_active(), ARRAY_SIZE(ext_widgets));
|
||||
|
||||
for (size_t i = 0; i < ui_count; i++) {
|
||||
RemoteUI *ui = uis[i];
|
||||
width = MIN(ui->width, width);
|
||||
@@ -218,7 +211,7 @@ void ui_refresh(void)
|
||||
if (i < kUIGlobalCount) {
|
||||
ext_widgets[i] |= ui_cb_ext[i];
|
||||
}
|
||||
// Set 'cmdheight' to zero when ext_messages becomes active for all tabpages.
|
||||
// Set 'cmdheight' to zero for all tabpages when ext_messages becomes active.
|
||||
if (i == kUIMessages && !ui_ext[i] && ext_widgets[i]) {
|
||||
set_option_value(kOptCmdheight, NUMBER_OPTVAL(0), 0);
|
||||
command_height();
|
||||
@@ -722,6 +715,9 @@ void ui_call_event(char *name, Array args)
|
||||
map_foreach_value(&ui_event_cbs, event_cb, {
|
||||
Error err = ERROR_INIT;
|
||||
Object res = nlua_call_ref(event_cb->cb, name, args, kRetNilBool, NULL, &err);
|
||||
// TODO(bfredl/luukvbaal): should this be documented or reconsidered?
|
||||
// Why does truthy return from Lua callback mean remote UI should not receive
|
||||
// the event.
|
||||
if (LUARET_TRUTHY(res)) {
|
||||
handled = true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user