diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-12-13 10:41:17 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-12-13 10:41:17 -0300 |
commit | 0bfc572e51d9035a615ef6e9523f736c9ffa8e57 (patch) | |
tree | 218f2bb13a873becf8fa657a296c8863f7e0e466 /lbaselib.c | |
parent | 1de95e97ef65632a88e08b6184bd9d1ceba7ec2f (diff) | |
download | lua-0bfc572e51d9035a615ef6e9523f736c9ffa8e57.tar.gz lua-0bfc572e51d9035a615ef6e9523f736c9ffa8e57.tar.bz2 lua-0bfc572e51d9035a615ef6e9523f736c9ffa8e57.zip |
Bug: GC is not reentrant
As the GC is not reentrant, finalizers should not be able to invoke it.
Diffstat (limited to 'lbaselib.c')
-rw-r--r-- | lbaselib.c | 19 |
1 files changed, 17 insertions, 2 deletions
@@ -182,12 +182,20 @@ static int luaB_rawset (lua_State *L) { | |||
182 | 182 | ||
183 | 183 | ||
184 | static int pushmode (lua_State *L, int oldmode) { | 184 | static int pushmode (lua_State *L, int oldmode) { |
185 | lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" | 185 | if (oldmode == -1) |
186 | : "generational"); | 186 | luaL_pushfail(L); /* invalid call to 'lua_gc' */ |
187 | else | ||
188 | lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" | ||
189 | : "generational"); | ||
187 | return 1; | 190 | return 1; |
188 | } | 191 | } |
189 | 192 | ||
190 | 193 | ||
194 | /* | ||
195 | ** check whether call to 'lua_gc' was valid (not inside a finalizer) | ||
196 | */ | ||
197 | #define checkvalres(res) { if (res == -1) break; } | ||
198 | |||
191 | static int luaB_collectgarbage (lua_State *L) { | 199 | static int luaB_collectgarbage (lua_State *L) { |
192 | static const char *const opts[] = {"stop", "restart", "collect", | 200 | static const char *const opts[] = {"stop", "restart", "collect", |
193 | "count", "step", "setpause", "setstepmul", | 201 | "count", "step", "setpause", "setstepmul", |
@@ -200,12 +208,14 @@ static int luaB_collectgarbage (lua_State *L) { | |||
200 | case LUA_GCCOUNT: { | 208 | case LUA_GCCOUNT: { |
201 | int k = lua_gc(L, o); | 209 | int k = lua_gc(L, o); |
202 | int b = lua_gc(L, LUA_GCCOUNTB); | 210 | int b = lua_gc(L, LUA_GCCOUNTB); |
211 | checkvalres(k); | ||
203 | lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024)); | 212 | lua_pushnumber(L, (lua_Number)k + ((lua_Number)b/1024)); |
204 | return 1; | 213 | return 1; |
205 | } | 214 | } |
206 | case LUA_GCSTEP: { | 215 | case LUA_GCSTEP: { |
207 | int step = (int)luaL_optinteger(L, 2, 0); | 216 | int step = (int)luaL_optinteger(L, 2, 0); |
208 | int res = lua_gc(L, o, step); | 217 | int res = lua_gc(L, o, step); |
218 | checkvalres(res); | ||
209 | lua_pushboolean(L, res); | 219 | lua_pushboolean(L, res); |
210 | return 1; | 220 | return 1; |
211 | } | 221 | } |
@@ -213,11 +223,13 @@ static int luaB_collectgarbage (lua_State *L) { | |||
213 | case LUA_GCSETSTEPMUL: { | 223 | case LUA_GCSETSTEPMUL: { |
214 | int p = (int)luaL_optinteger(L, 2, 0); | 224 | int p = (int)luaL_optinteger(L, 2, 0); |
215 | int previous = lua_gc(L, o, p); | 225 | int previous = lua_gc(L, o, p); |
226 | checkvalres(previous); | ||
216 | lua_pushinteger(L, previous); | 227 | lua_pushinteger(L, previous); |
217 | return 1; | 228 | return 1; |
218 | } | 229 | } |
219 | case LUA_GCISRUNNING: { | 230 | case LUA_GCISRUNNING: { |
220 | int res = lua_gc(L, o); | 231 | int res = lua_gc(L, o); |
232 | checkvalres(res); | ||
221 | lua_pushboolean(L, res); | 233 | lua_pushboolean(L, res); |
222 | return 1; | 234 | return 1; |
223 | } | 235 | } |
@@ -234,10 +246,13 @@ static int luaB_collectgarbage (lua_State *L) { | |||
234 | } | 246 | } |
235 | default: { | 247 | default: { |
236 | int res = lua_gc(L, o); | 248 | int res = lua_gc(L, o); |
249 | checkvalres(res); | ||
237 | lua_pushinteger(L, res); | 250 | lua_pushinteger(L, res); |
238 | return 1; | 251 | return 1; |
239 | } | 252 | } |
240 | } | 253 | } |
254 | luaL_pushfail(L); /* invalid call (inside a finalizer) */ | ||
255 | return 1; | ||
241 | } | 256 | } |
242 | 257 | ||
243 | 258 | ||