From a6593575e71a9cccf2d9711b774223aca12c22df Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sun, 16 Oct 2016 13:45:30 -0700 Subject: [PATCH] Be more precise about narrowing after an instance-of Only do the additional narrowing when all predecessors of the instance-of are equivalent move instructions. --- .../jf/dexlib2/analysis/MethodAnalyzer.java | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java index 0da57f16..0c073b39 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java @@ -1216,35 +1216,57 @@ public class MethodAnalyzer { } AnalyzedInstruction prevAnalyzedInstruction = analyzedInstruction.getPredecessors().first(); if (prevAnalyzedInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF) { + Instruction22c instanceOfInstruction = (Instruction22c)prevAnalyzedInstruction.instruction; if (canNarrowAfterInstanceOf(prevAnalyzedInstruction, analyzedInstruction, classPath)) { List narrowingRegisters = Lists.newArrayList(); RegisterType newType = RegisterType.getRegisterType(classPath, - (TypeReference)((Instruction22c)prevAnalyzedInstruction.instruction).getReference()); + (TypeReference)instanceOfInstruction.getReference()); if (instructionIndex > 1) { // If we have something like: // move-object/from16 v0, p1 // instance-of v2, v0, Lblah; // if-eqz v2, :target - // Then we need to narrow both v0 AND p1 - AnalyzedInstruction prevPrevAnalyzedInstruction = - analyzedInstructions.valueAt(instructionIndex - 2); - Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode(); - if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || - opcode == Opcode.MOVE_OBJECT_FROM16) { - TwoRegisterInstruction moveInstruction = - ((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction); - RegisterType originalType = - prevPrevAnalyzedInstruction.getPostInstructionRegisterType( - moveInstruction.getRegisterB()); - if (originalType.type != null) { - if (isNarrowingConversion(originalType, newType)) { - narrowingRegisters.add( - ((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction).getRegisterB()); + // Then we need to narrow both v0 AND p1, but only if all predecessors of instance-of are a + // move-object for the same registers + + int additionalNarrowingRegister = -1; + for (AnalyzedInstruction prevPrevAnalyzedInstruction: prevAnalyzedInstruction.predecessors) { + Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode(); + if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || + opcode == Opcode.MOVE_OBJECT_FROM16) { + TwoRegisterInstruction moveInstruction = + ((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction); + RegisterType originalType = + prevPrevAnalyzedInstruction.getPostInstructionRegisterType( + moveInstruction.getRegisterB()); + if (moveInstruction.getRegisterA() != instanceOfInstruction.getRegisterB()) { + additionalNarrowingRegister = -1; + break; } + if (originalType.type == null) { + additionalNarrowingRegister = -1; + break; + } + if (isNarrowingConversion(originalType, newType)) { + if (additionalNarrowingRegister != -1) { + if (additionalNarrowingRegister != moveInstruction.getRegisterB()) { + additionalNarrowingRegister = -1; + break; + } + } else { + additionalNarrowingRegister = moveInstruction.getRegisterB(); + } + } + } else { + additionalNarrowingRegister = -1; + break; } } + if (additionalNarrowingRegister != -1) { + narrowingRegisters.add(additionalNarrowingRegister); + } } // Propagate the original type to the failing branch, and the new type to the successful branch