2
0
Эх сурвалжийг харах

bug: when manipulating other threads, there is no garanties about
their stack space

Roberto Ierusalimschy 10 жил өмнө
parent
commit
97f2aa5a44
1 өөрчлөгдсөн 20 нэмэгдсэн , 1 устгасан
  1. 20 1
      ldblib.c

+ 20 - 1
ldblib.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldblib.c,v 1.147 2014/12/08 15:47:25 roberto Exp roberto $
+** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -27,6 +27,17 @@
 static const int HOOKKEY = 0;
 static const int HOOKKEY = 0;
 
 
 
 
+/*
+** If L1 != L, L1 can be in any state, and therefore there is no
+** garanties about its stack space; any push in L1 must be
+** checked.
+*/
+static void checkstack (lua_State *L, lua_State *L1, int n) {
+  if (L != L1 && !lua_checkstack(L1, n))
+    luaL_error(L, "stack overflow");
+}
+
+
 static int db_getregistry (lua_State *L) {
 static int db_getregistry (lua_State *L) {
   lua_pushvalue(L, LUA_REGISTRYINDEX);
   lua_pushvalue(L, LUA_REGISTRYINDEX);
   return 1;
   return 1;
@@ -127,12 +138,16 @@ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {
 
 
 /*
 /*
 ** Calls 'lua_getinfo' and collects all results in a new table.
 ** Calls 'lua_getinfo' and collects all results in a new table.
+** L1 needs stack space for an optional input (function) plus
+** two optional outputs (function and line table) from function
+** 'lua_getinfo'.
 */
 */
 static int db_getinfo (lua_State *L) {
 static int db_getinfo (lua_State *L) {
   lua_Debug ar;
   lua_Debug ar;
   int arg;
   int arg;
   lua_State *L1 = getthread(L, &arg);
   lua_State *L1 = getthread(L, &arg);
   const char *options = luaL_optstring(L, arg+2, "flnStu");
   const char *options = luaL_optstring(L, arg+2, "flnStu");
+  checkstack(L, L1, 3);
   if (lua_isfunction(L, arg + 1)) {  /* info about a function? */
   if (lua_isfunction(L, arg + 1)) {  /* info about a function? */
     options = lua_pushfstring(L, ">%s", options);  /* add '>' to 'options' */
     options = lua_pushfstring(L, ">%s", options);  /* add '>' to 'options' */
     lua_pushvalue(L, arg + 1);  /* move function to 'L1' stack */
     lua_pushvalue(L, arg + 1);  /* move function to 'L1' stack */
@@ -190,6 +205,7 @@ static int db_getlocal (lua_State *L) {
     int level = (int)luaL_checkinteger(L, arg + 1);
     int level = (int)luaL_checkinteger(L, arg + 1);
     if (!lua_getstack(L1, level, &ar))  /* out of range? */
     if (!lua_getstack(L1, level, &ar))  /* out of range? */
       return luaL_argerror(L, arg+1, "level out of range");
       return luaL_argerror(L, arg+1, "level out of range");
+    checkstack(L, L1, 1);
     name = lua_getlocal(L1, &ar, nvar);
     name = lua_getlocal(L1, &ar, nvar);
     if (name) {
     if (name) {
       lua_xmove(L1, L, 1);  /* move local value */
       lua_xmove(L1, L, 1);  /* move local value */
@@ -216,6 +232,7 @@ static int db_setlocal (lua_State *L) {
     return luaL_argerror(L, arg+1, "level out of range");
     return luaL_argerror(L, arg+1, "level out of range");
   luaL_checkany(L, arg+3);
   luaL_checkany(L, arg+3);
   lua_settop(L, arg+3);
   lua_settop(L, arg+3);
+  checkstack(L, L1, 1);
   lua_xmove(L, L1, 1);
   lua_xmove(L, L1, 1);
   name = lua_setlocal(L1, &ar, nvar);
   name = lua_setlocal(L1, &ar, nvar);
   if (name == NULL)
   if (name == NULL)
@@ -350,6 +367,7 @@ static int db_sethook (lua_State *L) {
     lua_pushvalue(L, -1);
     lua_pushvalue(L, -1);
     lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
     lua_setmetatable(L, -2);  /* setmetatable(hooktable) = hooktable */
   }
   }
+  checkstack(L, L1, 1);
   lua_pushthread(L1); lua_xmove(L1, L, 1);  /* key (thread) */
   lua_pushthread(L1); lua_xmove(L1, L, 1);  /* key (thread) */
   lua_pushvalue(L, arg + 1);  /* value (hook function) */
   lua_pushvalue(L, arg + 1);  /* value (hook function) */
   lua_rawset(L, -3);  /* hooktable[L1] = new Lua hook */
   lua_rawset(L, -3);  /* hooktable[L1] = new Lua hook */
@@ -370,6 +388,7 @@ static int db_gethook (lua_State *L) {
     lua_pushliteral(L, "external hook");
     lua_pushliteral(L, "external hook");
   else {  /* hook table must exist */
   else {  /* hook table must exist */
     lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
     lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY);
+    checkstack(L, L1, 1);
     lua_pushthread(L1); lua_xmove(L1, L, 1);
     lua_pushthread(L1); lua_xmove(L1, L, 1);
     lua_rawget(L, -2);   /* 1st result = hooktable[L1] */
     lua_rawget(L, -2);   /* 1st result = hooktable[L1] */
     lua_remove(L, -2);  /* remove hook table */
     lua_remove(L, -2);  /* remove hook table */