diff options
author | luukvbaal <luukvbaal@gmail.com> | 2024-05-01 22:51:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-01 13:51:06 -0700 |
commit | e778e0116198470ba037b9426f4ff7fa5cb7f880 (patch) | |
tree | 17921986e3eed8347c60b821d287768ab437f401 /src/nvim/ui.c | |
parent | 631d5189adaaf54eb48e0b136df3466880edb19c (diff) | |
download | rneovim-e778e0116198470ba037b9426f4ff7fa5cb7f880.tar.gz rneovim-e778e0116198470ba037b9426f4ff7fa5cb7f880.tar.bz2 rneovim-e778e0116198470ba037b9426f4ff7fa5cb7f880.zip |
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.
Diffstat (limited to 'src/nvim/ui.c')
-rw-r--r-- | src/nvim/ui.c | 16 |
1 files changed, 6 insertions, 10 deletions
diff --git a/src/nvim/ui.c b/src/nvim/ui.c index f5bab309d8..9bb66b886e 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -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; } |