diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-02-12 17:54:28 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-02-12 17:54:28 -0200 |
| commit | 3c649ce1230eaf1df0d64afb2cb2c2a98cd4faa4 (patch) | |
| tree | a18ad8614489166aac54d2ac56aa917fd97bf4a8 /ldebug.c | |
| parent | 95da574dbc97bfab54c2fdb170e1caf2f5571f1f (diff) | |
| download | lua-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.c | 101 |
1 files changed, 75 insertions, 26 deletions
| @@ -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 | ||
| 327 | static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) { | 328 | |
| 329 | static 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 | |||
| 339 | static 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 | |||
| 355 | static 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 | ||
| 485 | int luaG_checkcode (const Proto *pt) { | 530 | int 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: { |
