aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lapi.c52
-rw-r--r--lapi.h14
-rw-r--r--ldebug.c1
-rw-r--r--ldo.c5
-rw-r--r--testes/api.lua3
5 files changed, 45 insertions, 30 deletions
diff --git a/lapi.c b/lapi.c
index b2b82cd7..7df63798 100644
--- a/lapi.c
+++ b/lapi.c
@@ -139,7 +139,7 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
139 int i; 139 int i;
140 if (from == to) return; 140 if (from == to) return;
141 lua_lock(to); 141 lua_lock(to);
142 api_checknelems(from, n); 142 api_checkpop(from, n);
143 api_check(from, G(from) == G(to), "moving among independent states"); 143 api_check(from, G(from) == G(to), "moving among independent states");
144 api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow"); 144 api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow");
145 from->top.p -= n; 145 from->top.p -= n;
@@ -205,7 +205,6 @@ LUA_API void lua_settop (lua_State *L, int idx) {
205 api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top"); 205 api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top");
206 diff = idx + 1; /* will "subtract" index (as it is negative) */ 206 diff = idx + 1; /* will "subtract" index (as it is negative) */
207 } 207 }
208 api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot");
209 newtop = L->top.p + diff; 208 newtop = L->top.p + diff;
210 if (diff < 0 && L->tbclist.p >= newtop) { 209 if (diff < 0 && L->tbclist.p >= newtop) {
211 lua_assert(hastocloseCfunc(ci->nresults)); 210 lua_assert(hastocloseCfunc(ci->nresults));
@@ -253,6 +252,7 @@ LUA_API void lua_rotate (lua_State *L, int idx, int n) {
253 lua_lock(L); 252 lua_lock(L);
254 t = L->top.p - 1; /* end of stack segment being rotated */ 253 t = L->top.p - 1; /* end of stack segment being rotated */
255 p = index2stack(L, idx); /* start of segment */ 254 p = index2stack(L, idx); /* start of segment */
255 api_check(L, L->tbclist.p < p, "moving a to-be-closed slot");
256 api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); 256 api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
257 m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ 257 m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */
258 reverse(L, p, m); /* reverse the prefix with length 'n' */ 258 reverse(L, p, m); /* reverse the prefix with length 'n' */
@@ -345,9 +345,9 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
345LUA_API void lua_arith (lua_State *L, int op) { 345LUA_API void lua_arith (lua_State *L, int op) {
346 lua_lock(L); 346 lua_lock(L);
347 if (op != LUA_OPUNM && op != LUA_OPBNOT) 347 if (op != LUA_OPUNM && op != LUA_OPBNOT)
348 api_checknelems(L, 2); /* all other operations expect two operands */ 348 api_checkpop(L, 2); /* all other operations expect two operands */
349 else { /* for unary operations, add fake 2nd operand */ 349 else { /* for unary operations, add fake 2nd operand */
350 api_checknelems(L, 1); 350 api_checkpop(L, 1);
351 setobjs2s(L, L->top.p, L->top.p - 1); 351 setobjs2s(L, L->top.p, L->top.p - 1);
352 api_incr_top(L); 352 api_incr_top(L);
353 } 353 }
@@ -611,17 +611,18 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
611 api_incr_top(L); 611 api_incr_top(L);
612 } 612 }
613 else { 613 else {
614 int i;
614 CClosure *cl; 615 CClosure *cl;
615 api_checknelems(L, n); 616 api_checkpop(L, n);
616 api_check(L, n <= MAXUPVAL, "upvalue index too large"); 617 api_check(L, n <= MAXUPVAL, "upvalue index too large");
617 cl = luaF_newCclosure(L, n); 618 cl = luaF_newCclosure(L, n);
618 cl->f = fn; 619 cl->f = fn;
619 L->top.p -= n; 620 for (i = 0; i < n; i++) {
620 while (n--) { 621 setobj2n(L, &cl->upvalue[i], s2v(L->top.p - n + i));
621 setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n));
622 /* does not need barrier because closure is white */ 622 /* does not need barrier because closure is white */
623 lua_assert(iswhite(cl)); 623 lua_assert(iswhite(cl));
624 } 624 }
625 L->top.p -= n;
625 setclCvalue(L, s2v(L->top.p), cl); 626 setclCvalue(L, s2v(L->top.p), cl);
626 api_incr_top(L); 627 api_incr_top(L);
627 luaC_checkGC(L); 628 luaC_checkGC(L);
@@ -701,6 +702,7 @@ LUA_API int lua_gettable (lua_State *L, int idx) {
701 int hres; 702 int hres;
702 TValue *t; 703 TValue *t;
703 lua_lock(L); 704 lua_lock(L);
705 api_checkpop(L, 1);
704 t = index2value(L, idx); 706 t = index2value(L, idx);
705 luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, hres); 707 luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, hres);
706 if (hres != HOK) 708 if (hres != HOK)
@@ -751,13 +753,13 @@ l_sinline Table *gettable (lua_State *L, int idx) {
751 753
752LUA_API int lua_rawget (lua_State *L, int idx) { 754LUA_API int lua_rawget (lua_State *L, int idx) {
753 Table *t; 755 Table *t;
754 int hres;
755 lua_lock(L); 756 lua_lock(L);
756 api_checknelems(L, 1); 757 api_checkpop(L, 1);
757 t = gettable(L, idx); 758 t = gettable(L, idx);
758 hres = luaH_get(t, s2v(L->top.p - 1), s2v(L->top.p - 1)); 759 if (luaH_get(t, s2v(L->top.p - 1), s2v(L->top.p - 1)) != HOK)
759 L->top.p--; /* remove key */ 760 setnilvalue(s2v(L->top.p - 1));
760 return finishrawget(L, hres); 761 lua_unlock(L);
762 return ttype(s2v(L->top.p - 1));
761} 763}
762 764
763 765
@@ -851,7 +853,7 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) {
851static void auxsetstr (lua_State *L, const TValue *t, const char *k) { 853static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
852 int hres; 854 int hres;
853 TString *str = luaS_new(L, k); 855 TString *str = luaS_new(L, k);
854 api_checknelems(L, 1); 856 api_checkpop(L, 1);
855 luaV_fastset(t, str, s2v(L->top.p - 1), hres, luaH_psetstr); 857 luaV_fastset(t, str, s2v(L->top.p - 1), hres, luaH_psetstr);
856 if (hres == HOK) { 858 if (hres == HOK) {
857 luaV_finishfastset(L, t, s2v(L->top.p - 1)); 859 luaV_finishfastset(L, t, s2v(L->top.p - 1));
@@ -879,7 +881,7 @@ LUA_API void lua_settable (lua_State *L, int idx) {
879 TValue *t; 881 TValue *t;
880 int hres; 882 int hres;
881 lua_lock(L); 883 lua_lock(L);
882 api_checknelems(L, 2); 884 api_checkpop(L, 2);
883 t = index2value(L, idx); 885 t = index2value(L, idx);
884 luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset); 886 luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset);
885 if (hres == HOK) { 887 if (hres == HOK) {
@@ -902,7 +904,7 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
902 TValue *t; 904 TValue *t;
903 int hres; 905 int hres;
904 lua_lock(L); 906 lua_lock(L);
905 api_checknelems(L, 1); 907 api_checkpop(L, 1);
906 t = index2value(L, idx); 908 t = index2value(L, idx);
907 luaV_fastseti(t, n, s2v(L->top.p - 1), hres); 909 luaV_fastseti(t, n, s2v(L->top.p - 1), hres);
908 if (hres == HOK) 910 if (hres == HOK)
@@ -920,7 +922,7 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
920static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { 922static void aux_rawset (lua_State *L, int idx, TValue *key, int n) {
921 Table *t; 923 Table *t;
922 lua_lock(L); 924 lua_lock(L);
923 api_checknelems(L, n); 925 api_checkpop(L, n);
924 t = gettable(L, idx); 926 t = gettable(L, idx);
925 luaH_set(L, t, key, s2v(L->top.p - 1)); 927 luaH_set(L, t, key, s2v(L->top.p - 1));
926 invalidateTMcache(t); 928 invalidateTMcache(t);
@@ -945,7 +947,7 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
945LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { 947LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
946 Table *t; 948 Table *t;
947 lua_lock(L); 949 lua_lock(L);
948 api_checknelems(L, 1); 950 api_checkpop(L, 1);
949 t = gettable(L, idx); 951 t = gettable(L, idx);
950 luaH_setint(L, t, n, s2v(L->top.p - 1)); 952 luaH_setint(L, t, n, s2v(L->top.p - 1));
951 luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); 953 luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1));
@@ -958,7 +960,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
958 TValue *obj; 960 TValue *obj;
959 Table *mt; 961 Table *mt;
960 lua_lock(L); 962 lua_lock(L);
961 api_checknelems(L, 1); 963 api_checkpop(L, 1);
962 obj = index2value(L, objindex); 964 obj = index2value(L, objindex);
963 if (ttisnil(s2v(L->top.p - 1))) 965 if (ttisnil(s2v(L->top.p - 1)))
964 mt = NULL; 966 mt = NULL;
@@ -998,7 +1000,7 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) {
998 TValue *o; 1000 TValue *o;
999 int res; 1001 int res;
1000 lua_lock(L); 1002 lua_lock(L);
1001 api_checknelems(L, 1); 1003 api_checkpop(L, 1);
1002 o = index2value(L, idx); 1004 o = index2value(L, idx);
1003 api_check(L, ttisfulluserdata(o), "full userdata expected"); 1005 api_check(L, ttisfulluserdata(o), "full userdata expected");
1004 if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) 1006 if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue)))
@@ -1031,7 +1033,7 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults,
1031 lua_lock(L); 1033 lua_lock(L);
1032 api_check(L, k == NULL || !isLua(L->ci), 1034 api_check(L, k == NULL || !isLua(L->ci),
1033 "cannot use continuations inside hooks"); 1035 "cannot use continuations inside hooks");
1034 api_checknelems(L, nargs+1); 1036 api_checkpop(L, nargs + 1);
1035 api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); 1037 api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
1036 checkresults(L, nargs, nresults); 1038 checkresults(L, nargs, nresults);
1037 func = L->top.p - (nargs+1); 1039 func = L->top.p - (nargs+1);
@@ -1072,7 +1074,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
1072 lua_lock(L); 1074 lua_lock(L);
1073 api_check(L, k == NULL || !isLua(L->ci), 1075 api_check(L, k == NULL || !isLua(L->ci),
1074 "cannot use continuations inside hooks"); 1076 "cannot use continuations inside hooks");
1075 api_checknelems(L, nargs+1); 1077 api_checkpop(L, nargs + 1);
1076 api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); 1078 api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
1077 checkresults(L, nargs, nresults); 1079 checkresults(L, nargs, nresults);
1078 if (errfunc == 0) 1080 if (errfunc == 0)
@@ -1141,7 +1143,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
1141 ptrdiff_t otop = savestack(L, L->top.p); /* original top */ 1143 ptrdiff_t otop = savestack(L, L->top.p); /* original top */
1142 TValue *f = s2v(L->top.p - 1); /* function to be dumped */ 1144 TValue *f = s2v(L->top.p - 1); /* function to be dumped */
1143 lua_lock(L); 1145 lua_lock(L);
1144 api_checknelems(L, 1); 1146 api_checkpop(L, 1);
1145 api_check(L, isLfunction(f), "Lua function expected"); 1147 api_check(L, isLfunction(f), "Lua function expected");
1146 status = luaU_dump(L, clLvalue(f)->p, writer, data, strip); 1148 status = luaU_dump(L, clLvalue(f)->p, writer, data, strip);
1147 L->top.p = restorestack(L, otop); /* restore top */ 1149 L->top.p = restorestack(L, otop); /* restore top */
@@ -1244,7 +1246,7 @@ LUA_API int lua_error (lua_State *L) {
1244 TValue *errobj; 1246 TValue *errobj;
1245 lua_lock(L); 1247 lua_lock(L);
1246 errobj = s2v(L->top.p - 1); 1248 errobj = s2v(L->top.p - 1);
1247 api_checknelems(L, 1); 1249 api_checkpop(L, 1);
1248 /* error object is the memory error message? */ 1250 /* error object is the memory error message? */
1249 if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) 1251 if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg))
1250 luaM_error(L); /* raise a memory error */ 1252 luaM_error(L); /* raise a memory error */
@@ -1259,7 +1261,7 @@ LUA_API int lua_next (lua_State *L, int idx) {
1259 Table *t; 1261 Table *t;
1260 int more; 1262 int more;
1261 lua_lock(L); 1263 lua_lock(L);
1262 api_checknelems(L, 1); 1264 api_checkpop(L, 1);
1263 t = gettable(L, idx); 1265 t = gettable(L, idx);
1264 more = luaH_next(L, t, L->top.p - 1); 1266 more = luaH_next(L, t, L->top.p - 1);
1265 if (more) 1267 if (more)
diff --git a/lapi.h b/lapi.h
index 43845648..757bf3d2 100644
--- a/lapi.h
+++ b/lapi.h
@@ -29,8 +29,18 @@
29 29
30/* Ensure the stack has at least 'n' elements */ 30/* Ensure the stack has at least 'n' elements */
31#define api_checknelems(L,n) \ 31#define api_checknelems(L,n) \
32 api_check(L, (n) < (L->top.p - L->ci->func.p), \ 32 api_check(L, (n) < (L->top.p - L->ci->func.p), \
33 "not enough elements in the stack") 33 "not enough elements in the stack")
34
35
36/* Ensure the stack has at least 'n' elements to be popped. (Some
37** functions only update a slot after checking it for popping, but that
38** is only an optimization for a pop followed by a push.)
39*/
40#define api_checkpop(L,n) \
41 api_check(L, (n) < L->top.p - L->ci->func.p && \
42 L->tbclist.p < L->top.p - (n), \
43 "not enough free elements in the stack")
34 44
35 45
36/* 46/*
diff --git a/ldebug.c b/ldebug.c
index aa3277cb..daa979af 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -245,6 +245,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
245 lua_lock(L); 245 lua_lock(L);
246 name = luaG_findlocal(L, ar->i_ci, n, &pos); 246 name = luaG_findlocal(L, ar->i_ci, n, &pos);
247 if (name) { 247 if (name) {
248 api_checkpop(L, 1);
248 setobjs2s(L, pos, L->top.p - 1); 249 setobjs2s(L, pos, L->top.p - 1);
249 L->top.p--; /* pop value */ 250 L->top.p--; /* pop value */
250 } 251 }
diff --git a/ldo.c b/ldo.c
index 05b14ec8..699a9d2a 100644
--- a/ldo.c
+++ b/ldo.c
@@ -767,6 +767,7 @@ static CallInfo *findpcall (lua_State *L) {
767** coroutine error handler and should not kill the coroutine.) 767** coroutine error handler and should not kill the coroutine.)
768*/ 768*/
769static int resume_error (lua_State *L, const char *msg, int narg) { 769static int resume_error (lua_State *L, const char *msg, int narg) {
770 api_checkpop(L, narg);
770 L->top.p -= narg; /* remove args from the stack */ 771 L->top.p -= narg; /* remove args from the stack */
771 setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */ 772 setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */
772 api_incr_top(L); 773 api_incr_top(L);
@@ -849,7 +850,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
849 return resume_error(L, "C stack overflow", nargs); 850 return resume_error(L, "C stack overflow", nargs);
850 L->nCcalls++; 851 L->nCcalls++;
851 luai_userstateresume(L, nargs); 852 luai_userstateresume(L, nargs);
852 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 853 api_checkpop(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
853 status = luaD_rawrunprotected(L, resume, &nargs); 854 status = luaD_rawrunprotected(L, resume, &nargs);
854 /* continue running after recoverable errors */ 855 /* continue running after recoverable errors */
855 status = precover(L, status); 856 status = precover(L, status);
@@ -878,7 +879,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
878 luai_userstateyield(L, nresults); 879 luai_userstateyield(L, nresults);
879 lua_lock(L); 880 lua_lock(L);
880 ci = L->ci; 881 ci = L->ci;
881 api_checknelems(L, nresults); 882 api_checkpop(L, nresults);
882 if (l_unlikely(!yieldable(L))) { 883 if (l_unlikely(!yieldable(L))) {
883 if (L != G(L)->mainthread) 884 if (L != G(L)->mainthread)
884 luaG_runerror(L, "attempt to yield across a C-call boundary"); 885 luaG_runerror(L, "attempt to yield across a C-call boundary");
diff --git a/testes/api.lua b/testes/api.lua
index eec9c0ab..dc485240 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -1193,7 +1193,8 @@ do
1193 local a, b = pcall(T.makeCfunc[[ 1193 local a, b = pcall(T.makeCfunc[[
1194 call 0 1 # create resource 1194 call 0 1 # create resource
1195 toclose -1 # mark it to be closed 1195 toclose -1 # mark it to be closed
1196 error # resource is the error object 1196 pushvalue -1 # replicate it as error object
1197 error # resource right after error object
1197 ]], newresource) 1198 ]], newresource)
1198 assert(a == false and b[1] == 11) 1199 assert(a == false and b[1] == 11)
1199 assert(#openresource == 0) -- was closed 1200 assert(#openresource == 0) -- was closed