diff options
author | Ben Gruver <bgruv@google.com> | 2016-11-06 14:25:25 -0800 |
---|---|---|
committer | Ben Gruver <bgruv@google.com> | 2016-11-06 14:25:25 -0800 |
commit | 5e387e59311b0115ce769dea93c787076c5d7d82 (patch) | |
tree | 061b9f04aacb3592537cc960c954eabebe7484c3 | |
parent | a0ccd94bf9c653107629ea3d94dd6db9bf94c0d9 (diff) | |
download | smali-5e387e59311b0115ce769dea93c787076c5d7d82.tar.gz |
Add better error message for when instruction offset is out of range
5 files changed, 131 insertions, 101 deletions
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderOffsetInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderOffsetInstruction.java index d75d7b67..27e43d5e 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderOffsetInstruction.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/BuilderOffsetInstruction.java @@ -33,6 +33,7 @@ package org.jf.dexlib2.builder; import org.jf.dexlib2.Opcode; import org.jf.dexlib2.iface.instruction.OffsetInstruction; +import org.jf.util.ExceptionWithContext; import javax.annotation.Nonnull; @@ -48,9 +49,16 @@ public abstract class BuilderOffsetInstruction extends BuilderInstruction implem @Override public int getCodeOffset() { int codeOffset = internalGetCodeOffset(); - if ((this.getCodeUnits() == 1 && (codeOffset < Byte.MIN_VALUE || codeOffset > Byte.MAX_VALUE)) || - (this.getCodeUnits() == 2 && (codeOffset < Short.MIN_VALUE || codeOffset > Short.MAX_VALUE))) { - throw new IllegalStateException("Target is out of range"); + if (this.getCodeUnits() == 1) { + if (codeOffset < Byte.MIN_VALUE || codeOffset > Byte.MAX_VALUE) { + throw new ExceptionWithContext("Invalid instruction offset: %d. " + + "Offset must be in [-128, 127]", codeOffset); + } + } else if (this.getCodeUnits() == 2) { + if (codeOffset < Short.MIN_VALUE || codeOffset > Short.MAX_VALUE) { + throw new ExceptionWithContext("Invalid instruction offset: %d. " + + "Offset must be in [-32768, 32767]", codeOffset); + } } return codeOffset; } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java index 7109d361..00cce65d 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java @@ -815,7 +815,14 @@ public abstract class DexWriter< int debugItemOffset = writeDebugItem(offsetWriter, debugWriter, classSection.getParameterNames(methodKey), debugItems); - int codeItemOffset = writeCodeItem(codeWriter, ehBuf, methodKey, tryBlocks, instructions, debugItemOffset); + int codeItemOffset; + try { + codeItemOffset = writeCodeItem( + codeWriter, ehBuf, methodKey, tryBlocks, instructions, debugItemOffset); + } catch (RuntimeException ex) { + throw new ExceptionWithContext(ex, "Exception occurred while writing code_item for method %s", + methodSection.getMethodReference(methodKey)); + } if (codeItemOffset != -1) { codeOffsets.add(new CodeItemOffset<MethodKey>(methodKey, codeItemOffset)); @@ -964,105 +971,111 @@ public abstract class DexWriter< methodSection, protoSection); writer.writeInt(codeUnitCount); + int codeOffset = 0; for (Instruction instruction: instructions) { - switch (instruction.getOpcode().format) { - case Format10t: - instructionWriter.write((Instruction10t)instruction); - break; - case Format10x: - instructionWriter.write((Instruction10x)instruction); - break; - case Format11n: - instructionWriter.write((Instruction11n)instruction); - break; - case Format11x: - instructionWriter.write((Instruction11x)instruction); - break; - case Format12x: - instructionWriter.write((Instruction12x)instruction); - break; - case Format20bc: - instructionWriter.write((Instruction20bc)instruction); - break; - case Format20t: - instructionWriter.write((Instruction20t)instruction); - break; - case Format21c: - instructionWriter.write((Instruction21c)instruction); - break; - case Format21ih: - instructionWriter.write((Instruction21ih)instruction); - break; - case Format21lh: - instructionWriter.write((Instruction21lh)instruction); - break; - case Format21s: - instructionWriter.write((Instruction21s)instruction); - break; - case Format21t: - instructionWriter.write((Instruction21t)instruction); - break; - case Format22b: - instructionWriter.write((Instruction22b)instruction); - break; - case Format22c: - instructionWriter.write((Instruction22c)instruction); - break; - case Format22s: - instructionWriter.write((Instruction22s)instruction); - break; - case Format22t: - instructionWriter.write((Instruction22t)instruction); - break; - case Format22x: - instructionWriter.write((Instruction22x)instruction); - break; - case Format23x: - instructionWriter.write((Instruction23x)instruction); - break; - case Format30t: - instructionWriter.write((Instruction30t)instruction); - break; - case Format31c: - instructionWriter.write((Instruction31c)instruction); - break; - case Format31i: - instructionWriter.write((Instruction31i)instruction); - break; - case Format31t: - instructionWriter.write((Instruction31t)instruction); - break; - case Format32x: - instructionWriter.write((Instruction32x)instruction); - break; - case Format35c: - instructionWriter.write((Instruction35c)instruction); - break; - case Format3rc: - instructionWriter.write((Instruction3rc)instruction); - break; - case Format45cc: - instructionWriter.write((Instruction45cc) instruction); - break; - case Format4rcc: - instructionWriter.write((Instruction4rcc) instruction); - break; - case Format51l: - instructionWriter.write((Instruction51l)instruction); - break; - case ArrayPayload: - instructionWriter.write((ArrayPayload)instruction); - break; - case PackedSwitchPayload: - instructionWriter.write((PackedSwitchPayload)instruction); - break; - case SparseSwitchPayload: - instructionWriter.write((SparseSwitchPayload)instruction); - break; - default: - throw new ExceptionWithContext("Unsupported instruction format: %s", - instruction.getOpcode().format); + try { + switch (instruction.getOpcode().format) { + case Format10t: + instructionWriter.write((Instruction10t)instruction); + break; + case Format10x: + instructionWriter.write((Instruction10x)instruction); + break; + case Format11n: + instructionWriter.write((Instruction11n)instruction); + break; + case Format11x: + instructionWriter.write((Instruction11x)instruction); + break; + case Format12x: + instructionWriter.write((Instruction12x)instruction); + break; + case Format20bc: + instructionWriter.write((Instruction20bc)instruction); + break; + case Format20t: + instructionWriter.write((Instruction20t)instruction); + break; + case Format21c: + instructionWriter.write((Instruction21c)instruction); + break; + case Format21ih: + instructionWriter.write((Instruction21ih)instruction); + break; + case Format21lh: + instructionWriter.write((Instruction21lh)instruction); + break; + case Format21s: + instructionWriter.write((Instruction21s)instruction); + break; + case Format21t: + instructionWriter.write((Instruction21t)instruction); + break; + case Format22b: + instructionWriter.write((Instruction22b)instruction); + break; + case Format22c: + instructionWriter.write((Instruction22c)instruction); + break; + case Format22s: + instructionWriter.write((Instruction22s)instruction); + break; + case Format22t: + instructionWriter.write((Instruction22t)instruction); + break; + case Format22x: + instructionWriter.write((Instruction22x)instruction); + break; + case Format23x: + instructionWriter.write((Instruction23x)instruction); + break; + case Format30t: + instructionWriter.write((Instruction30t)instruction); + break; + case Format31c: + instructionWriter.write((Instruction31c)instruction); + break; + case Format31i: + instructionWriter.write((Instruction31i)instruction); + break; + case Format31t: + instructionWriter.write((Instruction31t)instruction); + break; + case Format32x: + instructionWriter.write((Instruction32x)instruction); + break; + case Format35c: + instructionWriter.write((Instruction35c)instruction); + break; + case Format3rc: + instructionWriter.write((Instruction3rc)instruction); + break; + case Format45cc: + instructionWriter.write((Instruction45cc)instruction); + break; + case Format4rcc: + instructionWriter.write((Instruction4rcc)instruction); + break; + case Format51l: + instructionWriter.write((Instruction51l)instruction); + break; + case ArrayPayload: + instructionWriter.write((ArrayPayload)instruction); + break; + case PackedSwitchPayload: + instructionWriter.write((PackedSwitchPayload)instruction); + break; + case SparseSwitchPayload: + instructionWriter.write((SparseSwitchPayload)instruction); + break; + default: + throw new ExceptionWithContext("Unsupported instruction format: %s", + instruction.getOpcode().format); + } + } catch (RuntimeException ex) { + throw new ExceptionWithContext(ex, "Error while writing instruction at code offset 0x%x", codeOffset); } + codeOffset += instruction.getCodeUnits(); } if (tryBlocks.size() > 0) { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/MethodSection.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/MethodSection.java index 32e6d6bf..f31e84c8 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/MethodSection.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/MethodSection.java @@ -39,6 +39,7 @@ import javax.annotation.Nonnull; public interface MethodSection<StringKey, TypeKey, ProtoRefKey extends MethodProtoReference, MethodRefKey extends MethodReference, MethodKey> extends IndexSection<MethodRefKey> { + @Nonnull MethodRefKey getMethodReference(@Nonnull MethodKey key); @Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key); @Nonnull ProtoRefKey getPrototype(@Nonnull MethodRefKey key); @Nonnull ProtoRefKey getPrototype(@Nonnull MethodKey key); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java index e2c59369..7f937fdc 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java @@ -71,6 +71,10 @@ class BuilderMethodPool extends BaseBuilderPool implements MethodSection<Builder return internMethod(new MethodKey(definingClass, name, parameters, returnType)); } + @Nonnull @Override public BuilderMethodReference getMethodReference(@Nonnull BuilderMethod builderMethod) { + return builderMethod.methodReference; + } + @Nonnull @Override public BuilderTypeReference getDefiningClass(@Nonnull BuilderMethodReference key) { return key.definingClass; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java index bb22458d..2801abd0 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java @@ -53,6 +53,10 @@ public class MethodPool extends BaseIndexPool<MethodReference> } } + @Nonnull @Override public MethodReference getMethodReference(@Nonnull PoolMethod poolMethod) { + return poolMethod; + } + @Nonnull @Override public CharSequence getDefiningClass(@Nonnull MethodReference methodReference) { return methodReference.getDefiningClass(); } |