📄 verify3a.c
字号:
} CHECK_LOCAL_INDEX(n); break; case LLOAD: case LSTORE: case DLOAD: case DSTORE: if (wide == true) { /* the WIDE is considered the beginning of the instruction */ v->status[pc] ^= IS_INSTRUCTION; v->status[pc] |= WIDE_MODDED; pc++; wide = false; n = getWord(code, pc); } else { GET_IDX(n, pc); } /* makes sure the index given for a local variable is within the correct index * * REM: longs and doubles take two consecutive local spots */ CHECK_LOCAL_INDEX(n + 1); break; case IINC: if (wide == true) { /* the WIDE is considered the beginning of the instruction */ v->status[pc] ^= IS_INSTRUCTION; v->status[pc] |= WIDE_MODDED; pc += 2; wide = false; } break; /******************************************************************** * BRANCHING INSTRUCTIONS ********************************************************************/ case GOTO: ENSURE_NON_WIDE; v->status[pc] |= END_BLOCK; n = pc + 1; branchoffset = getWord(code, n); newpc = pc + branchoffset; BRANCH_IN_BOUNDS(newpc, "goto"); v->status[newpc] |= START_BLOCK; break; case GOTO_W: ENSURE_NON_WIDE; v->status[pc] |= END_BLOCK; n = pc + 1; branchoffset = getDWord(code, n); newpc = pc + branchoffset; BRANCH_IN_BOUNDS(newpc, "goto_w"); v->status[newpc] |= START_BLOCK; break; case IF_ACMPEQ: case IFNONNULL: case IF_ACMPNE: case IFNULL: case IF_ICMPEQ: case IFEQ: case IF_ICMPNE: case IFNE: case IF_ICMPGT: case IFGT: case IF_ICMPGE: case IFGE: case IF_ICMPLT: case IFLT: case IF_ICMPLE: case IFLE: ENSURE_NON_WIDE; v->status[pc] |= END_BLOCK; newpc = getNextPC(code, pc); BRANCH_IN_BOUNDS(newpc, "if<condition> = false"); v->status[newpc] |= START_BLOCK; n = pc + 1; branchoffset = getWord(code, n); newpc = pc + branchoffset; BRANCH_IN_BOUNDS(newpc, "if<condition> = true"); v->status[newpc] |= START_BLOCK; break; case JSR: newpc = pc + 1; newpc = pc + getWord(code, newpc); goto JSR_common; case JSR_W: newpc = pc + 1; newpc = pc + getDWord(code, newpc); JSR_common: ENSURE_NON_WIDE; v->status[pc] |= END_BLOCK; BRANCH_IN_BOUNDS(newpc, "jsr"); v->status[newpc] |= START_BLOCK; /* the next instruction is a target for branching via RET */ pc = getNextPC(code, pc); BRANCH_IN_BOUNDS(pc, "jsr/ret"); v->status[pc] |= START_BLOCK; continue; case RET: v->status[pc] |= END_BLOCK; if (!wide) { GET_IDX(idx, pc); } else { GET_WIDX(idx, pc); v->status[pc] ^= IS_INSTRUCTION; v->status[pc] |= WIDE_MODDED; wide = false; pc += 2; } CHECK_LOCAL_INDEX(idx); pc = getNextPC(code, pc); continue; case LOOKUPSWITCH: ENSURE_NON_WIDE; v->status[pc] |= END_BLOCK; /* default branch...between 0 and 3 bytes of padding are added so that the * default branch is at an address that is divisible by 4 */ n = (pc + 1) % 4; if (n) n = pc + 5 - n; else n = pc + 1; newpc = pc + getDWord(code, n); BRANCH_IN_BOUNDS(newpc, "lookupswitch"); v->status[newpc] |= START_BLOCK; DBG(VERIFY3, dprintf(" lookupswitch: pc = %d ... instruction = ", newpc); printInstruction(code[newpc]); dprintf("\n"); ); /* get number of key/target pairs */ n += 4; low = getDWord(code, n); if (low < 0) { verifyError(v, "lookupswitch with npairs < 0"); return; } /* make sure all targets are in bounds */ /* NOTE: the cast here is only there to keep gcc from complaining */ for (n += 4, high = n + 8*low; n < (uint32)high; n += 8) { newpc = pc + getDWord(code, n+4); BRANCH_IN_BOUNDS(newpc, "lookupswitch"); v->status[newpc] |= START_BLOCK; DBG(VERIFY3, dprintf(" lookupswitch: pc = %d ... instruction = ", newpc); printInstruction(code[newpc]); dprintf("\n"); ); } pc = high; continue; case TABLESWITCH: ENSURE_NON_WIDE; v->status[pc] |= END_BLOCK; /* default branch...between 0 and 3 bytes of padding are added so that the * default branch is at an address that is divisible by 4 */ n = (pc + 1) % 4; if (n) n = pc + 5 - n; else n = pc + 1; newpc = pc + getDWord(code, n); BRANCH_IN_BOUNDS(newpc, "tableswitch"); v->status[newpc] |= START_BLOCK; DBG(VERIFY3, dprintf(" tableswitch: pc = %d ... instruction = ", newpc); printInstruction(code[newpc]); dprintf("\n"); ); /* get the high and low values of the table */ low = getDWord(code, n + 4); high = getDWord(code, n + 8); if (high < low) { DBG(VERIFY3, dprintf("ERROR: low = %d, high = %d\n", low, high); ); verifyError(v, "tableswitch high val < low val"); return; } n += 12; /* high and low are used as temps in this loop that checks * the validity of all the branches in the table */ /* NOTE: the cast is only to keep gcc from complaining */ for (high = n + 4*(high - low + 1); n < (uint32)high; n += 4) { newpc = pc + getDWord(code, n); BRANCH_IN_BOUNDS(newpc, "tableswitch"); v->status[newpc] |= START_BLOCK; DBG(VERIFY3, dprintf(" tableswitch: pc = %d ... instruction = ", newpc); printInstruction(code[newpc]); dprintf("\n"); ); } pc = high; continue; /* the rest of the ways to end a block */ case RETURN: case ARETURN: case IRETURN: case FRETURN: case LRETURN: case DRETURN: case ATHROW: ENSURE_NON_WIDE; v->status[pc] |= END_BLOCK; break; default: if (wide == true) { verifyError(v, "illegal instruction following wide instruction"); return; } } pc = getNextPC(code, pc); } DBG(VERIFY3, dprintf(" Verifier Pass 3a: second pass to locate illegal branches and count blocks...\n"); ); /* newpc is going to stand for the PC of the previous instruction */ for (newpc = 0, pc = 0; pc < codelen; pc++) { if (v->status[pc] & IS_INSTRUCTION) { if (v->status[pc] & START_BLOCK) { blockCount++; if (newpc < pc) { /* make sure that the previous instruction is * marked as the end of a block (it would only * have been marked so if it were some kind of * branch). */ v->status[newpc] |= END_BLOCK; } } newpc = pc; } else if (v->status[pc] & START_BLOCK) { verifyError(v, "branch into middle of instruction"); return; } } DBG(VERIFY3, dprintf(" perusing exception table\n"); ); if (v->method->exception_table != 0) { jexceptionEntry *entry; for (n = 0; n < v->method->exception_table->length; n++) { entry = &(v->method->exception_table->entry[n]); pc = entry->start_pc; if (pc >= codelen) { verifyError(v, "try block is beyond bound of method code"); return; } else if (!(v->status[pc] & IS_INSTRUCTION)) { verifyError(v, "try block starts in the middle of an instruction"); return; } pc = entry->end_pc; if (pc <= entry->start_pc) { verifyError(v, "try block ends before its starts"); return; } else if (pc > codelen) { verifyError(v, "try block ends beyond bound of method code"); return; } else if (!(v->status[pc] & IS_INSTRUCTION)) { verifyError(v, "try block ends in the middle of an instruction"); return; } pc = entry->handler_pc; if (pc >= codelen) { verifyError(v, "exception handler is beyond bound of method code"); return; } else if (!(v->status[pc] & IS_INSTRUCTION)) { verifyError(v, "exception handler starts in the middle of an instruction"); return; } v->status[pc] |= (EXCEPTION_HANDLER & START_BLOCK); /* verify properties about the clause * * if entry->catch_type == 0, it's a finally clause */ if (entry->catch_type != 0) { if (entry->catch_type == NULL) { entry->catch_type = getClass(entry->catch_idx, v->method->class, v->einfo); } if (entry->catch_type == NULL) { DBG(VERIFY3, dprintf(" ERROR: could not resolve catch type...\n"); ); entry->catch_type = UNRESOLVABLE_CATCHTYPE; verifyError(v, "unresolvable catch type"); return; } if (!instanceof(javaLangThrowable, entry->catch_type)) { verifyError(v, "Exception to be handled by exception handler is not a subclass of Java/Lang/Throwable"); return; } } } } if (v->method->lvars != NULL) { for (n = 0; n < v->method->lvars->length; n++) { localVariableEntry *lve; lve = &v->method->lvars->entry[n]; pc = lve->start_pc; if (pc >= codelen) { verifyError(v, "local variable is beyond bound of method code"); return; } else if (!(v->status[pc] & IS_INSTRUCTION)) { verifyError(v, "local variable starts in the middle of an instruction"); return; } if ((pc + lve->length) > codelen) { verifyError(v, "local variable is beyond bound of method code"); return; } } } DBG(VERIFY3, dprintf(" done, %d blocks found.\n", blockCount); ); DBG(VERIFY3, dprintf(" Verifier Pass 3a: third pass to allocate memory for basic blocks...\n"); ); blocks = checkPtr((BlockInfo**)gc_malloc(blockCount * sizeof(BlockInfo*), KGC_ALLOC_VERIFIER)); for (inABlock = true, n = 0, pc = 0; pc < codelen; pc++) { if (v->status[pc] & START_BLOCK) { blocks[n] = createBlock(v->method); blocks[n]->startAddr = pc; n++; inABlock = true; DBG(VERIFY3, dprintf(" setting blocks[%d]->startAddr = %d\n", n-1, blocks[n-1]->startAddr); ); } if (inABlock && (v->status[pc] & END_BLOCK)) { blocks[n-1]->lastAddr = pc; inABlock = false; DBG(VERIFY3, dprintf(" setting blocks[%d]->lastAddr = %d\n", n-1, blocks[n-1]->lastAddr); ); } } DBG(VERIFY3, dprintf(" Verifier Pass 3a: done\n"); ); v->numBlocks = blockCount; v->blocks = blocks; #undef CHECK_LOCAL_INDEX #undef BRANCH_IN_BOUNDS#undef GET_IDX#undef GET_WIDX#undef CHECK_POOL_IDX#undef ENSURE_NON_WIDE}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -