aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ui.c
diff options
context:
space:
mode:
authorluukvbaal <luukvbaal@gmail.com>2024-05-01 22:51:06 +0200
committerGitHub <noreply@github.com>2024-05-01 13:51:06 -0700
commite778e0116198470ba037b9426f4ff7fa5cb7f880 (patch)
tree17921986e3eed8347c60b821d287768ab437f401 /src/nvim/ui.c
parent631d5189adaaf54eb48e0b136df3466880edb19c (diff)
downloadrneovim-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.c16
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;
}