From 4bdf9962bfd413077d979af4ddc406e7fcd4bbd6 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 13 Feb 2015 14:01:17 -0200 Subject: [PATCH] bug: suspended function can have its 'func' field not pointing to its function, crashing debug functions --- ldebug.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/ldebug.c b/ldebug.c index 93bfc002..f6c25db3 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.109 2014/12/10 11:30:09 roberto Exp roberto $ +** $Id: ldebug.c,v 2.110 2015/01/02 12:52:22 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -48,6 +48,22 @@ static int currentline (CallInfo *ci) { } +/* +** If function yielded, its 'func' can be in the 'extra' field. The +** next function restores 'func' to its correct value for debugging +** purposes. (It exchanges 'func' and 'extra'; so, when called again, +** after debugging, it also "re-restores" ** 'func' to its altered value. +*/ +static void swapextra (lua_State *L) { + if (L->status == LUA_YIELD) { + CallInfo *ci = L->ci; /* get function that yielded */ + StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ + ci->func = restorestack(L, ci->extra); + ci->extra = savestack(L, temp); + } +} + + /* ** this function can be called asynchronous (e.g. during a signal) */ @@ -144,6 +160,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n, LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; lua_lock(L); + swapextra(L); if (ar == NULL) { /* information about non-active function? */ if (!isLfunction(L->top - 1)) /* not a Lua function? */ name = NULL; @@ -158,6 +175,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { api_incr_top(L); } } + swapextra(L); lua_unlock(L); return name; } @@ -165,12 +183,15 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { StkId pos = 0; /* to avoid warnings */ - const char *name = findlocal(L, ar->i_ci, n, &pos); + const char *name; lua_lock(L); + swapextra(L); + name = findlocal(L, ar->i_ci, n, &pos); if (name) { setobjs2s(L, pos, L->top - 1); L->top--; /* pop value */ } + swapextra(L); lua_unlock(L); return name; } @@ -270,6 +291,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { CallInfo *ci; StkId func; lua_lock(L); + swapextra(L); if (*what == '>') { ci = NULL; func = L->top - 1; @@ -288,6 +310,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { setobjs2s(L, L->top, func); api_incr_top(L); } + swapextra(L); /* correct before option 'L', which can raise a mem. error */ if (strchr(what, 'L')) collectvalidlines(L, cl); lua_unlock(L);