ART: Fix crash with unreachable void check-cast
return-void
check-cast v0, V
return-void
The above code sequence will not be rejected for the check-cast of a
void type because the check-cast is not reachable. However, when
GenerateSafeCastSet() is called from the compiler, this will cause
IsAssignableFrom(Conflict, Undefined) to be called, as it scans for all
check-casts across the code, regardless of its reachableness.
RegType::AssignableFrom() has been changed to handle a Conflict type,
whereas previously this would break the check that the lhs type is a
ReferenceType.
Additionally, GenerateSafeCastSet has been changed to never assess
instructions that weren't visited during verification.
Included is a new test DEX file, 801-VoidCheckCast, that uses this code
sequence.
Change-Id: I600055ab670ee48a075ffa867b46d2e74f5aa9c0
Signed-off-by: Stephen Kyle <stephen.kyle@arm.com>
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 9f0a696..17328c4 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -282,6 +282,10 @@
Instruction::Code code = inst->Opcode();
if ((code == Instruction::CHECK_CAST) || (code == Instruction::APUT_OBJECT)) {
uint32_t dex_pc = inst->GetDexPc(code_item->insns_);
+ if (!method_verifier->GetInstructionFlags(dex_pc).IsVisited()) {
+ // Do not attempt to quicken this instruction, it's unreachable anyway.
+ continue;
+ }
const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
bool is_safe_cast = false;
if (code == Instruction::CHECK_CAST) {