mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 02:34:59 -07:00
fix(lua): don't crash when lua_tolstring returns NULL for error value
This commit is contained in:
parent
dc110cba3c
commit
1ca73eae17
@ -123,6 +123,34 @@ lua_State *get_global_lstate(void)
|
||||
return global_lstate;
|
||||
}
|
||||
|
||||
/// get error on top of stack as a string
|
||||
///
|
||||
/// Might alter the top value on stack in place (but doesn't change stack height)
|
||||
///
|
||||
/// "error" points to memory on the lua stack, use
|
||||
/// or duplicate the string before using "lstate" again
|
||||
///
|
||||
/// @param[out] len length of error (can be NULL)
|
||||
static const char *nlua_get_error(lua_State *lstate, size_t *len)
|
||||
{
|
||||
if (luaL_getmetafield(lstate, -1, "__tostring")) {
|
||||
if (lua_isfunction(lstate, -1) && luaL_callmeta(lstate, -2, "__tostring")) {
|
||||
// call __tostring, convert the result replace error with it
|
||||
lua_replace(lstate, -3);
|
||||
}
|
||||
// pop __tostring.
|
||||
lua_pop(lstate, 1);
|
||||
}
|
||||
|
||||
const char *str = lua_tolstring(lstate, -1, len);
|
||||
if (str == NULL) {
|
||||
str = "[?????]";
|
||||
*len = 7;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/// Convert lua error into a Vim error message
|
||||
///
|
||||
/// @param lstate Lua interpreter state.
|
||||
@ -131,22 +159,7 @@ void nlua_error(lua_State *const lstate, const char *const msg)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
size_t len;
|
||||
const char *str = NULL;
|
||||
|
||||
if (luaL_getmetafield(lstate, -1, "__tostring")) {
|
||||
if (lua_isfunction(lstate, -1) && luaL_callmeta(lstate, -2, "__tostring")) {
|
||||
// call __tostring, convert the result and pop result.
|
||||
str = lua_tolstring(lstate, -1, &len);
|
||||
lua_pop(lstate, 1);
|
||||
}
|
||||
// pop __tostring.
|
||||
lua_pop(lstate, 1);
|
||||
}
|
||||
|
||||
if (!str) {
|
||||
// defer to lua default conversion, this will render tables as [NULL].
|
||||
str = lua_tolstring(lstate, -1, &len);
|
||||
}
|
||||
const char *str = nlua_get_error(lstate, &len);
|
||||
|
||||
if (in_script) {
|
||||
fprintf(stderr, msg, (int)len, str);
|
||||
@ -216,7 +229,9 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags
|
||||
// consider out of memory errors unrecoverable, just like xmalloc()
|
||||
preserve_exit(e_outofmem);
|
||||
}
|
||||
const char *error = lua_tostring(lstate, -1);
|
||||
|
||||
size_t len;
|
||||
const char *error = nlua_get_error(lstate, &len);
|
||||
|
||||
multiqueue_put(main_loop.events, nlua_luv_error_event,
|
||||
xstrdup(error), (void *)(intptr_t)kCallback);
|
||||
|
@ -136,4 +136,29 @@ describe('vim.uv', function()
|
||||
it("is equal to require('luv')", function()
|
||||
eq(true, exec_lua("return vim.uv == require('luv')"))
|
||||
end)
|
||||
|
||||
it("doesn't crash on async callbacks throwing nil error", function()
|
||||
local screen = Screen.new(50, 4)
|
||||
screen:attach()
|
||||
screen:set_default_attr_ids {
|
||||
[1] = { bold = true, reverse = true },
|
||||
[2] = { background = Screen.colors.Red, foreground = Screen.colors.Grey100 },
|
||||
[3] = { foreground = Screen.colors.SeaGreen4, bold = true },
|
||||
}
|
||||
|
||||
exec_lua [[
|
||||
local idle = vim.uv.new_idle()
|
||||
idle:start(function()
|
||||
idle:stop()
|
||||
error()
|
||||
end)
|
||||
]]
|
||||
|
||||
screen:expect([[
|
||||
{1: }|
|
||||
{2:Error executing luv callback:} |
|
||||
{2:[?????]} |
|
||||
{3:Press ENTER or type command to continue}^ |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user