diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-03-11 14:05:06 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-03-11 14:05:06 -0300 |
commit | 65b07dd53d7938a60112fc4473f5cad3473e3534 (patch) | |
tree | 469c75dba3b194c494b6ad6a30ca44e7e8354ef5 /lapi.c | |
parent | 7237eb3f1c480d6bc7fe2832ddd36f2137fb69d9 (diff) | |
download | lua-65b07dd53d7938a60112fc4473f5cad3473e3534.tar.gz lua-65b07dd53d7938a60112fc4473f5cad3473e3534.tar.bz2 lua-65b07dd53d7938a60112fc4473f5cad3473e3534.zip |
API asserts for illegal pops of to-be-closed variables
Diffstat (limited to 'lapi.c')
-rw-r--r-- | lapi.c | 52 |
1 files changed, 27 insertions, 25 deletions
@@ -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) { | |||
345 | LUA_API void lua_arith (lua_State *L, int op) { | 345 | LUA_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 | ||
752 | LUA_API int lua_rawget (lua_State *L, int idx) { | 754 | LUA_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) { | |||
851 | static void auxsetstr (lua_State *L, const TValue *t, const char *k) { | 853 | static 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) { | |||
920 | static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { | 922 | static 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) { | |||
945 | LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { | 947 | LUA_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) |