diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java index e5924765..4a73f345 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java @@ -69,9 +69,9 @@ public class DexBackedClassDef implements ClassDef { this.name = dexBuf.getType(dexBuf.readSmallUint(classDefOffset)); this.accessFlags = dexBuf.readSmallUint(classDefOffset + ACCESS_FLAGS_OFFSET); - this.superclass = dexBuf.getOptionalString(dexBuf.readSmallUint(classDefOffset + SUPERCLASS_OFFSET)); + this.superclass = dexBuf.getOptionalString(dexBuf.readOptionalUint(classDefOffset + SUPERCLASS_OFFSET)); this.interfacesOffset = dexBuf.readSmallUint(classDefOffset + INTERFACES_OFFSET); - this.sourceFile = dexBuf.getOptionalString(dexBuf.readSmallUint(classDefOffset + SOURCE_FILE_OFFSET)); + this.sourceFile = dexBuf.getOptionalString(dexBuf.readOptionalUint(classDefOffset + SOURCE_FILE_OFFSET)); int annotationsDirectoryOffset = dexBuf.readSmallUint(classDefOffset + ANNOTATIONS_OFFSET); this.annotationsDirectory = AnnotationsDirectory.newOrEmpty(dexBuf, annotationsDirectoryOffset); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBuffer.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBuffer.java index dfc77bf0..fced24ab 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBuffer.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBuffer.java @@ -104,7 +104,19 @@ public class DexBuffer { ((buf[offset+2] & 0xff) << 16) | ((buf[offset+3]) << 24); if (result < 0) { - throw new ExceptionWithContext("Encountered uint that is out of range at offset 0x%x", offset); + throw new ExceptionWithContext("Encountered small uint that is out of range at offset 0x%x", offset); + } + return result; + } + + public int readOptionalUint(int offset) { + byte[] buf = this.buf; + int result = (buf[offset] & 0xff) | + ((buf[offset+1] & 0xff) << 8) | + ((buf[offset+2] & 0xff) << 16) | + ((buf[offset+3]) << 24); + if (result < -1) { + throw new ExceptionWithContext("Encountered optional uint that is out of range at offset 0x%x", offset); } return result; } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexReader.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexReader.java index 48f583d0..f70c4495 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexReader.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexReader.java @@ -174,6 +174,13 @@ public class DexReader { return result; } + public int readOptionalUint() { + int o = offset; + int result = dexBuf.readOptionalUint(o); + offset = o + 4; + return result; + } + public int readUshort() { int o = offset; int result = dexBuf.readUshort(offset); diff --git a/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/DexBufferTest.java b/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/DexBufferTest.java index 94538349..737842e4 100644 --- a/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/DexBufferTest.java +++ b/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/DexBufferTest.java @@ -70,6 +70,39 @@ public class DexBufferTest { dexBuf.readSmallUint(0); } + @Test + public void testReadOptionalUintSuccess() { + BareDexBuffer dexBuf = new BareDexBuffer(new byte[] {0x11, 0x22, 0x33, 0x44}); + Assert.assertEquals(0x44332211, dexBuf.readSmallUint(0)); + + dexBuf = new BareDexBuffer(new byte[] {0x00, 0x00, 0x00, 0x00}); + Assert.assertEquals(0, dexBuf.readSmallUint(0)); + + dexBuf = new BareDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, 0x7f}); + Assert.assertEquals(0x7fffffff, dexBuf.readSmallUint(0)); + + dexBuf = new BareDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + Assert.assertEquals(-1, dexBuf.readOptionalUint(0)); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadOptionalUintTooLarge1() { + BareDexBuffer dexBuf = new BareDexBuffer(new byte[] {0x00, 0x00, 0x00, (byte)0x80}); + dexBuf.readSmallUint(0); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadOptionalUintTooLarge2() { + BareDexBuffer dexBuf = new BareDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x80}); + dexBuf.readSmallUint(0); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadOptionalUintTooLarge3() { + BareDexBuffer dexBuf = new BareDexBuffer(new byte[] {(byte)0xfe, (byte)0xff, (byte)0xff, (byte)0xff}); + dexBuf.readSmallUint(0); + } + @Test public void testReadUshort() { BareDexBuffer dexBuf = new BareDexBuffer(new byte[] {0x11, 0x22});