aboutsummaryrefslogtreecommitdiff
path: root/ldebug.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-02-12 17:54:28 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-02-12 17:54:28 -0200
commit3c649ce1230eaf1df0d64afb2cb2c2a98cd4faa4 (patch)
treea18ad8614489166aac54d2ac56aa917fd97bf4a8 /ldebug.c
parent95da574dbc97bfab54c2fdb170e1caf2f5571f1f (diff)
downloadlua-3c649ce1230eaf1df0d64afb2cb2c2a98cd4faa4.tar.gz
lua-3c649ce1230eaf1df0d64afb2cb2c2a98cd4faa4.tar.bz2
lua-3c649ce1230eaf1df0d64afb2cb2c2a98cd4faa4.zip
checking consistency of jumps (and some other details)
Diffstat (limited to 'ldebug.c')
-rw-r--r--ldebug.c101
1 files changed, 75 insertions, 26 deletions
diff --git a/ldebug.c b/ldebug.c
index 27a885e9..b1248bb7 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 1.61 2001/02/09 18:37:33 roberto Exp roberto $ 2** $Id: ldebug.c,v 1.62 2001/02/09 20:22:29 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -316,49 +316,82 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
316 316
317/* 317/*
318** {====================================================== 318** {======================================================
319** Symbolic Execution 319** Symbolic Execution and code checker
320** ======================================================= 320** =======================================================
321*/ 321*/
322 322
323 323
324#define check(x) if (!(x)) return 0; 324/*#define check(x) if (!(x)) return 0;*/
325#define check(x) assert(x)
325#define checkjump(pt, pc) check(0 <= (pc) && (pc) < (pt)->sizecode) 326#define checkjump(pt, pc) check(0 <= (pc) && (pc) < (pt)->sizecode)
326 327
327static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) { 328
329static int checklineinfo (const Proto *pt) {
330 int *lineinfo = pt->lineinfo;
331 if (lineinfo == NULL) return 1;
332 check(pt->sizelineinfo >= 2 && lineinfo[pt->sizelineinfo-1] == MAX_INT);
333 if (*lineinfo < 0) lineinfo++;
334 check(*lineinfo == 0);
335 return 1;
336}
337
338
339static int precheck (const Proto *pt) {
340 check(checklineinfo(pt));
341 check(pt->maxstacksize <= MAXSTACK);
342 check(pt->numparams+pt->is_vararg <= pt->maxstacksize);
343 check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
344 return 1;
345}
346
347
348/* value for non-initialized entries in array stacklevel */
349#define SL_EMPTY 255
350
351#define checkstacklevel(sl,top,pc) \
352 if (sl) { if (sl[pc] == SL_EMPTY) sl[pc] = top; else check(sl[pc] == top); }
353
354
355static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos,
356 unsigned char *sl) {
328 int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ 357 int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */
329 const Instruction *code = pt->code; 358 const Instruction *code = pt->code;
330 int top = pt->numparams; 359 int top = pt->numparams;
331 int pc = 0; 360 int pc = 0;
332 if (pt->is_vararg) /* varargs? */ 361 if (pt->is_vararg) /* varargs? */
333 top++; /* `arg' */ 362 top++; /* `arg' */
334 check (top <= pt->maxstacksize && pt->maxstacksize <= MAXSTACK); 363 checkstacklevel(sl, top, pc);
335 while (pc < lastpc) { 364 while (pc < lastpc) {
336 const Instruction i = code[pc++]; 365 const Instruction i = code[pc++];
337 OpCode op = GET_OPCODE(i); 366 OpCode op = GET_OPCODE(i);
338 int push = (int)luaK_opproperties[op].push;
339 int pop = (int)luaK_opproperties[op].pop;
340 int arg1 = 0; 367 int arg1 = 0;
341 int arg2 = 0; 368 int arg2 = 0;
369 int push, pop;
370 check(op < NUM_OPCODES);
371 push = (int)luaK_opproperties[op].push;
372 pop = (int)luaK_opproperties[op].pop;
342 switch ((enum Mode)luaK_opproperties[op].mode) { 373 switch ((enum Mode)luaK_opproperties[op].mode) {
343 case iO: break; 374 case iO: break;
344 case iU: arg1 = GETARG_U(i); break; 375 case iU: arg1 = GETARG_U(i); check(arg1 >= 0); break;
345 case iS: arg1 = GETARG_S(i); break; 376 case iS: arg1 = GETARG_S(i); break;
346 case iAB: arg1 = GETARG_A(i); arg2 = GETARG_B(i); break; 377 case iAB:
378 arg1 = GETARG_A(i); arg2 = GETARG_B(i); check(arg1 >= 0); break;
347 } 379 }
348 check(0 <= top && top <= pt->maxstacksize);
349 switch (op) { 380 switch (op) {
350 case OP_RETURN: { 381 case OP_RETURN: {
382 check(arg1 <= top);
351 pop = top-arg1; 383 pop = top-arg1;
352 break; 384 break;
353 } 385 }
354 case OP_CALL: { 386 case OP_CALL: {
355 if (arg2 == MULT_RET) arg2 = 1; 387 if (arg2 == MULT_RET) arg2 = 1;
388 check(arg1 < top);
356 pop = top-arg1; 389 pop = top-arg1;
357 push = arg2; 390 push = arg2;
358 break; 391 break;
359 } 392 }
360 case OP_TAILCALL: { 393 case OP_TAILCALL: {
361 check(arg1 <= top); 394 check(arg1 < top && arg2 <= top);
362 pop = top-arg2; 395 pop = top-arg2;
363 break; 396 break;
364 } 397 }
@@ -395,7 +428,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) {
395 break; 428 break;
396 } 429 }
397 case OP_SETTABLE: { 430 case OP_SETTABLE: {
398 check(2 <= arg1 && arg1 <= top); 431 check(3 <= arg1 && arg1 <= top);
399 pop = arg2; 432 pop = arg2;
400 break; 433 break;
401 } 434 }
@@ -425,21 +458,24 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) {
425 case OP_JMPGT: 458 case OP_JMPGT:
426 case OP_JMPGE: 459 case OP_JMPGE:
427 case OP_JMPT: 460 case OP_JMPT:
428 case OP_JMPF: 461 case OP_JMPF: {
462 checkjump(pt, pc+arg1);
463 check(pop <= top);
464 checkstacklevel(sl, top-pop, pc+arg1);
465 break;
466 }
429 case OP_JMP: 467 case OP_JMP:
430 case OP_FORLOOP: 468 case OP_FORLOOP:
431 case OP_LFORLOOP: { 469 case OP_LFORLOOP: {
432 checkjump(pt, pc+arg1); 470 checkjump(pt, pc+arg1);
433 break; 471 checkstacklevel(sl, top, pc+arg1);
434 }
435 case OP_PUSHNILJMP: {
436 checkjump(pt, pc+1);
437 break; 472 break;
438 } 473 }
439 case OP_JMPONT: 474 case OP_JMPONT:
440 case OP_JMPONF: { 475 case OP_JMPONF: {
441 int newpc = pc + arg1; 476 int newpc = pc+arg1;
442 checkjump(pt, newpc); 477 checkjump(pt, newpc);
478 checkstacklevel(sl, top, newpc);
443 /* jump is forward and do not skip `lastpc' and not full check? */ 479 /* jump is forward and do not skip `lastpc' and not full check? */
444 if (pc < newpc && newpc <= lastpc && stackpos >= 0) { 480 if (pc < newpc && newpc <= lastpc && stackpos >= 0) {
445 stack[top-1] = pc-1; /* value comes from `and'/`or' */ 481 stack[top-1] = pc-1; /* value comes from `and'/`or' */
@@ -448,14 +484,24 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) {
448 } 484 }
449 break; 485 break;
450 } 486 }
487 case OP_PUSHNILJMP: {
488 check(GET_OPCODE(code[pc]) == OP_PUSHINT); /* only valid sequence */
489 break;
490 }
451 case OP_FORPREP: { 491 case OP_FORPREP: {
492 int newpc = pc-arg1; /* jump is `negative' here */
452 check(top >= 3); 493 check(top >= 3);
453 checkjump(pt, pc-arg1); /* jump is `negative' here */ 494 checkjump(pt, newpc);
495 check(GET_OPCODE(code[newpc-1]) == OP_FORLOOP);
496 check(GETARG_S(code[newpc-1]) == arg1);
454 break; 497 break;
455 } 498 }
456 case OP_LFORPREP: { 499 case OP_LFORPREP: {
500 int newpc = pc-arg1; /* jump is `negative' here */
457 check(top >= 1); 501 check(top >= 1);
458 checkjump(pt, pc-arg1); /* jump is `negative' here */ 502 checkjump(pt, newpc);
503 check(GET_OPCODE(code[newpc-1]) == OP_LFORLOOP);
504 check(GETARG_S(code[newpc-1]) == arg1);
459 break; 505 break;
460 } 506 }
461 case OP_PUSHINT: 507 case OP_PUSHINT:
@@ -472,18 +518,21 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) {
472 break; 518 break;
473 } 519 }
474 } 520 }
475 check(0 <= pop && 0 <= push);
476 check(0 <= top-pop && top+(push-pop) <= pt->maxstacksize);
477 top -= pop; 521 top -= pop;
522 check(0 <= top && top+push <= pt->maxstacksize);
478 while (push--) stack[top++] = pc-1; 523 while (push--) stack[top++] = pc-1;
524 checkstacklevel(sl, top, pc);
479 } 525 }
480 check(GET_OPCODE(code[pt->sizecode-1]) == OP_RETURN);
481 return (stackpos >= 0) ? code[stack[stackpos]] : 1; 526 return (stackpos >= 0) ? code[stack[stackpos]] : 1;
482} 527}
483 528
484 529
485int luaG_checkcode (const Proto *pt) { 530int luaG_checkcode (lua_State *L, const Proto *pt) {
486 return luaG_symbexec(pt, pt->sizecode-1, -1); 531 unsigned char *sl = (unsigned char *)luaO_openspace(L, pt->sizecode);
532 int i;
533 for (i=0; i<pt->sizecode; i++)
534 sl[i] = SL_EMPTY;
535 return precheck(pt) && luaG_symbexec(pt, pt->sizecode-1, -1, sl);
487} 536}
488 537
489 538
@@ -495,7 +544,7 @@ static const char *getobjname (lua_State *L, StkId obj, const char **name) {
495 Proto *p = infovalue(func)->func->f.l; 544 Proto *p = infovalue(func)->func->f.l;
496 int pc = currentpc(func); 545 int pc = currentpc(func);
497 int stackpos = obj - (func+1); /* func+1 == function base */ 546 int stackpos = obj - (func+1); /* func+1 == function base */
498 Instruction i = luaG_symbexec(p, pc, stackpos); 547 Instruction i = luaG_symbexec(p, pc, stackpos, NULL);
499 lua_assert(pc != -1); 548 lua_assert(pc != -1);
500 switch (GET_OPCODE(i)) { 549 switch (GET_OPCODE(i)) {
501 case OP_GETGLOBAL: { 550 case OP_GETGLOBAL: {