From 4ace93ca6502dd1da38d5c06fa099d229e791ba8 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 4 Jan 2019 13:09:47 -0200 Subject: No more to-be-closed functions To-be-closed variables must contain objects with '__toclose' metamethods (or nil). Functions were removed for several reasons: * Functions interact badly with sandboxes. If a sandbox raises an error to interrupt a script, a to-be-closed function still can hijack control and continue running arbitrary sandboxed code. * Functions interact badly with coroutines. If a coroutine yields and is never resumed again, its to-be-closed functions will never run. To-be-closed objects, on the other hand, will still be closed, provided they have appropriate finalizers. * If you really need a function, it is easy to create a dummy object to run that function in its '__toclose' metamethod. This comit also adds closing of variables in case of panic. --- lfunc.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'lfunc.c') diff --git a/lfunc.c b/lfunc.c index bdf3cd25..362b798c 100644 --- a/lfunc.c +++ b/lfunc.c @@ -100,28 +100,23 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { static void callclose (lua_State *L, void *ud) { UNUSED(ud); - luaD_callnoyield(L, L->top - 2, 0); + luaD_callnoyield(L, L->top - 3, 0); } /* -** Prepare closing method plus its argument for object 'obj' with +** Prepare closing method plus its arguments for object 'obj' with ** error message 'err'. (This function assumes EXTRA_STACK.) */ static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) { StkId top = L->top; - if (ttisfunction(obj)) { /* object to-be-closed is a function? */ - setobj2s(L, top, obj); /* push function */ - setobj2s(L, top + 1, err); /* push error msg. as argument */ - } - else { /* try '__close' metamethod */ - const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); - if (ttisnil(tm)) /* no metamethod? */ - return 0; /* nothing to call */ - setobj2s(L, top, tm); /* will call metamethod... */ - setobj2s(L, top + 1, obj); /* with 'self' as the argument */ - } - L->top = top + 2; /* add function and argument */ + const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); + if (ttisnil(tm)) /* no metamethod? */ + return 0; /* nothing to call */ + setobj2s(L, top, tm); /* will call metamethod... */ + setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ + setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ + L->top = top + 3; /* add function and arguments */ return 1; } @@ -156,6 +151,7 @@ static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) { if (newstatus != LUA_OK) /* another error when closing? */ status = newstatus; /* this will be the new error */ } + /* else no metamethod; ignore this case and keep original error */ } return status; } -- cgit v1.2.3-55-g6feb