Gracefully handle instructions with invalid references

This commit is contained in:
Ben Gruver 2013-09-14 19:53:21 -07:00
parent f9bcf89674
commit f7d6d5fade
3 changed files with 65 additions and 8 deletions

View File

@ -32,10 +32,13 @@ import org.jf.baksmali.Adaptors.MethodDefinition;
import org.jf.baksmali.Adaptors.MethodItem; import org.jf.baksmali.Adaptors.MethodItem;
import org.jf.baksmali.Adaptors.ReferenceFormatter; import org.jf.baksmali.Adaptors.ReferenceFormatter;
import org.jf.baksmali.Renderers.LongRenderer; import org.jf.baksmali.Renderers.LongRenderer;
import org.jf.dexlib2.ReferenceType;
import org.jf.dexlib2.VerificationError; import org.jf.dexlib2.VerificationError;
import org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex;
import org.jf.dexlib2.iface.instruction.*; import org.jf.dexlib2.iface.instruction.*;
import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; import org.jf.dexlib2.iface.instruction.formats.Instruction20bc;
import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction; import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.util.IndentingWriter; import org.jf.util.IndentingWriter;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -58,6 +61,21 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
@Override @Override
public boolean writeTo(IndentingWriter writer) throws IOException { 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) { switch (instruction.getOpcode().format) {
case Format10t: case Format10t:
writeOpcode(writer); writeOpcode(writer);
@ -336,8 +354,14 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem {
} }
protected void writeReference(IndentingWriter writer) throws IOException { protected void writeReference(IndentingWriter writer) throws IOException {
try {
ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType, ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType,
((ReferenceInstruction)instruction).getReference()); ((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 { protected void writeVerificationErrorType(IndentingWriter writer) throws IOException {

View File

@ -38,5 +38,20 @@ public final class ReferenceType {
public static final int METHOD = 3; public static final int METHOD = 3;
public static final int NONE = 4; 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() {} private ReferenceType() {}
} }

View File

@ -163,42 +163,42 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
public int getStringIdItemOffset(int stringIndex) { public int getStringIdItemOffset(int stringIndex) {
if (stringIndex < 0 || stringIndex >= stringCount) { 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; return stringStartOffset + stringIndex*StringIdItem.ITEM_SIZE;
} }
public int getTypeIdItemOffset(int typeIndex) { public int getTypeIdItemOffset(int typeIndex) {
if (typeIndex < 0 || typeIndex >= typeCount) { 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; return typeStartOffset + typeIndex*TypeIdItem.ITEM_SIZE;
} }
public int getFieldIdItemOffset(int fieldIndex) { public int getFieldIdItemOffset(int fieldIndex) {
if (fieldIndex < 0 || fieldIndex >= fieldCount) { 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; return fieldStartOffset + fieldIndex*FieldIdItem.ITEM_SIZE;
} }
public int getMethodIdItemOffset(int methodIndex) { public int getMethodIdItemOffset(int methodIndex) {
if (methodIndex < 0 || methodIndex >= methodCount) { 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; return methodStartOffset + methodIndex*MethodIdItem.ITEM_SIZE;
} }
public int getProtoIdItemOffset(int protoIndex) { public int getProtoIdItemOffset(int protoIndex) {
if (protoIndex < 0 || protoIndex >= protoCount) { 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; return protoStartOffset + protoIndex*ProtoIdItem.ITEM_SIZE;
} }
public int getClassDefItemOffset(int classIndex) { public int getClassDefItemOffset(int classIndex) {
if (classIndex < 0 || classIndex >= classCount) { 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; return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE;
} }
@ -261,4 +261,22 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
super(message, cause); 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;
}
}
} }