diff options
Diffstat (limited to 'lapi.c')
| -rw-r--r-- | lapi.c | 45 |
1 files changed, 25 insertions, 20 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.272 2017/11/01 18:20:48 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.273 2017/11/02 11:28:56 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "lprefix.h" | 10 | #include "lprefix.h" |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | #include <limits.h> | ||
| 13 | #include <stdarg.h> | 14 | #include <stdarg.h> |
| 14 | #include <string.h> | 15 | #include <string.h> |
| 15 | 16 | ||
| @@ -60,12 +61,12 @@ const char lua_ident[] = | |||
| 60 | static TValue *index2value (lua_State *L, int idx) { | 61 | static TValue *index2value (lua_State *L, int idx) { |
| 61 | if (idx > 0) { | 62 | if (idx > 0) { |
| 62 | StkId o = L->func + idx; | 63 | StkId o = L->func + idx; |
| 63 | api_check(L, idx <= L->ci->top - (L->func + 1), "unacceptable index"); | 64 | api_check(L, idx < L->func->stkci.framesize, "unacceptable index"); |
| 64 | if (o >= L->top) return NONVALIDVALUE; | 65 | if (o >= L->top) return NONVALIDVALUE; |
| 65 | else return s2v(o); | 66 | else return s2v(o); |
| 66 | } | 67 | } |
| 67 | else if (!ispseudo(idx)) { /* negative index */ | 68 | else if (!ispseudo(idx)) { /* negative index */ |
| 68 | api_check(L, idx != 0 && -idx <= L->top - (L->func + 1), "invalid index"); | 69 | api_check(L, idx != 0 && -idx < L->func->stkci.framesize, "invalid index"); |
| 69 | return s2v(L->top + idx); | 70 | return s2v(L->top + idx); |
| 70 | } | 71 | } |
| 71 | else if (idx == LUA_REGISTRYINDEX) | 72 | else if (idx == LUA_REGISTRYINDEX) |
| @@ -109,10 +110,12 @@ static void growstack (lua_State *L, void *ud) { | |||
| 109 | 110 | ||
| 110 | LUA_API int lua_checkstack (lua_State *L, int n) { | 111 | LUA_API int lua_checkstack (lua_State *L, int n) { |
| 111 | int res; | 112 | int res; |
| 112 | CallInfo *ci = L->ci; | 113 | int frameuse = L->top - L->func; |
| 113 | lua_lock(L); | 114 | lua_lock(L); |
| 114 | api_check(L, n >= 0, "negative 'n'"); | 115 | api_check(L, n >= 0, "negative 'n'"); |
| 115 | if (L->stack_last - L->top > n) /* stack large enough? */ | 116 | if (n >= USHRT_MAX - frameuse) |
| 117 | res = 0; /* frame size overflow */ | ||
| 118 | else if (L->stack_last - L->top > n) /* stack large enough? */ | ||
| 116 | res = 1; /* yes; check is OK */ | 119 | res = 1; /* yes; check is OK */ |
| 117 | else { /* no; need to grow stack */ | 120 | else { /* no; need to grow stack */ |
| 118 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; | 121 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; |
| @@ -121,8 +124,8 @@ LUA_API int lua_checkstack (lua_State *L, int n) { | |||
| 121 | else /* try to grow stack */ | 124 | else /* try to grow stack */ |
| 122 | res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); | 125 | res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); |
| 123 | } | 126 | } |
| 124 | if (res && ci->top < L->top + n) | 127 | if (res && L->func->stkci.framesize < frameuse + n) |
| 125 | ci->top = L->top + n; /* adjust frame top */ | 128 | L->func->stkci.framesize = frameuse + n; /* adjust frame size */ |
| 126 | lua_unlock(L); | 129 | lua_unlock(L); |
| 127 | return res; | 130 | return res; |
| 128 | } | 131 | } |
| @@ -134,7 +137,7 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |||
| 134 | lua_lock(to); | 137 | lua_lock(to); |
| 135 | api_checknelems(from, n); | 138 | api_checknelems(from, n); |
| 136 | api_check(from, G(from) == G(to), "moving among independent states"); | 139 | api_check(from, G(from) == G(to), "moving among independent states"); |
| 137 | api_check(from, to->ci->top - to->top >= n, "stack overflow"); | 140 | api_check(from, functop(to->func) - to->top >= n, "stack overflow"); |
| 138 | from->top -= n; | 141 | from->top -= n; |
| 139 | for (i = 0; i < n; i++) { | 142 | for (i = 0; i < n; i++) { |
| 140 | setobjs2s(to, to->top, from->top + i); | 143 | setobjs2s(to, to->top, from->top + i); |
| @@ -929,15 +932,16 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { | |||
| 929 | 932 | ||
| 930 | 933 | ||
| 931 | #define checkresults(L,na,nr) \ | 934 | #define checkresults(L,na,nr) \ |
| 932 | api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ | 935 | api_check(L, (nr) == LUA_MULTRET || \ |
| 933 | "results from function overflow current stack size") | 936 | (functop(L->func) - L->top >= (nr) - (na)), \ |
| 937 | "results from function overflow current frame size") | ||
| 934 | 938 | ||
| 935 | 939 | ||
| 936 | LUA_API void lua_callk (lua_State *L, int nargs, int nresults, | 940 | LUA_API void lua_callk (lua_State *L, int nargs, int nresults, |
| 937 | lua_KContext ctx, lua_KFunction k) { | 941 | lua_KContext ctx, lua_KFunction k) { |
| 938 | StkId func; | 942 | StkId func; |
| 939 | lua_lock(L); | 943 | lua_lock(L); |
| 940 | api_check(L, k == NULL || !isLua(L->ci), | 944 | api_check(L, k == NULL || !isLua(L->func), |
| 941 | "cannot use continuations inside hooks"); | 945 | "cannot use continuations inside hooks"); |
| 942 | api_checknelems(L, nargs+1); | 946 | api_checknelems(L, nargs+1); |
| 943 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | 947 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); |
| @@ -976,36 +980,37 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, | |||
| 976 | lua_KContext ctx, lua_KFunction k) { | 980 | lua_KContext ctx, lua_KFunction k) { |
| 977 | struct CallS c; | 981 | struct CallS c; |
| 978 | int status; | 982 | int status; |
| 979 | ptrdiff_t func; | 983 | ptrdiff_t efunc; |
| 980 | lua_lock(L); | 984 | lua_lock(L); |
| 981 | api_check(L, k == NULL || !isLua(L->ci), | 985 | api_check(L, k == NULL || !isLua(L->func), |
| 982 | "cannot use continuations inside hooks"); | 986 | "cannot use continuations inside hooks"); |
| 983 | api_checknelems(L, nargs+1); | 987 | api_checknelems(L, nargs+1); |
| 984 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | 988 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); |
| 985 | checkresults(L, nargs, nresults); | 989 | checkresults(L, nargs, nresults); |
| 986 | if (errfunc == 0) | 990 | if (errfunc == 0) |
| 987 | func = 0; | 991 | efunc = 0; |
| 988 | else { | 992 | else { |
| 989 | StkId o = index2stack(L, errfunc); | 993 | StkId o = index2stack(L, errfunc); |
| 990 | func = savestack(L, o); | 994 | efunc = savestack(L, o); |
| 991 | } | 995 | } |
| 992 | c.func = L->top - (nargs+1); /* function to be called */ | 996 | c.func = L->top - (nargs+1); /* function to be called */ |
| 993 | if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ | 997 | if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ |
| 994 | c.nresults = nresults; /* do a 'conventional' protected call */ | 998 | c.nresults = nresults; /* do a 'conventional' protected call */ |
| 995 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); | 999 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), efunc); |
| 996 | } | 1000 | } |
| 997 | else { /* prepare continuation (call is already protected by 'resume') */ | 1001 | else { /* prepare continuation (call is already protected by 'resume') */ |
| 998 | CallInfo *ci = L->ci; | 1002 | CallInfo *ci = L->ci; |
| 1003 | StkId func = L->func; | ||
| 999 | ci->u.c.k = k; /* save continuation */ | 1004 | ci->u.c.k = k; /* save continuation */ |
| 1000 | ci->u.c.ctx = ctx; /* save context */ | 1005 | ci->u.c.ctx = ctx; /* save context */ |
| 1001 | /* save information for error recovery */ | 1006 | /* save information for error recovery */ |
| 1002 | ci->u2.funcidx = savestack(L, c.func); | 1007 | ci->u2.funcidx = savestack(L, c.func); |
| 1003 | ci->u.c.old_errfunc = L->errfunc; | 1008 | ci->u.c.old_errfunc = L->errfunc; |
| 1004 | L->errfunc = func; | 1009 | L->errfunc = efunc; |
| 1005 | setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ | 1010 | setoah(callstatus(func), L->allowhook); /* save value of 'allowhook' */ |
| 1006 | ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ | 1011 | callstatus(func) |= CIST_YPCALL; /* function can do error recovery */ |
| 1007 | luaD_call(L, c.func, nresults); /* do the call */ | 1012 | luaD_call(L, c.func, nresults); /* do the call */ |
| 1008 | ci->callstatus &= ~CIST_YPCALL; | 1013 | callstatus(func) &= ~CIST_YPCALL; |
| 1009 | L->errfunc = ci->u.c.old_errfunc; | 1014 | L->errfunc = ci->u.c.old_errfunc; |
| 1010 | status = LUA_OK; /* if it is here, there were no errors */ | 1015 | status = LUA_OK; /* if it is here, there were no errors */ |
| 1011 | } | 1016 | } |
