From 4b25fe09ccf80dd24851d88785b1596248ad18f7 Mon Sep 17 00:00:00 2001 From: "neovim-backports[bot]" <175700243+neovim-backports[bot]@users.noreply.github.com> Date: Sun, 19 Jan 2025 01:00:18 +0000 Subject: [PATCH] fix(lua): prevent SIGSEGV when lua error is NULL in libuv_worker (#32091) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Calling `xstrdup` with a NULL pointer causes a SIGSEGV if `lua_tostring` returns NULL in `nlua_luv_thread_common_cfpcall`. Crash stack trace: - `_platform_strlen` → `xstrdup` (memory.c:469) - `nlua_luv_thread_common_cfpcall` (executor.c:281) Solution: Check if `lua_tostring` returns NULL and pass NULL to `event_create` to avoid the crash. (cherry picked from commit a5b1b83a2693ffa7a5a0a22b3693d36ea60051be) Co-authored-by: 林玮 (Jade Lin) --- src/nvim/lua/executor.c | 3 +-- test/functional/lua/thread_spec.lua | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 6f9f9d332a..6f968747fc 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -274,10 +274,9 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres #endif } const char *error = lua_tostring(lstate, -1); - loop_schedule_deferred(&main_loop, event_create(nlua_luv_error_event, - xstrdup(error), + error != NULL ? xstrdup(error) : NULL, (void *)(intptr_t)(is_callback ? kThreadCallback : kThread))); diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua index 780057b580..1f8ae74fe8 100644 --- a/test/functional/lua/thread_spec.lua +++ b/test/functional/lua/thread_spec.lua @@ -27,6 +27,26 @@ describe('thread', function() }) end) + it('handle non-string error', function() + exec_lua [[ + local thread = vim.uv.new_thread(function() + error() + end) + vim.uv.thread_join(thread) + ]] + + screen:expect([[ + | + {1:~ }|*5 + {2: }| + {3:Error in luv thread:} | + {3:[NULL]} | + {4:Press ENTER or type command to continue}^ | + ]]) + feed('') + assert_alive() + end) + it('entry func is executed in protected mode', function() exec_lua [[ local thread = vim.uv.new_thread(function()