Add "optional" uint, that allows -1 as a value

This is used for "optional" indexes, that have a "not present"
value of -1
This commit is contained in:
Ben Gruver 2012-10-21 21:40:18 -07:00
parent 198c33bc26
commit 90a1ffeda1
4 changed files with 55 additions and 3 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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});