pxb1988/dex2jar · error · BadOpException

bad payload offset for

Error message

bad payload offset for %s

What it means

DexFileReader throws BadOpException when an instruction's declared payload offset does not point inside the insns array at all (the u1SwitchData/u1payload offset check fails before any payload type is examined). This means the bytecode references data outside the code unit, which cannot happen in a valid dex.

Solutions

  1. Confirm the dex is complete and unmodified (compare checksum/signature in the dex header).
  2. Rebuild the dex from source or re-extract it from the APK.
  3. Pre-scan with dexdump/apkanalyzer to identify malformed methods.
  4. Catch BadOpException and skip the offending method if full-file conversion is not required.

Example fix

// before
dexReader.accept(visitor, 0);
// after
try {
    dexReader.accept(visitor, 0);
} catch (BadOpException e) {
    LOG.warn("bad payload offset: " + e.getMessage());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check dex integrity first: header checksum
int stored = ByteBuffer.wrap(data, 8, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
Checksum cs = new CRC32(); cs.update(data, 12, data.length - 12);
if ((int) cs.getValue() != stored) throw new IllegalArgumentException("dex checksum mismatch");

Try / catch

try {
    dexReader.accept(visitor, 0);
} catch (BadOpException e) {
    LOG.warn("bad payload offset: " + e.getMessage());
}

Prevention

When it happens

Trigger: Decoding a dex where a switch or fill-array-data instruction carries a payload offset that resolves outside the method's insns array, e.g. offset <= 0 or beyond the array length.

Common situations: Corrupted or truncated dex files; dex files modified by anti-analysis protections; inputs produced by broken dex writers.

Related errors


AI-assisted analysis of pxb1988/dex2jar@b5bda4fb49 (2026-09-08). Data as JSON: /api/errors/2ca0e08bb48673c1. Report an issue: GitHub.

Appendix: source

Thrown at dex-reader/src/main/java/com/googlecode/d2j/reader/DexFileReader.java:1260

                        case 0x02:// sparse-switch-data
                        {
                            int size = ushort(insns, u1SwitchData + 2);
                            int b = u1SwitchData + 4 + 4 * size;// targets
                            for (int i = 0; i < size; i++) {
                                target = offset + sint(insns, b + i * 4);
                                if (target < 0 || target * 2 > insns.length ) {
                                    throw new BadOpException("jump out of insns %s -> %04x", op, target);
                                }
                                q.add(target);
                                order(labelsMap, target);
                            }
                            break;
                        }
                        default:
                            throw new BadOpException("bad payload for %s", op);
                    }
            } else {
                throw new BadOpException("bad payload offset for %s", op);
            }
        }

        if (canContinue) {
            int idx = Integer.MAX_VALUE;
            switch (op.indexType) {
            case kIndexStringRef:
                if (op.format == InstructionFormat.kFmt31c) {
                    idx = uint(insns, u1offset + 2);
                } else {// other
                    idx = ushort(insns, u1offset + 2);
                }
                canContinue = idx >= 0 && idx < string_ids_size;
                break;
            case kIndexTypeRef:
                idx = ushort(insns, u1offset + 2);
                canContinue = idx < type_ids_size;
                break;

View on GitHub (pinned to b5bda4fb49)