| 4823 | |
| 4824 | |
| 4825 | static Instruction symbexec (const Proto *pt, int lastpc, int reg) { |
| 4826 | int pc; |
| 4827 | int last; /* stores position of last instruction that changed `reg' */ |
| 4828 | last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ |
| 4829 | check(precheck(pt)); |
| 4830 | for (pc = 0; pc < lastpc; pc++) { |
| 4831 | Instruction i = pt->code[pc]; |
| 4832 | OpCode op = GET_OPCODE(i); |
| 4833 | int a = GETARG_A(i); |
| 4834 | int b = 0; |
| 4835 | int c = 0; |
| 4836 | check(op < NUM_OPCODES); |
| 4837 | checkreg(pt, a); |
| 4838 | switch (getOpMode(op)) { |
| 4839 | case iABC: { |
| 4840 | b = GETARG_B(i); |
| 4841 | c = GETARG_C(i); |
| 4842 | check(checkArgMode(pt, b, getBMode(op))); |
| 4843 | check(checkArgMode(pt, c, getCMode(op))); |
| 4844 | break; |
| 4845 | } |
| 4846 | case iABx: { |
| 4847 | b = GETARG_Bx(i); |
| 4848 | if (getBMode(op) == OpArgK) check(b < pt->sizek); |
| 4849 | break; |
| 4850 | } |
| 4851 | case iAsBx: { |
| 4852 | b = GETARG_sBx(i); |
| 4853 | if (getBMode(op) == OpArgR) { |
| 4854 | int dest = pc+1+b; |
| 4855 | check(0 <= dest && dest < pt->sizecode); |
| 4856 | if (dest > 0) { |
| 4857 | int j; |
| 4858 | /* check that it does not jump to a setlist count; this |
| 4859 | is tricky, because the count from a previous setlist may |
| 4860 | have the same value of an invalid setlist; so, we must |
| 4861 | go all the way back to the first of them (if any) */ |
| 4862 | for (j = 0; j < dest; j++) { |
| 4863 | Instruction d = pt->code[dest-1-j]; |
| 4864 | if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; |
| 4865 | } |
| 4866 | /* if 'j' is even, previous value is not a setlist (even if |
| 4867 | it looks like one) */ |
| 4868 | check((j&1) == 0); |
| 4869 | } |
| 4870 | } |
| 4871 | break; |
| 4872 | } |
| 4873 | } |
| 4874 | if (testAMode(op)) { |
| 4875 | if (a == reg) last = pc; /* change register `a' */ |
| 4876 | } |
| 4877 | if (testTMode(op)) { |
| 4878 | check(pc+2 < pt->sizecode); /* check skip */ |
| 4879 | check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); |
| 4880 | } |
| 4881 | switch (op) { |
| 4882 | case OP_LOADBOOL: { |
no test coverage detected