ParceledListSliceTestpublic class ParceledListSliceTest extends TestCase
Methods Summary |
---|
private static int | measureLargeObject()
Parcel p = Parcel.obtain();
try {
new LargeObject(0, 0, 0, 0, 0).writeToParcel(p, 0);
return p.dataPosition();
} finally {
p.recycle();
}
| public void | testHomogeneousElements()Test that only homogeneous elements may be unparceled.
List<BaseObject> list = new ArrayList<BaseObject>();
list.add(new LargeObject(0, 1, 2, 3, 4));
list.add(new SmallObject(5, 6));
list.add(new SmallObject(7, 8));
Parcel parcel = Parcel.obtain();
try {
writeEvilParceledListSlice(parcel, list);
parcel.setDataPosition(0);
try {
ParceledListSlice.CREATOR.createFromParcel(parcel, getClass().getClassLoader());
assertTrue("Unparceled heterogeneous ParceledListSlice", false);
} catch (IllegalArgumentException e) {
// Success, we're not allowed to process heterogeneous
// elements in a ParceledListSlice.
}
} finally {
parcel.recycle();
}
| public void | testLargeList()Test that when the list is large, the data is successfully parceled
and unparceled (the implementation will send pieces of the list in
separate round-trips to avoid the IPC limit).
final int thresholdBytes = 256 * 1024;
final int objectCount = thresholdBytes / measureLargeObject();
List<LargeObject> list = new ArrayList<LargeObject>();
for (int i = 0; i < objectCount; i++) {
list.add(new LargeObject(
i * 5,
(i * 5) + 1,
(i * 5) + 2,
(i * 5) + 3,
(i * 5) + 4
));
}
ParceledListSlice<LargeObject> slice;
Parcel parcel = Parcel.obtain();
try {
parcel.writeParcelable(new ParceledListSlice<LargeObject>(list), 0);
parcel.setDataPosition(0);
slice = parcel.readParcelable(getClass().getClassLoader());
} finally {
parcel.recycle();
}
assertNotNull(slice);
assertNotNull(slice.getList());
assertEquals(objectCount, slice.getList().size());
for (int i = 0; i < objectCount; i++) {
assertEquals(i * 5, slice.getList().get(i).mFieldA);
assertEquals((i * 5) + 1, slice.getList().get(i).mFieldB);
assertEquals((i * 5) + 2, slice.getList().get(i).mFieldC);
assertEquals((i * 5) + 3, slice.getList().get(i).mFieldD);
assertEquals((i * 5) + 4, slice.getList().get(i).mFieldE);
}
| public void | testSmallList()
final int objectCount = 100;
List<SmallObject> list = new ArrayList<SmallObject>();
for (int i = 0; i < objectCount; i++) {
list.add(new SmallObject(i * 2, (i * 2) + 1));
}
ParceledListSlice<SmallObject> slice;
Parcel parcel = Parcel.obtain();
try {
parcel.writeParcelable(new ParceledListSlice<SmallObject>(list), 0);
parcel.setDataPosition(0);
slice = parcel.readParcelable(getClass().getClassLoader());
} finally {
parcel.recycle();
}
assertNotNull(slice);
assertNotNull(slice.getList());
assertEquals(objectCount, slice.getList().size());
for (int i = 0; i < objectCount; i++) {
assertEquals(i * 2, slice.getList().get(i).mFieldA);
assertEquals((i * 2) + 1, slice.getList().get(i).mFieldB);
}
| private static void | writeEvilParceledListSlice(android.os.Parcel dest, java.util.List list)Write a ParcelableListSlice that uses the BaseObject base class as the Creator.
This is dangerous, as it may affect how the data is unparceled, then later parceled
by the system, leading to a self-modifying data security vulnerability.
final int listCount = list.size();
// Number of items.
dest.writeInt(listCount);
// The type/creator to use when unparceling. Here we use the base class
// to simulate an attack on ParceledListSlice.
dest.writeString(BaseObject.class.getName());
for (int i = 0; i < listCount; i++) {
// 1 means the item is present.
dest.writeInt(1);
list.get(i).writeToParcel(dest, 0);
}
|
|