diff --git a/jode/jode/bytecode/AttributeInfo.java b/jode/jode/bytecode/AttributeInfo.java index c323489..d8352f7 100644 --- a/jode/jode/bytecode/AttributeInfo.java +++ b/jode/jode/bytecode/AttributeInfo.java @@ -38,8 +38,14 @@ public class AttributeInfo { name = attrName; data = new byte[length]; input.readFully(data); - } else - input.skip(length); + } else { + while (length > 0) { + int skipped = (int) input.skip(length); + if (skipped == 0) + throw new EOFException("Can't skip. EOF?"); + length -= skipped; + } + } } public String getName() { diff --git a/jode/jode/bytecode/BinaryInfo.java b/jode/jode/bytecode/BinaryInfo.java index 08f98a1..3170fd5 100644 --- a/jode/jode/bytecode/BinaryInfo.java +++ b/jode/jode/bytecode/BinaryInfo.java @@ -51,8 +51,13 @@ public class BinaryInfo { int count = input.readUnsignedShort(); for (int i=0; i< count; i++) { input.readUnsignedShort(); // the name index - int length = input.readInt(); - input.skip(length); + long length = input.readInt(); + while (length > 0) { + long skipped = input.skip(length); + if (skipped == 0) + throw new EOFException("Can't skip. EOF?"); + length -= skipped; + } } } diff --git a/jode/jode/decompiler/Opcodes.java b/jode/jode/decompiler/Opcodes.java index d183f13..56c5e40 100644 --- a/jode/jode/decompiler/Opcodes.java +++ b/jode/jode/decompiler/Opcodes.java @@ -113,6 +113,22 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { return new RetBlock(local); } + /** + * Skips the specified number of bytes in the input stream. This calls + * skip as long until the bytes are all skipped. + * @param is the inputstream to skip. + * @param count the number of bytes to skip. + */ + private final static void skip(InputStream is, long count) + throws IOException { + while (count > 0) { + long skipped = is.skip(count); + if (skipped == 0) + throw new EOFException("Can't skip"); + count -= skipped; + } + } + /** * Read an opcode out of a data input stream and determine its size * and its successors. @@ -127,10 +143,10 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { int opcode = stream.readUnsignedByte(); switch (opcode) { case opc_multianewarray: - stream.skip(3); + skip(stream, 3); return new int[] { 4, addr+4 }; case opc_invokeinterface: - stream.skip(4); + skip(stream, 4); return new int[] { 5, addr+5 }; case opc_wide: { @@ -139,21 +155,21 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { case opc_fload: case opc_dload: case opc_aload: case opc_istore: case opc_lstore: case opc_fstore: case opc_dstore: case opc_astore: - stream.skip(2); + skip(stream, 2); return new int[] { 4, addr+4 }; case opc_iinc: - stream.skip(4); + skip(stream, 4); return new int[] { 6, addr+6 }; case opc_ret: - stream.skip(2); + skip(stream, 2); return new int[] { 4 }; default: throw new ClassFormatError("Invalid wide opcode "+opcode); } } case opc_ret: - stream.skip(1); + skip(stream, 1); return new int[] { 2 }; case opc_jsr_w: @@ -166,7 +182,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { case opc_tableswitch: { int length = 3-(addr % 4); - stream.skip(length); + skip(stream, length); int def = addr + stream.readInt(); int low = stream.readInt(); int high = stream.readInt(); @@ -180,7 +196,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { } case opc_lookupswitch: { int length = 3-(addr % 4); - stream.skip(length); + skip(stream, length); int def = addr + stream.readInt(); int npairs = stream.readInt(); int[] dests = new int[npairs+2]; @@ -212,14 +228,14 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { case opc_anewarray: case opc_checkcast: case opc_instanceof: - stream.skip(2); + skip(stream, 2); return new int[] { 3, addr+3 }; } if (opcode == opc_newarray || (opcode >= opc_bipush && opcode <= opc_aload) || (opcode >= opc_istore && opcode <= opc_astore)) { - stream.skip(1); + skip(stream, 1); return new int[] { 2, addr+2 }; } @@ -475,7 +491,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { ca.getLocalInfo(addr, stream.readUnsignedByte())); case opc_tableswitch: { int length = 3-(addr % 4); - stream.skip(length); + skip(stream, length); int def = addr + stream.readInt(); int low = stream.readInt(); int high = stream.readInt(); @@ -492,7 +508,7 @@ public abstract class Opcodes implements jode.bytecode.Opcodes { } case opc_lookupswitch: { int length = 3-(addr % 4); - stream.skip(length); + skip(stream, length); int def = addr + stream.readInt(); int npairs = stream.readInt(); int[] cases = new int[npairs]; diff --git a/jode/jode/obfuscator/MethodIdentifier.java b/jode/jode/obfuscator/MethodIdentifier.java index 704adba..fa35295 100644 --- a/jode/jode/obfuscator/MethodIdentifier.java +++ b/jode/jode/obfuscator/MethodIdentifier.java @@ -52,7 +52,7 @@ public class MethodIdentifier extends Identifier implements Opcodes { if (exceptionsattr != null) readExceptions(exceptionsattr); } catch (IOException ex) { - ex.printStackTrace(); + ex.printStackTrace(Obfuscator.err); } } @@ -63,6 +63,22 @@ public class MethodIdentifier extends Identifier implements Opcodes { } } + /** + * Skips the specified number of bytes in the input stream. This calls + * skip as long until the bytes are all skipped. + * @param is the inputstream to skip. + * @param count the number of bytes to skip. + */ + private final static void skip(InputStream is, long count) + throws IOException { + while (count > 0) { + long skipped = is.skip(count); + if (skipped == 0) + throw new EOFException("Can't skip."); + count -= skipped; + } + } + /** * Reads the opcodes out of the code info and determine its * references @@ -84,12 +100,12 @@ public class MethodIdentifier extends Identifier implements Opcodes { case opc_istore: case opc_lstore: case opc_fstore: case opc_dstore: case opc_astore: case opc_ret: - stream.skip(2); + skip(stream, 2); addr+=4; break; case opc_iinc: - stream.skip(4); + skip(stream, 4); addr+=6; break; default: @@ -98,7 +114,7 @@ public class MethodIdentifier extends Identifier implements Opcodes { break; } case opc_ret: - stream.skip(1); + skip(stream, 1); addr+=2; break; case opc_sipush: @@ -108,28 +124,28 @@ public class MethodIdentifier extends Identifier implements Opcodes { case opc_ifnull: case opc_ifnonnull: case opc_putstatic: case opc_putfield: - stream.skip(2); + skip(stream, 2); addr+=3; break; case opc_jsr_w: case opc_goto_w: - stream.skip(4); + skip(stream, 4); addr+=5; break; case opc_tableswitch: { int length = 7-(addr % 4); - stream.skip(length); + skip(stream, length); int low = stream.readInt(); int high = stream.readInt(); - stream.skip(4*(high-low+1)); + skip(stream, 4*(high-low+1)); addr += 9 + length + 4*(high-low+1); break; } case opc_lookupswitch: { int length = 7-(addr % 4); - stream.skip(length); + skip(stream, length); int npairs = stream.readInt(); - stream.skip(8*npairs); + skip(stream, 8*npairs); addr += 5 + length + 8*npairs; break; } @@ -166,7 +182,7 @@ public class MethodIdentifier extends Identifier implements Opcodes { clazz.bundle.reachableIdentifier(clName, false); addr += 3; if (opcode == opc_multianewarray) { - stream.skip(1); + skip(stream, 1); addr ++; } break; @@ -184,7 +200,7 @@ public class MethodIdentifier extends Identifier implements Opcodes { addr += 3; if (opcode == opc_invokeinterface) { - stream.skip(2); + skip(stream, 2); addr += 2; } break; @@ -194,10 +210,10 @@ public class MethodIdentifier extends Identifier implements Opcodes { if (opcode == opc_newarray || (opcode >= opc_bipush && opcode <= opc_aload) || (opcode >= opc_istore && opcode <= opc_astore)) { - stream.skip(1); + skip(stream, 1); addr += 2; } else if (opcode >= opc_ifeq && opcode <= opc_jsr) { - stream.skip(2); + skip(stream, 2); addr += 3; } else if (opcode == opc_xxxunusedxxx || opcode >= opc_breakpoint) @@ -242,7 +258,7 @@ public class MethodIdentifier extends Identifier implements Opcodes { try { analyzeCode(); } catch (IOException ex) { - ex.printStackTrace(); + ex.printStackTrace(Obfuscator.err); System.exit(0); } } @@ -557,7 +573,7 @@ public class MethodIdentifier extends Identifier implements Opcodes { output.writeShort(0); // No Attributes; output.close(); } catch (IOException ex) { - ex.printStackTrace(); + ex.printStackTrace(Obfuscator.err); code = null; return; } @@ -590,12 +606,12 @@ public class MethodIdentifier extends Identifier implements Opcodes { case opc_istore: case opc_lstore: case opc_fstore: case opc_dstore: case opc_astore: case opc_ret: - stream.skip(2); + skip(stream, 2); addr+=4; break; case opc_iinc: - stream.skip(4); + skip(stream, 4); addr+=6; break; default: @@ -605,23 +621,23 @@ public class MethodIdentifier extends Identifier implements Opcodes { } case opc_tableswitch: { int length = 7-(addr % 4); - stream.skip(length); + skip(stream, length); int low = stream.readInt(); int high = stream.readInt(); - stream.skip(4*(high-low+1)); + skip(stream, 4*(high-low+1)); addr += 9 + length + 4*(high-low+1); break; } case opc_lookupswitch: { int length = 7-(addr % 4); - stream.skip(length); + skip(stream, length); int npairs = stream.readInt(); - stream.skip(8*npairs); + skip(stream, 8*npairs); addr += 5 + length + 8*npairs; break; } case opc_ret: - stream.skip(1); + skip(stream, 1); addr+=2; break; case opc_sipush: @@ -633,28 +649,28 @@ public class MethodIdentifier extends Identifier implements Opcodes { case opc_anewarray: case opc_checkcast: case opc_instanceof: - stream.skip(2); + skip(stream, 2); addr+=3; break; case opc_multianewarray: - stream.skip(3); + skip(stream, 3); addr += 4; break; case opc_jsr_w: case opc_goto_w: case opc_invokeinterface: - stream.skip(4); + skip(stream, 4); addr+=5; break; default: if (opcode == opc_newarray || (opcode >= opc_bipush && opcode <= opc_aload) || (opcode >= opc_istore && opcode <= opc_astore)) { - stream.skip(1); + skip(stream, 1); addr += 2; } else if (opcode >= opc_ifeq && opcode <= opc_jsr || opcode >= opc_getstatic && opcode <= opc_invokestatic) { - stream.skip(2); + skip(stream, 2); addr += 3; } else if (opcode == opc_xxxunusedxxx || opcode >= opc_breakpoint) @@ -664,7 +680,7 @@ public class MethodIdentifier extends Identifier implements Opcodes { } } } catch (IOException ex) { - ex.printStackTrace(); + ex.printStackTrace(Obfuscator.err); } } }