first version of code verification

This commit is contained in:
Roberto Ierusalimschy 2001-02-09 16:37:33 -02:00
parent b6ce590433
commit c81404cae5
3 changed files with 129 additions and 49 deletions

163
ldebug.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 1.59 2001/02/02 15:13:05 roberto Exp roberto $ ** $Id: ldebug.c,v 1.60 2001/02/07 18:13:49 roberto Exp roberto $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -321,12 +321,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
*/ */
static int pushpc (int *stack, int pc, int top, int n) { #define check(x) if (!(x)) return 0;
while (n--) #define checkjump(pt, pc) check(0 <= (pc) && (pc) < (pt)->sizecode)
stack[top++] = pc-1;
return top;
}
static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) { static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) {
int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */
@ -335,78 +331,159 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) {
int pc = 0; int pc = 0;
if (pt->is_vararg) /* varargs? */ if (pt->is_vararg) /* varargs? */
top++; /* `arg' */ top++; /* `arg' */
check (top <= pt->maxstacksize && pt->maxstacksize <= MAXSTACK);
while (pc < lastpc) { while (pc < lastpc) {
const Instruction i = code[pc++]; const Instruction i = code[pc++];
lua_assert(0 <= top && top <= pt->maxstacksize); OpCode op = GET_OPCODE(i);
switch (GET_OPCODE(i)) { int push = (int)luaK_opproperties[op].push;
case OP_RETURN: { int pop = (int)luaK_opproperties[op].pop;
lua_assert(top >= GETARG_U(i)); int arg1 = 0;
top = GETARG_U(i); int arg2 = 0;
break; switch ((enum Mode)luaK_opproperties[op].mode) {
case iO: break;
case iU: arg1 = GETARG_U(i); break;
case iS: arg1 = GETARG_S(i); break;
case iAB: arg1 = GETARG_A(i); arg2 = GETARG_B(i); break;
} }
case OP_TAILCALL: { check(0 <= top && top <= pt->maxstacksize);
lua_assert(top >= GETARG_A(i)); switch (op) {
top = GETARG_B(i); case OP_RETURN: {
pop = top-arg1;
break; break;
} }
case OP_CALL: { case OP_CALL: {
int nresults = GETARG_B(i); if (arg2 == MULT_RET) arg2 = 1;
if (nresults == MULT_RET) nresults = 1; pop = top-arg1;
lua_assert(top >= GETARG_A(i)); push = arg2;
top = pushpc(stack, pc, GETARG_A(i), nresults); break;
}
case OP_TAILCALL: {
check(arg1 <= top);
pop = top-arg2;
break; break;
} }
case OP_PUSHNIL: { case OP_PUSHNIL: {
top = pushpc(stack, pc, top, GETARG_U(i)); check(arg1 > 0);
push = arg1;
break; break;
} }
case OP_POP: { case OP_POP: {
top -= GETARG_U(i); pop = arg1;
break;
}
case OP_PUSHSTRING:
case OP_GETGLOBAL:
case OP_GETDOTTED:
case OP_PUSHSELF:
case OP_SETGLOBAL: {
check(arg1 < pt->sizekstr);
break;
}
case OP_PUSHNUM:
case OP_PUSHNEGNUM: {
check(arg1 < pt->sizeknum);
break;
}
case OP_PUSHUPVALUE: {
/* ?? */
break;
}
case OP_GETLOCAL:
case OP_GETINDEXED:
case OP_SETLOCAL: {
check(arg1 < top);
break;
}
case OP_SETTABLE: {
check(2 <= arg1 && arg1 <= top);
pop = arg2;
break; break;
} }
case OP_SETTABLE:
case OP_SETLIST: { case OP_SETLIST: {
top -= GETARG_B(i); pop = arg2;
check(top-pop >= 1); /* there must be a table below the list */
break; break;
} }
case OP_SETMAP: { case OP_SETMAP: {
top -= 2*GETARG_U(i); pop = 2*arg1;
check(top-pop >= 1);
break; break;
} }
case OP_CONCAT: { case OP_CONCAT: {
top -= GETARG_U(i); pop = arg1;
stack[top++] = pc-1;
break; break;
} }
case OP_CLOSURE: { case OP_CLOSURE: {
top -= GETARG_B(i); /* ?? */
stack[top++] = pc-1; pop = arg2;
break;
}
case OP_JMPNE:
case OP_JMPEQ:
case OP_JMPLT:
case OP_JMPLE:
case OP_JMPGT:
case OP_JMPGE:
case OP_JMPT:
case OP_JMPF:
case OP_JMP:
case OP_FORLOOP:
case OP_LFORLOOP: {
checkjump(pt, pc+arg1);
break;
}
case OP_PUSHNILJMP: {
checkjump(pt, pc+1);
break; break;
} }
case OP_JMPONT: case OP_JMPONT:
case OP_JMPONF: { case OP_JMPONF: {
int newpc = pc + GETARG_S(i); int newpc = pc + arg1;
/* jump is forward and do not skip `lastpc'? */ checkjump(pt, newpc);
if (pc < newpc && newpc <= lastpc) { /* jump is forward and do not skip `lastpc' and not full check? */
if (pc < newpc && newpc <= lastpc && stackpos >= 0) {
stack[top-1] = pc-1; /* value comes from `and'/`or' */ stack[top-1] = pc-1; /* value comes from `and'/`or' */
pc = newpc; /* do the jump */ pc = newpc; /* do the jump */
pop = 0; /* do not pop */
} }
else
top--; /* do not jump; pop value */
break; break;
} }
default: { case OP_FORPREP: {
OpCode op = GET_OPCODE(i); check(top >= 3);
int push = (int)luaK_opproperties[op].push; checkjump(pt, pc-arg1); /* jump is `negative' here */
int pop = (int)luaK_opproperties[op].pop; break;
lua_assert(push != VD && pop != VD); }
lua_assert(0 <= top-pop && top+push <= pt->maxstacksize); case OP_LFORPREP: {
check(top >= 1);
checkjump(pt, pc-arg1); /* jump is `negative' here */
break;
}
case OP_PUSHINT:
case OP_GETTABLE:
case OP_CREATETABLE:
case OP_ADD:
case OP_ADDI:
case OP_SUB:
case OP_MULT:
case OP_DIV:
case OP_POW:
case OP_MINUS:
case OP_NOT: {
break;
}
}
check(0 <= pop && 0 <= push);
check(0 <= top-pop && top+(push-pop) <= pt->maxstacksize);
top -= pop; top -= pop;
top = pushpc(stack, pc, top, push); while (push--) stack[top++] = pc-1;
} }
check(GET_OPCODE(code[pt->sizecode-1]) == OP_RETURN);
return (stackpos >= 0) ? code[stack[stackpos]] : 1;
} }
}
return code[stack[stackpos]];
int luaG_checkcode (const Proto *pt) {
return luaG_symbexec(pt, pt->sizecode-1, -1);
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.h,v 1.7 2000/10/05 12:14:08 roberto Exp roberto $ ** $Id: ldebug.h,v 1.8 2001/02/07 18:13:49 roberto Exp roberto $
** Auxiliary functions from Debug Interface module ** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -16,6 +16,7 @@ void luaG_typeerror (lua_State *L, StkId o, const char *op);
void luaG_binerror (lua_State *L, StkId p1, int t, const char *op); void luaG_binerror (lua_State *L, StkId p1, int t, const char *op);
int luaG_getline (int *lineinfo, int pc, int refline, int *refi); int luaG_getline (int *lineinfo, int pc, int refline, int *refi);
void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2); void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2);
int luaG_checkcode (const Proto *pt);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 1.129 2001/02/05 17:48:52 roberto Exp roberto $ ** $Id: lparser.c,v 1.130 2001/02/08 11:19:10 roberto Exp roberto $
** LL(1) Parser and code generator for Lua ** LL(1) Parser and code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -11,6 +11,7 @@
#include "lua.h" #include "lua.h"
#include "lcode.h" #include "lcode.h"
#include "ldebug.h"
#include "lfunc.h" #include "lfunc.h"
#include "llex.h" #include "llex.h"
#include "lmem.h" #include "lmem.h"
@ -351,6 +352,7 @@ static void close_func (LexState *ls) {
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int);
f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */
f->sizelineinfo = fs->nlineinfo; f->sizelineinfo = fs->nlineinfo;
lua_assert(luaG_checkcode(f));
ls->fs = fs->prev; ls->fs = fs->prev;
lua_assert(fs->bl == NULL); lua_assert(fs->bl == NULL);
} }