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.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<T extends Instruction> 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<T extends Instruction> extends MethodItem {
}
protected void writeReference(IndentingWriter writer) throws IOException {
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 {

View File

@ -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() {}
}

View File

@ -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;
}
}
}