diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-01-04 13:09:47 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-01-04 13:09:47 -0200 |
| commit | 4ace93ca6502dd1da38d5c06fa099d229e791ba8 (patch) | |
| tree | 34f95ef56aecb56ae1db5e8b843b6e9bd2cbae51 /lfunc.c | |
| parent | c6f7181e910b6b2ff1346b5486a31be87b1da5af (diff) | |
| download | lua-4ace93ca6502dd1da38d5c06fa099d229e791ba8.tar.gz lua-4ace93ca6502dd1da38d5c06fa099d229e791ba8.tar.bz2 lua-4ace93ca6502dd1da38d5c06fa099d229e791ba8.zip | |
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.
Diffstat (limited to 'lfunc.c')
| -rw-r--r-- | lfunc.c | 24 |
1 files changed, 10 insertions, 14 deletions
| @@ -100,28 +100,23 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
| 100 | 100 | ||
| 101 | static void callclose (lua_State *L, void *ud) { | 101 | static void callclose (lua_State *L, void *ud) { |
| 102 | UNUSED(ud); | 102 | UNUSED(ud); |
| 103 | luaD_callnoyield(L, L->top - 2, 0); | 103 | luaD_callnoyield(L, L->top - 3, 0); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | 106 | ||
| 107 | /* | 107 | /* |
| 108 | ** Prepare closing method plus its argument for object 'obj' with | 108 | ** Prepare closing method plus its arguments for object 'obj' with |
| 109 | ** error message 'err'. (This function assumes EXTRA_STACK.) | 109 | ** error message 'err'. (This function assumes EXTRA_STACK.) |
| 110 | */ | 110 | */ |
| 111 | static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) { | 111 | static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) { |
| 112 | StkId top = L->top; | 112 | StkId top = L->top; |
| 113 | if (ttisfunction(obj)) { /* object to-be-closed is a function? */ | 113 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); |
| 114 | setobj2s(L, top, obj); /* push function */ | 114 | if (ttisnil(tm)) /* no metamethod? */ |
| 115 | setobj2s(L, top + 1, err); /* push error msg. as argument */ | 115 | return 0; /* nothing to call */ |
| 116 | } | 116 | setobj2s(L, top, tm); /* will call metamethod... */ |
| 117 | else { /* try '__close' metamethod */ | 117 | setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ |
| 118 | const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); | 118 | setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ |
| 119 | if (ttisnil(tm)) /* no metamethod? */ | 119 | L->top = top + 3; /* add function and arguments */ |
| 120 | return 0; /* nothing to call */ | ||
| 121 | setobj2s(L, top, tm); /* will call metamethod... */ | ||
| 122 | setobj2s(L, top + 1, obj); /* with 'self' as the argument */ | ||
| 123 | } | ||
| 124 | L->top = top + 2; /* add function and argument */ | ||
| 125 | return 1; | 120 | return 1; |
| 126 | } | 121 | } |
| 127 | 122 | ||
| @@ -156,6 +151,7 @@ static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) { | |||
| 156 | if (newstatus != LUA_OK) /* another error when closing? */ | 151 | if (newstatus != LUA_OK) /* another error when closing? */ |
| 157 | status = newstatus; /* this will be the new error */ | 152 | status = newstatus; /* this will be the new error */ |
| 158 | } | 153 | } |
| 154 | /* else no metamethod; ignore this case and keep original error */ | ||
| 159 | } | 155 | } |
| 160 | return status; | 156 | return status; |
| 161 | } | 157 | } |
