BUG/MINOR: hlua: prevent LJMP in hlua_traceback()

Function is often used on error paths where no precaution is taken
against LJMP. Since the function is used on error paths (which include
out-of-memory error paths) the function lua_getinfo() could also raise
a memory exception, causing the process to crash or improper error
handling if the caller isn't prepared against that eventually. Since the
function is only used on rare events (error handling) and is lacking the
__LJMP prototype pefix, let's make it safe by protecting the lua_getinfo()
call so that hlua_traceback() callers may use it safely now (the function
will always succeed, output will be truncated in case of error).

This could be backported to all stable versions.
This commit is contained in:
Aurelien DARRAGON 2024-06-04 10:41:32 +02:00
parent f0e5b825cf
commit 365ee28510

View File

@ -848,20 +848,41 @@ void hlua_unref(lua_State *L, int ref)
luaL_unref(L, LUA_REGISTRYINDEX, ref);
}
__LJMP const char *hlua_traceback(lua_State *L, const char* sep)
__LJMP static int _hlua_traceback(lua_State *L)
{
lua_Debug *ar = lua_touserdata(L, 1);
/* Fill fields:
* 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
* 'l': fills in the field currentline;
* 'n': fills in the field name and namewhat;
* 't': fills in the field istailcall;
*/
return lua_getinfo(L, "Slnt", ar);
}
/* This function cannot fail (output will simply be truncated upon errors) */
const char *hlua_traceback(lua_State *L, const char* sep)
{
lua_Debug ar;
int level = 0;
struct buffer *msg = get_trash_chunk();
while (lua_getstack(L, level++, &ar)) {
/* Fill fields:
* 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
* 'l': fills in the field currentline;
* 'n': fills in the field name and namewhat;
* 't': fills in the field istailcall;
*/
lua_getinfo(L, "Slnt", &ar);
if (!lua_checkstack(L, 2))
goto end; // abort
lua_pushcfunction(L, _hlua_traceback);
lua_pushlightuserdata(L, &ar);
/* safe getinfo */
switch (lua_pcall(L, 1, 1, 0)) {
case LUA_OK:
break;
default:
goto end; // abort
}
/* skip these empty entries, usually they come from deep C functions */
if (ar.currentline < 0 && *ar.what == 'C' && !*ar.namewhat && !ar.name)
@ -902,6 +923,7 @@ __LJMP const char *hlua_traceback(lua_State *L, const char* sep)
chunk_appendf(msg, " ...");
}
end:
return msg->area;
}