From f7d6d5fadec6276246194a55b6aefe4815b50ace Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Sat, 14 Sep 2013 19:53:21 -0700 Subject: [PATCH] Gracefully handle instructions with invalid references --- .../Format/InstructionMethodItem.java | 28 +++++++++++++++-- .../java/org/jf/dexlib2/ReferenceType.java | 15 ++++++++++ .../dexlib2/dexbacked/DexBackedDexFile.java | 30 +++++++++++++++---- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java index 3aa0b187..b4508005 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java @@ -32,10 +32,13 @@ import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodItem; import org.jf.baksmali.Adaptors.ReferenceFormatter; import org.jf.baksmali.Renderers.LongRenderer; +import org.jf.dexlib2.ReferenceType; import org.jf.dexlib2.VerificationError; +import org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex; import org.jf.dexlib2.iface.instruction.*; import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction; +import org.jf.dexlib2.iface.reference.Reference; import org.jf.util.IndentingWriter; import javax.annotation.Nonnull; @@ -58,6 +61,21 @@ public class InstructionMethodItem extends MethodItem { @Override public boolean writeTo(IndentingWriter writer) throws IOException { + boolean invalidReference = false; + if (instruction instanceof ReferenceInstruction) { + try { + Reference reference = ((ReferenceInstruction)instruction).getReference(); + } catch (InvalidItemIndex ex) { + invalidReference = true; + + writer.write("#invalid "); + writer.write(ReferenceType.toString(instruction.getOpcode().referenceType)); + writer.write(" index: "); + writer.printSignedIntAsDec(ex.getInvalidIndex()); + writer.write("\n#"); + } + } + switch (instruction.getOpcode().format) { case Format10t: writeOpcode(writer); @@ -336,8 +354,14 @@ public class InstructionMethodItem extends MethodItem { } protected void writeReference(IndentingWriter writer) throws IOException { - ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType, - ((ReferenceInstruction)instruction).getReference()); + try { + ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType, + ((ReferenceInstruction)instruction).getReference()); + } catch (InvalidItemIndex ex) { + writer.write(ReferenceType.toString(instruction.getOpcode().referenceType)); + writer.write("@"); + writer.printSignedIntAsDec(ex.getInvalidIndex()); + } } protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java b/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java index 0f71f4ed..5b74e7dc 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java @@ -38,5 +38,20 @@ public final class ReferenceType { public static final int METHOD = 3; public static final int NONE = 4; + public static String toString(int referenceType) { + switch (referenceType) { + case STRING: + return "string"; + case TYPE: + return "type"; + case FIELD: + return "field"; + case METHOD: + return "method"; + default: + throw new IllegalArgumentException("Invalid reference type: " + referenceType); + } + } + private ReferenceType() {} } \ No newline at end of file diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java index f36c9c35..32c7ef94 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java @@ -163,42 +163,42 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile { public int getStringIdItemOffset(int stringIndex) { if (stringIndex < 0 || stringIndex >= stringCount) { - throw new ExceptionWithContext("String index out of bounds: %d", stringIndex); + throw new InvalidItemIndex(stringIndex, "String index out of bounds: %d", stringIndex); } return stringStartOffset + stringIndex*StringIdItem.ITEM_SIZE; } public int getTypeIdItemOffset(int typeIndex) { if (typeIndex < 0 || typeIndex >= typeCount) { - throw new ExceptionWithContext("Type index out of bounds: %d", typeIndex); + throw new InvalidItemIndex(typeIndex, "Type index out of bounds: %d", typeIndex); } return typeStartOffset + typeIndex*TypeIdItem.ITEM_SIZE; } public int getFieldIdItemOffset(int fieldIndex) { if (fieldIndex < 0 || fieldIndex >= fieldCount) { - throw new ExceptionWithContext("Field index out of bounds: %d", fieldIndex); + throw new InvalidItemIndex(fieldIndex, "Field index out of bounds: %d", fieldIndex); } return fieldStartOffset + fieldIndex*FieldIdItem.ITEM_SIZE; } public int getMethodIdItemOffset(int methodIndex) { if (methodIndex < 0 || methodIndex >= methodCount) { - throw new ExceptionWithContext("Method index out of bounds: %d", methodIndex); + throw new InvalidItemIndex(methodIndex, "Method findex out of bounds: %d", methodIndex); } return methodStartOffset + methodIndex*MethodIdItem.ITEM_SIZE; } public int getProtoIdItemOffset(int protoIndex) { if (protoIndex < 0 || protoIndex >= protoCount) { - throw new ExceptionWithContext("Proto index out of bounds: %d", protoIndex); + throw new InvalidItemIndex(protoIndex, "Proto index out of bounds: %d", protoIndex); } return protoStartOffset + protoIndex*ProtoIdItem.ITEM_SIZE; } public int getClassDefItemOffset(int classIndex) { if (classIndex < 0 || classIndex >= classCount) { - throw new ExceptionWithContext("Class index out of bounds: %d", classIndex); + throw new InvalidItemIndex(classIndex, "Class index out of bounds: %d", classIndex); } return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE; } @@ -261,4 +261,22 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile { super(message, cause); } } + + public static class InvalidItemIndex extends ExceptionWithContext { + private final int itemIndex; + + public InvalidItemIndex(int itemIndex) { + super(""); + this.itemIndex = itemIndex; + } + + public InvalidItemIndex(int itemIndex, String message, Object... formatArgs) { + super(message, formatArgs); + this.itemIndex = itemIndex; + } + + public int getInvalidIndex() { + return itemIndex; + } + } }