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
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);