diff options
author | Andreas Gampe <agampe@google.com> | 2014-06-19 18:13:29 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2014-06-20 18:03:12 -0700 |
commit | c3314311df5ae50ea9151ac4933d3eccbdefb41a (patch) | |
tree | 9da2c9de0286fad85f29a132fbc35d43951b7eab /runtime | |
parent | a81fe3d512ef846aad3398222afd1f0588bbaf7c (diff) | |
download | art-c3314311df5ae50ea9151ac4933d3eccbdefb41a.zip art-c3314311df5ae50ea9151ac4933d3eccbdefb41a.tar.gz art-c3314311df5ae50ea9151ac4933d3eccbdefb41a.tar.bz2 |
ART: Method verifier must check invoke-virtuals for non-zero args
Compiler checks rely on all instructions, not just reachable ones,
so add two new verifier flags.
Bug: 15755602
Change-Id: Ia9c2146cf82d94ce4d69fb6f7be6450137bb84bd
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/dex_instruction.h | 49 | ||||
-rw-r--r-- | runtime/dex_instruction_list.h | 20 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 15 |
3 files changed, 51 insertions, 33 deletions
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h index edba502..b6810b0 100644 --- a/runtime/dex_instruction.h +++ b/runtime/dex_instruction.h @@ -145,28 +145,30 @@ class Instruction { }; enum VerifyFlag { - 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, + 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, + kVerifyVarArgNonZero = 0x040000, + kVerifyVarArgRange = 0x080000, + kVerifyVarArgRangeNonZero = 0x100000, + kVerifyRuntimeOnly = 0x200000, + kVerifyError = 0x400000, }; static constexpr uint32_t kMaxVarArgRegs = 5; @@ -506,7 +508,8 @@ class Instruction { int GetVerifyExtraFlags() const { return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget | - kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError)); + kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero | kVerifyVarArgRange | + kVerifyVarArgRangeNonZero | kVerifyError)); } bool GetVerifyIsRuntimeOnly() const { diff --git a/runtime/dex_instruction_list.h b/runtime/dex_instruction_list.h index 4cda58b..103b0d7 100644 --- a/runtime/dex_instruction_list.h +++ b/runtime/dex_instruction_list.h @@ -128,17 +128,17 @@ V(0x6B, SPUT_BYTE, "sput-byte", k21c, false, kFieldRef, kContinue | kThrow | kStore | kRegBFieldOrConstant, kVerifyRegA | kVerifyRegBField) \ V(0x6C, SPUT_CHAR, "sput-char", k21c, false, kFieldRef, kContinue | kThrow | kStore | kRegBFieldOrConstant, kVerifyRegA | kVerifyRegBField) \ V(0x6D, SPUT_SHORT, "sput-short", k21c, false, kFieldRef, kContinue | kThrow | kStore | kRegBFieldOrConstant, kVerifyRegA | kVerifyRegBField) \ - V(0x6E, INVOKE_VIRTUAL, "invoke-virtual", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArg) \ - V(0x6F, INVOKE_SUPER, "invoke-super", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArg) \ - V(0x70, INVOKE_DIRECT, "invoke-direct", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArg) \ + V(0x6E, INVOKE_VIRTUAL, "invoke-virtual", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgNonZero) \ + V(0x6F, INVOKE_SUPER, "invoke-super", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgNonZero) \ + V(0x70, INVOKE_DIRECT, "invoke-direct", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgNonZero) \ V(0x71, INVOKE_STATIC, "invoke-static", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArg) \ - V(0x72, INVOKE_INTERFACE, "invoke-interface", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArg) \ + V(0x72, INVOKE_INTERFACE, "invoke-interface", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgNonZero) \ V(0x73, RETURN_VOID_BARRIER, "return-void-barrier", k10x, false, kNone, kReturn, kVerifyNone) \ - V(0x74, INVOKE_VIRTUAL_RANGE, "invoke-virtual/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \ - V(0x75, INVOKE_SUPER_RANGE, "invoke-super/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \ - V(0x76, INVOKE_DIRECT_RANGE, "invoke-direct/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \ + V(0x74, INVOKE_VIRTUAL_RANGE, "invoke-virtual/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \ + V(0x75, INVOKE_SUPER_RANGE, "invoke-super/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \ + V(0x76, INVOKE_DIRECT_RANGE, "invoke-direct/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \ V(0x77, INVOKE_STATIC_RANGE, "invoke-static/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \ - V(0x78, INVOKE_INTERFACE_RANGE, "invoke-interface/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRange) \ + V(0x78, INVOKE_INTERFACE_RANGE, "invoke-interface/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \ V(0x79, UNUSED_79, "unused-79", k10x, false, kUnknown, 0, kVerifyError) \ V(0x7A, UNUSED_7A, "unused-7a", k10x, false, kUnknown, 0, kVerifyError) \ V(0x7B, NEG_INT, "neg-int", k12x, true, kNone, kContinue, kVerifyRegA | kVerifyRegB) \ @@ -251,8 +251,8 @@ 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(0xE9, INVOKE_VIRTUAL_QUICK, "invoke-virtual-quick", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyVarArgNonZero | kVerifyRuntimeOnly) \ + V(0xEA, INVOKE_VIRTUAL_RANGE_QUICK, "invoke-virtual/range-quick", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyVarArgRangeNonZero | 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 c9c3bba..7762bc0 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -717,13 +717,28 @@ bool MethodVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_of case Instruction::kVerifySwitchTargets: result = result && CheckSwitchTargets(code_offset); break; + case Instruction::kVerifyVarArgNonZero: + // Fall-through. case Instruction::kVerifyVarArg: { + if (inst->GetVerifyExtraFlags() == Instruction::kVerifyVarArgNonZero && inst->VRegA() <= 0) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid arg count (" << inst->VRegA() << ") in " + "non-range invoke"; + return false; + } uint32_t args[Instruction::kMaxVarArgRegs]; inst->GetVarArgs(args); result = result && CheckVarArgRegs(inst->VRegA(), args); break; } + case Instruction::kVerifyVarArgRangeNonZero: + // Fall-through. case Instruction::kVerifyVarArgRange: + if (inst->GetVerifyExtraFlags() == Instruction::kVerifyVarArgRangeNonZero && + inst->VRegA() <= 0) { + Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid arg count (" << inst->VRegA() << ") in " + "range invoke"; + return false; + } result = result && CheckVarArgRangeRegs(inst->VRegA(), inst->VRegC()); break; case Instruction::kVerifyError: |