diff options
author | Ian Rogers <irogers@google.com> | 2014-06-13 10:31:28 -0700 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-06-13 11:25:17 -0700 |
commit | 5fb22a916dcb652fd2c2a2421de621f458177dcd (patch) | |
tree | 4453b47638d9c8b8da61c9fc967f2e7ec89ffb22 | |
parent | 1eadc56648869e1b3989407525313a7eea1fed22 (diff) | |
download | art-5fb22a916dcb652fd2c2a2421de621f458177dcd.tar.gz art-5fb22a916dcb652fd2c2a2421de621f458177dcd.tar.bz2 art-5fb22a916dcb652fd2c2a2421de621f458177dcd.zip |
Don't verify runtime only opcodes in the data-flow phase of verification.
Bug: 15570344
Change-Id: I0304e8742a1d0318783ba72862e684ab91f63d0e
-rw-r--r-- | runtime/dex_instruction.h | 56 | ||||
-rw-r--r-- | runtime/dex_instruction_list.h | 16 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 29 |
3 files changed, 43 insertions, 58 deletions
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h index 1ff5c196b..edba5020d 100644 --- a/runtime/dex_instruction.h +++ b/runtime/dex_instruction.h @@ -145,27 +145,28 @@ class Instruction { }; enum VerifyFlag { - kVerifyNone = 0x00000, - kVerifyRegA = 0x00001, - kVerifyRegAWide = 0x00002, - kVerifyRegB = 0x00004, - kVerifyRegBField = 0x00008, - kVerifyRegBMethod = 0x00010, - kVerifyRegBNewInstance = 0x00020, - kVerifyRegBString = 0x00040, - kVerifyRegBType = 0x00080, - kVerifyRegBWide = 0x00100, - kVerifyRegC = 0x00200, - kVerifyRegCField = 0x00400, - kVerifyRegCNewArray = 0x00800, - kVerifyRegCType = 0x01000, - kVerifyRegCWide = 0x02000, - kVerifyArrayData = 0x04000, - kVerifyBranchTarget = 0x08000, - kVerifySwitchTargets = 0x10000, - kVerifyVarArg = 0x20000, - kVerifyVarArgRange = 0x40000, - kVerifyError = 0x80000, + kVerifyNone = 0x000000, + kVerifyRegA = 0x000001, + kVerifyRegAWide = 0x000002, + kVerifyRegB = 0x000004, + kVerifyRegBField = 0x000008, + kVerifyRegBMethod = 0x000010, + kVerifyRegBNewInstance = 0x000020, + kVerifyRegBString = 0x000040, + kVerifyRegBType = 0x000080, + kVerifyRegBWide = 0x000100, + kVerifyRegC = 0x000200, + kVerifyRegCField = 0x000400, + kVerifyRegCNewArray = 0x000800, + kVerifyRegCType = 0x001000, + kVerifyRegCWide = 0x002000, + kVerifyArrayData = 0x004000, + kVerifyBranchTarget = 0x008000, + kVerifySwitchTargets = 0x010000, + kVerifyVarArg = 0x020000, + kVerifyVarArgRange = 0x040000, + kVerifyRuntimeOnly = 0x080000, + kVerifyError = 0x100000, }; static constexpr uint32_t kMaxVarArgRegs = 5; @@ -493,18 +494,23 @@ class Instruction { } int GetVerifyTypeArgumentB() const { - return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod | - kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide)); + return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | + kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | + kVerifyRegBWide)); } int GetVerifyTypeArgumentC() const { return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField | - kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide)); + kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide)); } int GetVerifyExtraFlags() const { return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget | - kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError)); + kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError)); + } + + bool GetVerifyIsRuntimeOnly() const { + return (kInstructionVerifyFlags[Opcode()] & kVerifyRuntimeOnly) != 0; } // Get the dex PC of this instruction as a offset in code units from the beginning of insns. diff --git a/runtime/dex_instruction_list.h b/runtime/dex_instruction_list.h index f43e42f04..4cda58b92 100644 --- a/runtime/dex_instruction_list.h +++ b/runtime/dex_instruction_list.h @@ -245,14 +245,14 @@ V(0xE0, SHL_INT_LIT8, "shl-int/lit8", k22b, true, kNone, kContinue | kShl | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \ V(0xE1, SHR_INT_LIT8, "shr-int/lit8", k22b, true, kNone, kContinue | kShr | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \ V(0xE2, USHR_INT_LIT8, "ushr-int/lit8", k22b, true, kNone, kContinue | kUshr | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \ - V(0xE3, IGET_QUICK, "iget-quick", k22c, true, kFieldRef, kContinue | kThrow | kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \ - V(0xE4, IGET_WIDE_QUICK, "iget-wide-quick", k22c, true, kFieldRef, kContinue | kThrow | kLoad | kRegCFieldOrConstant, kVerifyRegAWide | kVerifyRegB) \ - V(0xE5, IGET_OBJECT_QUICK, "iget-object-quick", k22c, true, kFieldRef, kContinue | kThrow | kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \ - V(0xE6, IPUT_QUICK, "iput-quick", k22c, false, kFieldRef, kContinue | kThrow | kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \ - V(0xE7, IPUT_WIDE_QUICK, "iput-wide-quick", k22c, false, kFieldRef, kContinue | kThrow | kStore | kRegCFieldOrConstant, kVerifyRegAWide | kVerifyRegB) \ - V(0xE8, IPUT_OBJECT_QUICK, "iput-object-quick", k22c, false, kFieldRef, kContinue | kThrow | kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB) \ - V(0xE9, INVOKE_VIRTUAL_QUICK, "invoke-virtual-quick", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyVarArg) \ - V(0xEA, INVOKE_VIRTUAL_RANGE_QUICK, "invoke-virtual/range-quick", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyVarArgRange) \ + V(0xE3, IGET_QUICK, "iget-quick", k22c, true, kFieldRef, kContinue | kThrow | kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \ + V(0xE4, IGET_WIDE_QUICK, "iget-wide-quick", k22c, true, kFieldRef, kContinue | kThrow | kLoad | kRegCFieldOrConstant, kVerifyRegAWide | kVerifyRegB | kVerifyRuntimeOnly) \ + V(0xE5, IGET_OBJECT_QUICK, "iget-object-quick", k22c, true, kFieldRef, kContinue | kThrow | kLoad | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \ + V(0xE6, IPUT_QUICK, "iput-quick", k22c, false, kFieldRef, kContinue | kThrow | kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \ + V(0xE7, IPUT_WIDE_QUICK, "iput-wide-quick", k22c, false, kFieldRef, kContinue | kThrow | kStore | kRegCFieldOrConstant, kVerifyRegAWide | kVerifyRegB | kVerifyRuntimeOnly) \ + V(0xE8, IPUT_OBJECT_QUICK, "iput-object-quick", k22c, false, kFieldRef, kContinue | kThrow | kStore | kRegCFieldOrConstant, kVerifyRegA | kVerifyRegB | kVerifyRuntimeOnly) \ + V(0xE9, INVOKE_VIRTUAL_QUICK, "invoke-virtual-quick", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyVarArg | kVerifyRuntimeOnly) \ + V(0xEA, INVOKE_VIRTUAL_RANGE_QUICK, "invoke-virtual/range-quick", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyVarArgRange | kVerifyRuntimeOnly) \ V(0xEB, UNUSED_EB, "unused-eb", k10x, false, kUnknown, 0, kVerifyError) \ V(0xEC, UNUSED_EC, "unused-ec", k10x, false, kUnknown, 0, kVerifyError) \ V(0xED, UNUSED_ED, "unused-ed", k10x, false, kUnknown, 0, kVerifyError) \ diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 63a1fe5f3..f551d6923 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -731,6 +731,10 @@ bool MethodVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_of result = false; break; } + if (inst->GetVerifyIsRuntimeOnly() && Runtime::Current()->IsCompiler()) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "opcode only expected at runtime " << inst->Name(); + result = false; + } return result; } @@ -1334,31 +1338,6 @@ bool MethodVerifier::CodeFlowVerifyMethod() { insn_flags_[insn_idx].ClearChanged(); } - // When we're in compiler mode, do not accept quickened instructions. - // We explicitly iterate over *all* instructions to check code that may be unreachable and - // missed by the loop above. - if (Runtime::Current() != nullptr && Runtime::Current()->IsCompiler()) { - uint32_t insn_idx = 0; - for (; insn_idx < insns_size; insn_idx += insn_flags_[insn_idx].GetLengthInCodeUnits()) { - const Instruction* inst = Instruction::At(insns + insn_idx); - switch (inst->Opcode()) { - case Instruction::IGET_QUICK: - case Instruction::IGET_WIDE_QUICK: - case Instruction::IGET_OBJECT_QUICK: - case Instruction::IPUT_QUICK: - case Instruction::IPUT_WIDE_QUICK: - case Instruction::IPUT_OBJECT_QUICK: - case Instruction::INVOKE_VIRTUAL_QUICK: - case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: - Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Quickened instructions not allowed. "; - return false; - - default: - break; - } - } - } - if (gDebugVerify) { /* * Scan for dead code. There's nothing "evil" about dead code |