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) |
