From 24e23de721bb8ddc042e0f11f44f4ff2ff7ebb0b Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 20 May 2026 21:02:00 +0200 Subject: fix(lua): use even safer and even better error() message conversion problem: this crashes neovim: ondska = setmetatable({}, {__tostring = error}) error(ondska) solution: make it not crash neovim --- src/nvim/lua/executor.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/nvim/lua/executor.c') diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 1ab51d7386..d7633bd828 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -277,16 +277,18 @@ lua_State *get_global_lstate(void) /// The returned string points to memory on the Lua stack. Use or duplicate it before using /// `lstate` again. /// -/// @param[out] len length of error (can be NULL) +/// @param[out] len length of error static const char *nlua_get_error(lua_State *lstate, size_t *len) + FUNC_ATTR_NONNULL_RET { - if (luaL_getmetafield(lstate, -1, "__tostring")) { - if (lua_isfunction(lstate, -1) && luaL_callmeta(lstate, -2, "__tostring")) { - // call __tostring, convert the result and replace error with it - lua_replace(lstate, -3); + if (lua_type(lstate, -1) != LUA_TSTRING) { + lua_getglobal(lstate, "tostring"); + lua_pushvalue(lstate, -2); + if (lua_pcall(lstate, 1, 1, 0) || lua_type(lstate, -1) != LUA_TSTRING) { + lua_pop(lstate, 1); + lua_pushstring(lstate, "[UNPRINTABLE ERROR]"); } - // pop __tostring. - lua_pop(lstate, 1); + lua_replace(lstate, -2); } return lua_tolstring(lstate, -1, len); @@ -433,10 +435,11 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres pthread_exit(0); #endif } - const char *error = lua_tostring(lstate, -1); + size_t len; + const char *error = nlua_get_error(lstate, &len); loop_schedule_deferred(&main_loop, event_create(nlua_luv_error_event, - error != NULL ? xstrdup(error) : NULL, + xmemdupz(error, len), (void *)(intptr_t)(is_callback ? kThreadCallback : kThread))); -- cgit