Commit 20bf85b1 authored by Skylot's avatar Skylot

core: ignore bogus opcode decode (#214)

parent f02b99a1
package jadx.core.dex.instructions;
import java.io.EOFException;
import com.android.dex.Code;
import com.android.dx.io.OpcodeInfo;
import com.android.dx.io.Opcodes;
import com.android.dx.io.instructions.DecodedInstruction;
import com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction;
import com.android.dx.io.instructions.PackedSwitchPayloadDecodedInstruction;
import com.android.dx.io.instructions.ShortArrayCodeInput;
import com.android.dx.io.instructions.SparseSwitchPayloadDecodedInstruction;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType;
......@@ -12,16 +26,8 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.exceptions.DecodeException;
import com.android.dex.Code;
import com.android.dx.io.OpcodeInfo;
import com.android.dx.io.Opcodes;
import com.android.dx.io.instructions.DecodedInstruction;
import com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction;
import com.android.dx.io.instructions.PackedSwitchPayloadDecodedInstruction;
import com.android.dx.io.instructions.ShortArrayCodeInput;
import com.android.dx.io.instructions.SparseSwitchPayloadDecodedInstruction;
public class InsnDecoder {
private static final Logger LOG = LoggerFactory.getLogger(InsnDecoder.class);
private final MethodNode method;
private final DexNode dex;
......@@ -37,26 +43,36 @@ public class InsnDecoder {
int size = encodedInstructions.length;
DecodedInstruction[] decoded = new DecodedInstruction[size];
ShortArrayCodeInput in = new ShortArrayCodeInput(encodedInstructions);
try {
while (in.hasMore()) {
decoded[in.cursor()] = DecodedInstruction.decode(in);
decoded[in.cursor()] = decodeRawInsn(in);
}
} catch (Exception e) {
throw new DecodeException(method, "", e);
throw new DecodeException(method, e.getMessage(), e);
}
insnArr = decoded;
}
private DecodedInstruction decodeRawInsn(ShortArrayCodeInput in) throws EOFException {
int opcodeUnit = in.read();
int opcode = Opcodes.extractOpcodeFromUnit(opcodeUnit);
OpcodeInfo.Info opcodeInfo;
try {
opcodeInfo = OpcodeInfo.get(opcode);
} catch (IllegalArgumentException e) {
LOG.warn("Ignore decode error: '{}', replace with NOP instruction", e.getMessage());
opcodeInfo = OpcodeInfo.NOP;
}
return opcodeInfo.getFormat().decode(opcodeUnit, in);
}
public InsnNode[] process() throws DecodeException {
InsnNode[] instructions = new InsnNode[insnArr.length];
for (int i = 0; i < insnArr.length; i++) {
DecodedInstruction rawInsn = insnArr[i];
if (rawInsn != null) {
InsnNode insn = decode(rawInsn, i);
if (insn != null) {
insn.setOffset(i);
}
insn.setOffset(i);
instructions[i] = insn;
} else {
instructions[i] = null;
......@@ -66,15 +82,14 @@ public class InsnDecoder {
return instructions;
}
@NotNull
private InsnNode decode(DecodedInstruction insn, int offset) throws DecodeException {
switch (insn.getOpcode()) {
case Opcodes.NOP:
return new InsnNode(InsnType.NOP, 0);
case Opcodes.PACKED_SWITCH_PAYLOAD:
case Opcodes.SPARSE_SWITCH_PAYLOAD:
case Opcodes.FILL_ARRAY_DATA_PAYLOAD:
return null;
return new InsnNode(InsnType.NOP, 0);
// move-result will be process in invoke and filled-new-array instructions
case Opcodes.MOVE_RESULT:
......@@ -565,9 +580,10 @@ public class InsnDecoder {
return insn(InsnType.MONITOR_EXIT,
null,
InsnArg.reg(insn, 0, ArgType.UNKNOWN_OBJECT));
}
throw new DecodeException("Unknown instruction: '" + OpcodeInfo.getName(insn.getOpcode()) + "'");
default:
throw new DecodeException("Unknown instruction: '" + OpcodeInfo.getName(insn.getOpcode()) + "'");
}
}
private InsnNode decodeSwitch(DecodedInstruction insn, int offset, boolean packed) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment