aboutsummaryrefslogtreecommitdiff
path: root/lbaselib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-12-13 10:41:17 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-12-13 10:41:17 -0300
commit0bfc572e51d9035a615ef6e9523f736c9ffa8e57 (patch)
tree218f2bb13a873becf8fa657a296c8863f7e0e466 /lbaselib.c
parent1de95e97ef65632a88e08b6184bd9d1ceba7ec2f (diff)
downloadlua-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.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/lbaselib.c b/lbaselib.c
index 912c4cc6..1d60c9de 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -182,12 +182,20 @@ static int luaB_rawset (lua_State *L) {
182 182
183 183
184static int pushmode (lua_State *L, int oldmode) { 184static 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
191static int luaB_collectgarbage (lua_State *L) { 199static 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