Skip to content

Commit 342d239

Browse files
Darleleta-denoyelle
authored andcommitted
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. (cherry picked from commit 365ee28) Signed-off-by: Amaury Denoyelle <[email protected]>
1 parent 2219de9 commit 342d239

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

src/hlua.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -848,20 +848,41 @@ void hlua_unref(lua_State *L, int ref)
848848
luaL_unref(L, LUA_REGISTRYINDEX, ref);
849849
}
850850

851-
__LJMP const char *hlua_traceback(lua_State *L, const char* sep)
851+
__LJMP static int _hlua_traceback(lua_State *L)
852+
{
853+
lua_Debug *ar = lua_touserdata(L, 1);
854+
855+
/* Fill fields:
856+
* 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
857+
* 'l': fills in the field currentline;
858+
* 'n': fills in the field name and namewhat;
859+
* 't': fills in the field istailcall;
860+
*/
861+
return lua_getinfo(L, "Slnt", ar);
862+
}
863+
864+
865+
/* This function cannot fail (output will simply be truncated upon errors) */
866+
const char *hlua_traceback(lua_State *L, const char* sep)
852867
{
853868
lua_Debug ar;
854869
int level = 0;
855870
struct buffer *msg = get_trash_chunk();
856871

857872
while (lua_getstack(L, level++, &ar)) {
858-
/* Fill fields:
859-
* 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
860-
* 'l': fills in the field currentline;
861-
* 'n': fills in the field name and namewhat;
862-
* 't': fills in the field istailcall;
863-
*/
864-
lua_getinfo(L, "Slnt", &ar);
873+
if (!lua_checkstack(L, 2))
874+
goto end; // abort
875+
876+
lua_pushcfunction(L, _hlua_traceback);
877+
lua_pushlightuserdata(L, &ar);
878+
879+
/* safe getinfo */
880+
switch (lua_pcall(L, 1, 1, 0)) {
881+
case LUA_OK:
882+
break;
883+
default:
884+
goto end; // abort
885+
}
865886

866887
/* skip these empty entries, usually they come from deep C functions */
867888
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)
902923
chunk_appendf(msg, " ...");
903924
}
904925

926+
end:
905927
return msg->area;
906928
}
907929

0 commit comments

Comments
 (0)