aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/lua/executor.c
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2026-05-20 21:02:00 +0200
committerbfredl <bjorn.linse@gmail.com>2026-05-25 11:06:02 +0200
commit24e23de721bb8ddc042e0f11f44f4ff2ff7ebb0b (patch)
treeb382a4ab32dd24839ba4953b51c1d5c2373c0019 /src/nvim/lua/executor.c
parent526ae1cc1b432d7f1d9a412be86ac28c809f77eb (diff)
downloadrneovim-24e23de721bb8ddc042e0f11f44f4ff2ff7ebb0b.tar.gz
rneovim-24e23de721bb8ddc042e0f11f44f4ff2ff7ebb0b.tar.bz2
rneovim-24e23de721bb8ddc042e0f11f44f4ff2ff7ebb0b.zip
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
Diffstat (limited to 'src/nvim/lua/executor.c')
-rw-r--r--src/nvim/lua/executor.c21
1 files changed, 12 insertions, 9 deletions
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)));