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 /ldblib.c | |
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
Diffstat (limited to 'ldblib.c')
-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 */ |