diff options
author | Jeff Hao <jeffhao@google.com> | 2013-09-04 16:11:55 -0700 |
---|---|---|
committer | Jeff Hao <jeffhao@google.com> | 2013-09-04 16:14:13 -0700 |
commit | c642ec8987746a2a44b990bd5354306242d709da (patch) | |
tree | bc257f588bd2623eadb8b4af0b99df3096993c42 /runtime/verifier | |
parent | 8c6326c528aa785041f0d8c08e24c6b793ba5b6e (diff) | |
download | android_art-c642ec8987746a2a44b990bd5354306242d709da.tar.gz android_art-c642ec8987746a2a44b990bd5354306242d709da.tar.bz2 android_art-c642ec8987746a2a44b990bd5354306242d709da.zip |
Fix verifier upcasting type after instance_of.
The verifier automatically changed the type of a register to be
the checked type in an instance_of instruction, even if the
checked type was the register type's superclass. This would loosen
the type information of the register and cause problems later.
Bug: 10614872
Change-Id: I67aa2c66be754d946e928b8a64431f193539b842
Diffstat (limited to 'runtime/verifier')
-rw-r--r-- | runtime/verifier/method_verifier.cc | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 34a0f73fdf..fa00c61017 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -1921,9 +1921,12 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { (instance_of_inst->VRegA_22c() != instance_of_inst->VRegB_22c())) { // Check that the we are not attempting conversion to interface types, // which is not done because of the multiple inheritance implications. + // Also don't change the type if it would result in an upcast. + const RegType& orig_type = work_line_->GetRegisterType(instance_of_inst->VRegB_22c()); const RegType& cast_type = ResolveClassAndCheckAccess(instance_of_inst->VRegC_22c()); - if (!cast_type.IsUnresolvedTypes() && !cast_type.GetClass()->IsInterface()) { + if (!cast_type.IsUnresolvedTypes() && !cast_type.GetClass()->IsInterface() && + !cast_type.IsAssignableFrom(orig_type)) { RegisterLine* update_line = new RegisterLine(code_item_->registers_size_, this); if (inst->Opcode() == Instruction::IF_EQZ) { fallthrough_line.reset(update_line); |