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
(cherry picked from commit c642ec8987746a2a44b990bd5354306242d709da)
Change-Id: Ib447557d3582dad6ac01f0e3b4ee497a27a45172
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 34a0f73..fa00c61 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -1921,9 +1921,12 @@
(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);