diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-02-19 15:06:21 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-02-19 15:06:21 -0200 |
| commit | 97f2aa5a443b75f2528a27e6e78fe18f66cb4f87 (patch) | |
| tree | 1cd2494cc684dd41769f3be66cb1b4040e1da231 | |
| parent | 419e2cb01d3527928cc4035f8b9b9589946e0e1a (diff) | |
| download | lua-97f2aa5a443b75f2528a27e6e78fe18f66cb4f87.tar.gz lua-97f2aa5a443b75f2528a27e6e78fe18f66cb4f87.tar.bz2 lua-97f2aa5a443b75f2528a27e6e78fe18f66cb4f87.zip | |
bug: when manipulating other threads, there is no garanties about
their stack space
| -rw-r--r-- | ldblib.c | 21 |
1 files changed, 20 insertions, 1 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldblib.c,v 1.147 2014/12/08 15:47:25 roberto Exp roberto $ | 2 | ** $Id: ldblib.c,v 1.148 2015/01/02 12:52:22 roberto Exp roberto $ |
| 3 | ** Interface from Lua to its debug API | 3 | ** Interface from Lua to its debug API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -27,6 +27,17 @@ | |||
| 27 | static const int HOOKKEY = 0; | 27 | static const int HOOKKEY = 0; |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | /* | ||
| 31 | ** If L1 != L, L1 can be in any state, and therefore there is no | ||
| 32 | ** garanties about its stack space; any push in L1 must be | ||
| 33 | ** checked. | ||
| 34 | */ | ||
| 35 | static void checkstack (lua_State *L, lua_State *L1, int n) { | ||
| 36 | if (L != L1 && !lua_checkstack(L1, n)) | ||
| 37 | luaL_error(L, "stack overflow"); | ||
| 38 | } | ||
| 39 | |||
| 40 | |||
| 30 | static int db_getregistry (lua_State *L) { | 41 | static int db_getregistry (lua_State *L) { |
| 31 | lua_pushvalue(L, LUA_REGISTRYINDEX); | 42 | lua_pushvalue(L, LUA_REGISTRYINDEX); |
| 32 | return 1; | 43 | return 1; |
| @@ -127,12 +138,16 @@ static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { | |||
| 127 | 138 | ||
| 128 | /* | 139 | /* |
| 129 | ** Calls 'lua_getinfo' and collects all results in a new table. | 140 | ** Calls 'lua_getinfo' and collects all results in a new table. |
| 141 | ** L1 needs stack space for an optional input (function) plus | ||
| 142 | ** two optional outputs (function and line table) from function | ||
| 143 | ** 'lua_getinfo'. | ||
| 130 | */ | 144 | */ |
| 131 | static int db_getinfo (lua_State *L) { | 145 | static int db_getinfo (lua_State *L) { |
| 132 | lua_Debug ar; | 146 | lua_Debug ar; |
| 133 | int arg; | 147 | int arg; |
| 134 | lua_State *L1 = getthread(L, &arg); | 148 | lua_State *L1 = getthread(L, &arg); |
| 135 | const char *options = luaL_optstring(L, arg+2, "flnStu"); | 149 | const char *options = luaL_optstring(L, arg+2, "flnStu"); |
| 150 | checkstack(L, L1, 3); | ||
| 136 | if (lua_isfunction(L, arg + 1)) { /* info about a function? */ | 151 | if (lua_isfunction(L, arg + 1)) { /* info about a function? */ |
| 137 | options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ | 152 | options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ |
| 138 | lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ | 153 | lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ |
| @@ -190,6 +205,7 @@ static int db_getlocal (lua_State *L) { | |||
| 190 | int level = (int)luaL_checkinteger(L, arg + 1); | 205 | int level = (int)luaL_checkinteger(L, arg + 1); |
| 191 | if (!lua_getstack(L1, level, &ar)) /* out of range? */ | 206 | if (!lua_getstack(L1, level, &ar)) /* out of range? */ |
| 192 | return luaL_argerror(L, arg+1, "level out of range"); | 207 | return luaL_argerror(L, arg+1, "level out of range"); |
| 208 | checkstack(L, L1, 1); | ||
| 193 | name = lua_getlocal(L1, &ar, nvar); | 209 | name = lua_getlocal(L1, &ar, nvar); |
| 194 | if (name) { | 210 | if (name) { |
| 195 | lua_xmove(L1, L, 1); /* move local value */ | 211 | lua_xmove(L1, L, 1); /* move local value */ |
| @@ -216,6 +232,7 @@ static int db_setlocal (lua_State *L) { | |||
| 216 | return luaL_argerror(L, arg+1, "level out of range"); | 232 | return luaL_argerror(L, arg+1, "level out of range"); |
| 217 | luaL_checkany(L, arg+3); | 233 | luaL_checkany(L, arg+3); |
| 218 | lua_settop(L, arg+3); | 234 | lua_settop(L, arg+3); |
| 235 | checkstack(L, L1, 1); | ||
| 219 | lua_xmove(L, L1, 1); | 236 | lua_xmove(L, L1, 1); |
| 220 | name = lua_setlocal(L1, &ar, nvar); | 237 | name = lua_setlocal(L1, &ar, nvar); |
| 221 | if (name == NULL) | 238 | if (name == NULL) |
| @@ -350,6 +367,7 @@ static int db_sethook (lua_State *L) { | |||
| 350 | lua_pushvalue(L, -1); | 367 | lua_pushvalue(L, -1); |
| 351 | lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ | 368 | lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ |
| 352 | } | 369 | } |
| 370 | checkstack(L, L1, 1); | ||
| 353 | lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ | 371 | lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ |
| 354 | lua_pushvalue(L, arg + 1); /* value (hook function) */ | 372 | lua_pushvalue(L, arg + 1); /* value (hook function) */ |
| 355 | lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ | 373 | lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ |
| @@ -370,6 +388,7 @@ static int db_gethook (lua_State *L) { | |||
| 370 | lua_pushliteral(L, "external hook"); | 388 | lua_pushliteral(L, "external hook"); |
| 371 | else { /* hook table must exist */ | 389 | else { /* hook table must exist */ |
| 372 | lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); | 390 | lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); |
| 391 | checkstack(L, L1, 1); | ||
| 373 | lua_pushthread(L1); lua_xmove(L1, L, 1); | 392 | lua_pushthread(L1); lua_xmove(L1, L, 1); |
| 374 | lua_rawget(L, -2); /* 1st result = hooktable[L1] */ | 393 | lua_rawget(L, -2); /* 1st result = hooktable[L1] */ |
| 375 | lua_remove(L, -2); /* remove hook table */ | 394 | lua_remove(L, -2); /* remove hook table */ |
