From a0314c265e76426e3e05e615cc713cf36c78cb85 Mon Sep 17 00:00:00 2001 From: "JesusFreke@JesusFreke.com" Date: Mon, 8 Feb 2010 02:27:30 +0000 Subject: [PATCH] Handle uninitialized referenced appropriately git-svn-id: https://smali.googlecode.com/svn/trunk@610 55b6fa8a-2a1e-11de-a435-ffa8d773f76a --- .../Code/Analysis/AnalyzedInstruction.java | 43 +++++++++++++++++++ .../dexlib/Code/Analysis/MethodAnalyzer.java | 24 ++++++++++- .../jf/dexlib/Code/Analysis/RegisterType.java | 10 ++++- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java index a12cc9e6..a6997335 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java @@ -1,6 +1,9 @@ package org.jf.dexlib.Code.Analysis; import org.jf.dexlib.Code.*; +import org.jf.dexlib.Item; +import org.jf.dexlib.ItemType; +import org.jf.dexlib.MethodIdItem; import org.jf.dexlib.Util.ExceptionWithContext; import java.util.LinkedList; @@ -100,6 +103,23 @@ public class AnalyzedInstruction { return mergedRegisterType; } + protected boolean isInvokeInit() { + if (instruction.opcode != Opcode.INVOKE_DIRECT && instruction.opcode != Opcode.INVOKE_DIRECT_RANGE) { + return false; + } + + InstructionWithReference instruction = (InstructionWithReference)this.instruction; + Item item = instruction.getReferencedItem(); + assert item.getItemType() == ItemType.TYPE_METHOD_ID_ITEM; + MethodIdItem method = (MethodIdItem)item; + + if (!method.getMethodName().equals("")) { + return false; + } + + return true; + } + public boolean setsRegister() { return instruction.opcode.setsRegister(); } @@ -109,10 +129,33 @@ public class AnalyzedInstruction { } public boolean setsRegister(int registerNumber) { + + //When constructing a new object, the register type will be an uninitialized reference after the new-instance + //instruction, but becomes an initialized reference once the method is called. So even though invoke + //instructions don't normally change any registers, calling an method will change the type of its + //object register. If the uninitialized reference has been copied to other registers, they will be initialized + //as well, so we need to check for that too + if (isInvokeInit()) { + int destinationRegister = ((FiveRegisterInstruction)instruction).getRegisterD(); + if (registerNumber == destinationRegister) { + return true; + } + RegisterType preInstructionDestRegisterType = getMergedRegisterTypeFromPredecessors(destinationRegister); + if (preInstructionDestRegisterType.category != RegisterType.Category.UninitRef) { + return false; + } + //check if the uninit ref has been copied to another register + if (getMergedRegisterTypeFromPredecessors(registerNumber) == preInstructionDestRegisterType) { + return true; + } + return false; + } + if (!setsRegister()) { return false; } int destinationRegister = getDestinationRegister(); + if (registerNumber == destinationRegister) { return true; } diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java index 630404a5..f5538bb6 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java @@ -1024,6 +1024,28 @@ public class MethodAnalyzer { private boolean handleNewInstance(AnalyzedInstruction analyzedInstruction) { InstructionWithReference instruction = (InstructionWithReference)analyzedInstruction.instruction; + int register = ((SingleRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); + RegisterType destRegisterType = analyzedInstruction.postRegisterMap[register]; + if (destRegisterType.category != RegisterType.Category.Unknown) { + assert destRegisterType.category == RegisterType.Category.UninitRef; + + //the "post-instruction" destination register will only be set if we've gone over + //this instruction at least once before. If this is the case, then we need to check + //all the other registers, and make sure that none of them contain the same + //uninitialized reference that is in the destination register. + + for (int i=0; i is invoked + return new RegisterType(Category.UninitRef, classType); + } + public static RegisterType getRegisterType(Category category, ClassDef classType) { RegisterType newRegisterType = new RegisterType(category, classType); RegisterType internedRegisterType = internedRegisterTypes.get(newRegisterType);