Improve assertions.

This commit is contained in:
Mike Pall
2020-06-13 00:52:54 +02:00
parent 8b55054473
commit 8ae5170cdc
71 changed files with 1363 additions and 927 deletions

View File

@@ -28,8 +28,8 @@
/* -- Common helper functions --------------------------------------------- */
#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
#define api_checkvalidindex(L, i) api_check(L, (i) != niltv(L))
#define lj_checkapi_slot(idx) \
lj_checkapi((idx) <= (L->top - L->base), "stack slot %d out of range", (idx))
static TValue *index2adr(lua_State *L, int idx)
{
@@ -37,7 +37,8 @@ static TValue *index2adr(lua_State *L, int idx)
TValue *o = L->base + (idx - 1);
return o < L->top ? o : niltv(L);
} else if (idx > LUA_REGISTRYINDEX) {
api_check(L, idx != 0 && -idx <= L->top - L->base);
lj_checkapi(idx != 0 && -idx <= L->top - L->base,
"bad stack slot %d", idx);
return L->top + idx;
} else if (idx == LUA_GLOBALSINDEX) {
TValue *o = &G(L)->tmptv;
@@ -47,7 +48,8 @@ static TValue *index2adr(lua_State *L, int idx)
return registry(L);
} else {
GCfunc *fn = curr_func(L);
api_check(L, fn->c.gct == ~LJ_TFUNC && !isluafunc(fn));
lj_checkapi(fn->c.gct == ~LJ_TFUNC && !isluafunc(fn),
"calling frame is not a C function");
if (idx == LUA_ENVIRONINDEX) {
TValue *o = &G(L)->tmptv;
settabV(L, o, tabref(fn->c.env));
@@ -59,13 +61,27 @@ static TValue *index2adr(lua_State *L, int idx)
}
}
static TValue *stkindex2adr(lua_State *L, int idx)
static LJ_AINLINE TValue *index2adr_check(lua_State *L, int idx)
{
TValue *o = index2adr(L, idx);
lj_checkapi(o != niltv(L), "invalid stack slot %d", idx);
return o;
}
static TValue *index2adr_stack(lua_State *L, int idx)
{
if (idx > 0) {
TValue *o = L->base + (idx - 1);
if (o < L->top) {
return o;
} else {
lj_checkapi(0, "invalid stack slot %d", idx);
return niltv(L);
}
return o < L->top ? o : niltv(L);
} else {
api_check(L, idx != 0 && -idx <= L->top - L->base);
lj_checkapi(idx != 0 && -idx <= L->top - L->base,
"invalid stack slot %d", idx);
return L->top + idx;
}
}
@@ -99,17 +115,17 @@ LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
lj_err_callerv(L, LJ_ERR_STKOVM, msg);
}
LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
LUA_API void lua_xmove(lua_State *L, lua_State *to, int n)
{
TValue *f, *t;
if (from == to) return;
api_checknelems(from, n);
api_check(from, G(from) == G(to));
if (L == to) return;
lj_checkapi_slot(n);
lj_checkapi(G(L) == G(to), "move across global states");
lj_state_checkstack(to, (MSize)n);
f = from->top;
f = L->top;
t = to->top = to->top + n;
while (--n >= 0) copyTV(to, --t, --f);
from->top = f;
L->top = f;
}
LUA_API const lua_Number *lua_version(lua_State *L)
@@ -129,7 +145,7 @@ LUA_API int lua_gettop(lua_State *L)
LUA_API void lua_settop(lua_State *L, int idx)
{
if (idx >= 0) {
api_check(L, idx <= tvref(L->maxstack) - L->base);
lj_checkapi(idx <= tvref(L->maxstack) - L->base, "bad stack slot %d", idx);
if (L->base + idx > L->top) {
if (L->base + idx >= tvref(L->maxstack))
lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base));
@@ -138,23 +154,21 @@ LUA_API void lua_settop(lua_State *L, int idx)
L->top = L->base + idx;
}
} else {
api_check(L, -(idx+1) <= (L->top - L->base));
lj_checkapi(-(idx+1) <= (L->top - L->base), "bad stack slot %d", idx);
L->top += idx+1; /* Shrinks top (idx < 0). */
}
}
LUA_API void lua_remove(lua_State *L, int idx)
{
TValue *p = stkindex2adr(L, idx);
api_checkvalidindex(L, p);
TValue *p = index2adr_stack(L, idx);
while (++p < L->top) copyTV(L, p-1, p);
L->top--;
}
LUA_API void lua_insert(lua_State *L, int idx)
{
TValue *q, *p = stkindex2adr(L, idx);
api_checkvalidindex(L, p);
TValue *q, *p = index2adr_stack(L, idx);
for (q = L->top; q > p; q--) copyTV(L, q, q-1);
copyTV(L, p, L->top);
}
@@ -162,19 +176,18 @@ LUA_API void lua_insert(lua_State *L, int idx)
static void copy_slot(lua_State *L, TValue *f, int idx)
{
if (idx == LUA_GLOBALSINDEX) {
api_check(L, tvistab(f));
lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
/* NOBARRIER: A thread (i.e. L) is never black. */
setgcref(L->env, obj2gco(tabV(f)));
} else if (idx == LUA_ENVIRONINDEX) {
GCfunc *fn = curr_func(L);
if (fn->c.gct != ~LJ_TFUNC)
lj_err_msg(L, LJ_ERR_NOENV);
api_check(L, tvistab(f));
lj_checkapi(tvistab(f), "stack slot %d is not a table", idx);
setgcref(fn->c.env, obj2gco(tabV(f)));
lj_gc_barrier(L, fn, f);
} else {
TValue *o = index2adr(L, idx);
api_checkvalidindex(L, o);
TValue *o = index2adr_check(L, idx);
copyTV(L, o, f);
if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */
lj_gc_barrier(L, curr_func(L), f);
@@ -183,7 +196,7 @@ static void copy_slot(lua_State *L, TValue *f, int idx)
LUA_API void lua_replace(lua_State *L, int idx)
{
api_checknelems(L, 1);
lj_checkapi_slot(1);
copy_slot(L, L->top - 1, idx);
L->top--;
}
@@ -219,7 +232,7 @@ LUA_API int lua_type(lua_State *L, int idx)
#else
int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u);
#endif
lua_assert(tt != LUA_TNIL || tvisnil(o));
lj_assertL(tt != LUA_TNIL || tvisnil(o), "bad tag conversion");
return tt;
}
}
@@ -677,14 +690,14 @@ LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n)
{
GCfunc *fn;
lj_gc_check(L);
api_checknelems(L, n);
lj_checkapi_slot(n);
fn = lj_func_newC(L, (MSize)n, getcurrenv(L));
fn->c.f = f;
L->top -= n;
while (n--)
copyTV(L, &fn->c.upvalue[n], L->top+n);
setfuncV(L, L->top, fn);
lua_assert(iswhite(obj2gco(fn)));
lj_assertL(iswhite(obj2gco(fn)), "new GC object is not white");
incr_top(L);
}
@@ -754,7 +767,7 @@ LUA_API void *lua_newuserdata(lua_State *L, size_t size)
LUA_API void lua_concat(lua_State *L, int n)
{
api_checknelems(L, n);
lj_checkapi_slot(n);
if (n >= 2) {
n--;
do {
@@ -780,9 +793,8 @@ LUA_API void lua_concat(lua_State *L, int n)
LUA_API void lua_gettable(lua_State *L, int idx)
{
cTValue *v, *t = index2adr(L, idx);
api_checkvalidindex(L, t);
v = lj_meta_tget(L, t, L->top-1);
cTValue *t = index2adr_check(L, idx);
cTValue *v = lj_meta_tget(L, t, L->top-1);
if (v == NULL) {
L->top += 2;
lj_vm_call(L, L->top-2, 1+1);
@@ -794,9 +806,8 @@ LUA_API void lua_gettable(lua_State *L, int idx)
LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
{
cTValue *v, *t = index2adr(L, idx);
cTValue *v, *t = index2adr_check(L, idx);
TValue key;
api_checkvalidindex(L, t);
setstrV(L, &key, lj_str_newz(L, k));
v = lj_meta_tget(L, t, &key);
if (v == NULL) {
@@ -812,14 +823,14 @@ LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
LUA_API void lua_rawget(lua_State *L, int idx)
{
cTValue *t = index2adr(L, idx);
api_check(L, tvistab(t));
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1));
}
LUA_API void lua_rawgeti(lua_State *L, int idx, int n)
{
cTValue *v, *t = index2adr(L, idx);
api_check(L, tvistab(t));
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
v = lj_tab_getint(tabV(t), n);
if (v) {
copyTV(L, L->top, v);
@@ -861,8 +872,7 @@ LUALIB_API int luaL_getmetafield(lua_State *L, int idx, const char *field)
LUA_API void lua_getfenv(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
api_checkvalidindex(L, o);
cTValue *o = index2adr_check(L, idx);
if (tvisfunc(o)) {
settabV(L, L->top, tabref(funcV(o)->c.env));
} else if (tvisudata(o)) {
@@ -879,7 +889,7 @@ LUA_API int lua_next(lua_State *L, int idx)
{
cTValue *t = index2adr(L, idx);
int more;
api_check(L, tvistab(t));
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
more = lj_tab_next(L, tabV(t), L->top-1);
if (more) {
incr_top(L); /* Return new key and value slot. */
@@ -905,7 +915,7 @@ LUA_API void *lua_upvalueid(lua_State *L, int idx, int n)
{
GCfunc *fn = funcV(index2adr(L, idx));
n--;
api_check(L, (uint32_t)n < fn->l.nupvalues);
lj_checkapi((uint32_t)n < fn->l.nupvalues, "bad upvalue %d", n);
return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
(void *)&fn->c.upvalue[n];
}
@@ -915,8 +925,10 @@ LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2)
GCfunc *fn1 = funcV(index2adr(L, idx1));
GCfunc *fn2 = funcV(index2adr(L, idx2));
n1--; n2--;
api_check(L, isluafunc(fn1) && (uint32_t)n1 < fn1->l.nupvalues);
api_check(L, isluafunc(fn2) && (uint32_t)n2 < fn2->l.nupvalues);
lj_checkapi(isluafunc(fn1), "stack slot %d is not a Lua function", idx1);
lj_checkapi(isluafunc(fn2), "stack slot %d is not a Lua function", idx2);
lj_checkapi((uint32_t)n1 < fn1->l.nupvalues, "bad upvalue %d", n1+1);
lj_checkapi((uint32_t)n2 < fn2->l.nupvalues, "bad upvalue %d", n2+1);
setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]);
lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1]));
}
@@ -945,9 +957,8 @@ LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
LUA_API void lua_settable(lua_State *L, int idx)
{
TValue *o;
cTValue *t = index2adr(L, idx);
api_checknelems(L, 2);
api_checkvalidindex(L, t);
cTValue *t = index2adr_check(L, idx);
lj_checkapi_slot(2);
o = lj_meta_tset(L, t, L->top-2);
if (o) {
/* NOBARRIER: lj_meta_tset ensures the table is not black. */
@@ -966,9 +977,8 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
{
TValue *o;
TValue key;
cTValue *t = index2adr(L, idx);
api_checknelems(L, 1);
api_checkvalidindex(L, t);
cTValue *t = index2adr_check(L, idx);
lj_checkapi_slot(1);
setstrV(L, &key, lj_str_newz(L, k));
o = lj_meta_tset(L, t, &key);
if (o) {
@@ -987,7 +997,7 @@ LUA_API void lua_rawset(lua_State *L, int idx)
{
GCtab *t = tabV(index2adr(L, idx));
TValue *dst, *key;
api_checknelems(L, 2);
lj_checkapi_slot(2);
key = L->top-2;
dst = lj_tab_set(L, t, key);
copyTV(L, dst, key+1);
@@ -999,7 +1009,7 @@ LUA_API void lua_rawseti(lua_State *L, int idx, int n)
{
GCtab *t = tabV(index2adr(L, idx));
TValue *dst, *src;
api_checknelems(L, 1);
lj_checkapi_slot(1);
dst = lj_tab_setint(L, t, n);
src = L->top-1;
copyTV(L, dst, src);
@@ -1011,13 +1021,12 @@ LUA_API int lua_setmetatable(lua_State *L, int idx)
{
global_State *g;
GCtab *mt;
cTValue *o = index2adr(L, idx);
api_checknelems(L, 1);
api_checkvalidindex(L, o);
cTValue *o = index2adr_check(L, idx);
lj_checkapi_slot(1);
if (tvisnil(L->top-1)) {
mt = NULL;
} else {
api_check(L, tvistab(L->top-1));
lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
mt = tabV(L->top-1);
}
g = G(L);
@@ -1054,11 +1063,10 @@ LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
LUA_API int lua_setfenv(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
cTValue *o = index2adr_check(L, idx);
GCtab *t;
api_checknelems(L, 1);
api_checkvalidindex(L, o);
api_check(L, tvistab(L->top-1));
lj_checkapi_slot(1);
lj_checkapi(tvistab(L->top-1), "top stack slot is not a table");
t = tabV(L->top-1);
if (tvisfunc(o)) {
setgcref(funcV(o)->c.env, obj2gco(t));
@@ -1081,7 +1089,7 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
TValue *val;
GCobj *o;
const char *name;
api_checknelems(L, 1);
lj_checkapi_slot(1);
name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o);
if (name) {
L->top--;
@@ -1108,8 +1116,9 @@ static TValue *api_call_base(lua_State *L, int nargs)
LUA_API void lua_call(lua_State *L, int nargs, int nresults)
{
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
api_checknelems(L, nargs+1);
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
"thread called in wrong state %d", L->status);
lj_checkapi_slot(nargs+1);
lj_vm_call(L, api_call_base(L, nargs), nresults+1);
}
@@ -1119,13 +1128,13 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
uint8_t oldh = hook_save(g);
ptrdiff_t ef;
int status;
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
api_checknelems(L, nargs+1);
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
"thread called in wrong state %d", L->status);
lj_checkapi_slot(nargs+1);
if (errfunc == 0) {
ef = 0;
} else {
cTValue *o = stkindex2adr(L, errfunc);
api_checkvalidindex(L, o);
cTValue *o = index2adr_stack(L, errfunc);
ef = savestack(L, o);
}
status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
@@ -1151,7 +1160,8 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
global_State *g = G(L);
uint8_t oldh = hook_save(g);
int status;
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
"thread called in wrong state %d", L->status);
status = lj_vm_cpcall(L, func, ud, cpcall);
if (status) hook_restore(g, oldh);
return status;