From 5c30d255c7d69f079f42f5320cc2f565dd49cb8b Mon Sep 17 00:00:00 2001 From: Dibyendu Majumdar Date: Sat, 20 Feb 2021 15:25:50 +0000 Subject: [PATCH] some improvements to type checking via XmiliaH --- src/lapi.c | 31 +++++++++++++------------------ src/ldebug.c | 29 +++++++++++++---------------- src/lfunc.c | 4 +++- src/lfunc.h | 2 +- src/ltests.c | 3 ++- src/lvm.c | 27 +++++++++++++++++++++++++++ src/lvm.h | 1 + 7 files changed, 60 insertions(+), 37 deletions(-) diff --git a/src/lapi.c b/src/lapi.c index 9eac09a..5c9e303 100644 --- a/src/lapi.c +++ b/src/lapi.c @@ -1568,8 +1568,9 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { static const char *aux_upvalue (StkId fi, int n, TValue **val, - CClosure **owner, UpVal **uv, ravitype_t *type) { + CClosure **owner, UpVal **uv, ravitype_t *type, TString **usertype) { *type = RAVI_TANY; + *usertype = NULL; switch (ttype(fi)) { case LUA_TCCL: { /* C closure */ CClosure *f = clCvalue(fi); @@ -1587,6 +1588,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, if (uv) *uv = f->upvals[n - 1]; name = p->upvalues[n-1].name; *type = p->upvalues[n - 1].ravi_type; + *usertype = p->upvalues[n - 1].usertype; return (name == NULL) ? "(*no name)" : getstr(name); } default: return NULL; /* not a closure */ @@ -1597,9 +1599,10 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; ravitype_t type; + TString *usertype; TValue *val = NULL; /* to avoid warnings */ lua_lock(L); - name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL, &type); + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL, &type, &usertype); if (name) { setobj2s(L, L->top, val); api_incr_top(L); @@ -1616,30 +1619,22 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { UpVal *uv = NULL; StkId fi; ravitype_t type; /* RAVI upvalue type will be obtained if possible */ + TString *usertype; lua_lock(L); fi = index2addr(L, funcindex); api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val, &owner, &uv, &type); + name = aux_upvalue(fi, n, &val, &owner, &uv, &type, &usertype); if (name) { /* RAVI extension ** We need to ensure that this function does ** not subvert the types of local variables */ - if ( type == RAVI_TNUMFLT - || type == RAVI_TNUMINT - || type == RAVI_TARRAYFLT - || type == RAVI_TARRAYINT) { - StkId input = L->top - 1; - int compatible = - (type == RAVI_TNUMFLT && ttisfloat(input)) - || (type == RAVI_TNUMINT && ttisinteger(input)) - || (type == RAVI_TARRAYFLT && ttisfarray(input)) - || (type == RAVI_TARRAYINT && ttisiarray(input)) - || (type == RAVI_TTABLE && ttisLtable(input)) - ; - if (!compatible) - name = NULL; - } + + StkId input = L->top - 1; + int compatible = raviV_checktype(L, input, type, usertype); + + if (!compatible) + name = NULL; } if (name) { L->top--; diff --git a/src/ldebug.c b/src/ldebug.c index 13ba22b..5c4f2d3 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -147,16 +147,17 @@ static const char *findvararg (CallInfo *ci, int n, StkId *pos) { static const char *findlocal (lua_State *L, CallInfo *ci, int n, - StkId *pos, ravitype_t *type) { + StkId *pos, ravitype_t *type, TString** usertype) { const char *name = NULL; StkId base; *type = RAVI_TANY; + *usertype = NULL; if (isLua(ci)) { if (n < 0) /* access to vararg values? */ return findvararg(ci, -n, pos); else { base = ci->u.l.base; - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci), type); + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci), type, usertype); } } else @@ -176,17 +177,18 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n, LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; ravitype_t type; + TString *usertype; lua_lock(L); swapextra(L); if (ar == NULL) { /* information about non-active function? */ if (!isLfunction(L->top - 1)) /* not a Lua function? */ name = NULL; else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0, &type); + name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0, &type, &usertype); } else { /* active function; get information through 'ar' */ StkId pos = NULL; /* to avoid warnings */ - name = findlocal(L, ar->i_ci, n, &pos, &type); + name = findlocal(L, ar->i_ci, n, &pos, &type, &usertype); if (name) { setobj2s(L, L->top, pos); api_incr_top(L); @@ -202,24 +204,18 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { StkId pos = NULL; /* to avoid warnings */ const char *name; ravitype_t type; + TString* usertype; int compatible = 1; lua_lock(L); swapextra(L); - name = findlocal(L, ar->i_ci, n, &pos, &type); + name = findlocal(L, ar->i_ci, n, &pos, &type, &usertype); if (name) { /* RAVI extension ** We need to ensure that this function does ** not subvert the types of local variables */ - if (type == RAVI_TNUMFLT || type == RAVI_TNUMINT || type == RAVI_TARRAYFLT || type == RAVI_TARRAYINT) { - StkId input = L->top - 1; - compatible = (type == RAVI_TNUMFLT && ttisfloat(input)) - || (type == RAVI_TNUMINT && ttisinteger(input)) - || (type == RAVI_TARRAYFLT && ttisfarray(input)) - || (type == RAVI_TARRAYINT && ttisiarray(input)) - || (type == RAVI_TTABLE && ttisLtable(input)) - ; - } + StkId input = L->top - 1; + int compatible = raviV_checktype(L, input, type, usertype); if (compatible) { setobjs2s(L, pos, L->top - 1); L->top--; /* pop value */ @@ -457,7 +453,8 @@ static const char *getobjname (Proto *p, int lastpc, int reg, const char **name) { int pc; ravitype_t type; - *name = luaF_getlocalname(p, reg + 1, lastpc, &type); + TString *usertype; + *name = luaF_getlocalname(p, reg + 1, lastpc, &type, &usertype); if (*name) /* is a local? */ return "local"; /* else try symbolic execution */ @@ -488,7 +485,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg, int k = GETARG_C(i); /* key index */ int t = GETARG_B(i); /* table index */ const char *vn = (op != OP_GETTABUP && op != OP_RAVI_GETTABUP_SK) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc, &type) /* t+1 is the local variable number */ + ? luaF_getlocalname(p, t + 1, pc, &type, &usertype) /* t+1 is the local variable number */ : upvalname(p, t); kname(p, pc, k, name); return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; diff --git a/src/lfunc.c b/src/lfunc.c index 09db3d9..c8f817e 100644 --- a/src/lfunc.c +++ b/src/lfunc.c @@ -243,7 +243,7 @@ void luaF_freeproto (lua_State *L, Proto *f) { ** Returns NULL if not found. ** RAVI extension - also return the known type if any */ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravitype_t *type) { +const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravitype_t *type, TString **usertype) { int i; for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { if (pc < f->locvars[i].endpc) { /* is variable active? */ @@ -252,11 +252,13 @@ const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravityp if (f->locvars[i].varname == NULL) break; *type = f->locvars[i].ravi_type; + *usertype = f->locvars[i].usertype; return getstr(f->locvars[i].varname); } } } *type = RAVI_TANY; + *usertype = NULL; return NULL; /* not found */ } diff --git a/src/lfunc.h b/src/lfunc.h index 21f1aa2..778caff 100644 --- a/src/lfunc.h +++ b/src/lfunc.h @@ -57,7 +57,7 @@ LUAI_FUNC void luaF_close (lua_State *L, StkId level); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); /* The additional type argument is a Ravi extension */ LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc, ravitype_t* type); + int pc, ravitype_t* type, TString **usertype); #endif diff --git a/src/ltests.c b/src/ltests.c index 174855e..188e43f 100644 --- a/src/ltests.c +++ b/src/ltests.c @@ -645,10 +645,11 @@ static int listlocals (lua_State *L) { int i = 0; const char *name; ravitype_t tt; + TString *usertype; luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected"); p = getproto(obj_at(L, 1)); - while ((name = luaF_getlocalname(p, ++i, pc, &tt)) != NULL) + while ((name = luaF_getlocalname(p, ++i, pc, &tt, &usertype)) != NULL) lua_pushstring(L, name); return i-1; } diff --git a/src/lvm.c b/src/lvm.c index 80e9894..868b1c4 100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -1204,6 +1204,33 @@ void luaV_finishOp (lua_State *L) { if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ Protect(luaV_finishset(L,t,k,v,slot)); } +int raviV_checktype(lua_State *L, TValue *input, ravitype_t type, TString *usertype) { + if (type == RAVI_TANY) + return 1; + if (type == RAVI_TNIL && ttisnil(input)) + return 1; + if (type == RAVI_TBOOLEAN && ttisboolean(input)) + return 1; + if (type == RAVI_TNUMINT && ttisinteger(input)) + return 1; + if (type == RAVI_TNUMFLT && ttisfloat(input)) + return 1; + if (type == RAVI_TARRAYINT && ttisiarray(input)) + return 1; + if (type == RAVI_TARRAYFLT && ttisfarray(input)) + return 1; + if (type == RAVI_TTABLE && ttisLtable(input)) + return 1; + if (type == RAVI_TSTRING && ttisstring(input)) + return 1; + if (type == RAVI_TFUNCTION && ttisclosure(input)) + return 1; + if (type == RAVI_TUSERDATA) { + if (raviV_check_usertype(L, usertype, input)) + return 1; + } + return 0; +} int raviV_check_usertype(lua_State *L, TString *name, const TValue *o) { diff --git a/src/lvm.h b/src/lvm.h index bf2bf6c..111211e 100644 --- a/src/lvm.h +++ b/src/lvm.h @@ -172,6 +172,7 @@ LUAI_FUNC void raviV_settable_sskey(lua_State *L, const TValue *t, TValue *key, LUAI_FUNC void raviV_gettable_i(lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void raviV_settable_i(lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void raviV_op_totype(lua_State *L, TValue *ra, TValue *rb); +LUAI_FUNC int raviV_checktype(lua_State *L, TValue *input, ravitype_t type, TString *usertype); LUAI_FUNC int raviV_check_usertype(lua_State *L, TString *name, const TValue *o); #ifdef RAVI_DEFER_STATEMENT LUAI_FUNC void raviV_op_defer(lua_State *L, TValue *ra);