From 1a83d5a2d052e7e5896741807e855e99668f755a Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 7 Jan 2017 18:04:19 -0800 Subject: [PATCH] Propagate sideways conversions after an instance-of + if-eq/if-eqz Previously, we only propagated the conversion if it was a narrowing conversion, to avoid problems that can occur with member access with widening conversions. However, it should be safe to do the conversion for a "sideways" conversion - one that is neither widening or narrowing. This can happen if we don't yet have full knowledge of the register types, or, less likely, if the "true" branch is impossible to reach. In the first case, we should get better type info as we continue to analyze the method, and we'll revisit the conversion once we have better type info. Or, if it really is an impossible conversion, we still want to propagate the type from the instance-of to the true branch. --- .../dexlib2/analysis/AnalyzedInstruction.java | 3 ++- .../jf/dexlib2/analysis/MethodAnalyzer.java | 22 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalyzedInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalyzedInstruction.java index 111913cc..ce262fa0 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalyzedInstruction.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalyzedInstruction.java @@ -374,7 +374,8 @@ public class AnalyzedInstruction implements Comparable { if (previousInstruction != null && previousInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF && registerNumber == ((Instruction22c)previousInstruction.instruction).getRegisterB() && - MethodAnalyzer.canNarrowAfterInstanceOf(previousInstruction, this, methodAnalyzer.getClassPath())) { + MethodAnalyzer.canPropogateTypeAfterInstanceOf( + previousInstruction, this, methodAnalyzer.getClassPath())) { return true; } } 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 6b2c6528..030cfe8f 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java @@ -1167,20 +1167,26 @@ public class MethodAnalyzer { setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, castRegisterType); } - private static boolean isNarrowingConversion(RegisterType originalType, RegisterType newType) { + private static boolean isNotWideningConversion(RegisterType originalType, RegisterType newType) { if (originalType.type == null || newType.type == null) { - return false; + return true; } if (originalType.type.isInterface()) { return newType.type.implementsInterface(originalType.type.getType()); } else { TypeProto commonSuperclass = newType.type.getCommonSuperclass(originalType.type); - return commonSuperclass.getType().equals(originalType.type.getType()); + if (commonSuperclass.getType().equals(originalType.type.getType())) { + return true; } + if (commonSuperclass.getType().equals(newType.type.getType())) { + return false; + } + } + return true; } - static boolean canNarrowAfterInstanceOf(AnalyzedInstruction analyzedInstanceOfInstruction, - AnalyzedInstruction analyzedIfInstruction, ClassPath classPath) { + static boolean canPropogateTypeAfterInstanceOf(AnalyzedInstruction analyzedInstanceOfInstruction, + AnalyzedInstruction analyzedIfInstruction, ClassPath classPath) { if (!classPath.isArt()) { return false; } @@ -1197,7 +1203,7 @@ public class MethodAnalyzer { RegisterType originalType = analyzedIfInstruction.getPreInstructionRegisterType(objectRegister); - return isNarrowingConversion(originalType, registerType); + return isNotWideningConversion(originalType, registerType); } } catch (UnresolvedClassException ex) { return false; @@ -1220,7 +1226,7 @@ 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)) { + if (canPropogateTypeAfterInstanceOf(prevAnalyzedInstruction, analyzedInstruction, classPath)) { List narrowingRegisters = Lists.newArrayList(); RegisterType newType = RegisterType.getRegisterType(classPath, @@ -1252,7 +1258,7 @@ public class MethodAnalyzer { additionalNarrowingRegister = -1; break; } - if (isNarrowingConversion(originalType, newType)) { + if (isNotWideningConversion(originalType, newType)) { if (additionalNarrowingRegister != -1) { if (additionalNarrowingRegister != moveInstruction.getRegisterB()) { additionalNarrowingRegister = -1;