From f741c3727383008b131cd3877cbdb3857e07fc9b Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Fri, 7 Nov 2014 11:26:14 -0800 Subject: Fix ParceledListSlice to enforce the same concrete types among its elements. Bug:17671747 Change-Id: I896f75738e5b464ccb6c03290f139cc2fa72f966 (cherry picked from commit 3df1c38ee098872352086e03d6f1adb16796ee29) --- .../java/android/content/pm/ParceledListSlice.java | 47 ++++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'core/java') diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java index 8a43472a430b..335a45e40777 100644 --- a/core/java/android/content/pm/ParceledListSlice.java +++ b/core/java/android/content/pm/ParceledListSlice.java @@ -30,6 +30,12 @@ import java.util.List; * Transfer a large list of Parcelable objects across an IPC. Splits into * multiple transactions if needed. * + * Caveat: for efficiency and security, all elements must be the same concrete type. + * In order to avoid writing the class name of each object, we must ensure that + * each object is the same type, or else unparceling then reparceling the data may yield + * a different result if the class name encoded in the Parcelable is a Base type. + * See b/17671747. + * * @hide */ public class ParceledListSlice implements Parcelable { @@ -56,13 +62,25 @@ public class ParceledListSlice implements Parcelable { if (N <= 0) { return; } + Parcelable.Creator creator = p.readParcelableCreator(loader); + Class listElementClass = null; + int i = 0; while (i < N) { if (p.readInt() == 0) { break; } - mList.add(p.readCreator(creator, loader)); + + final T parcelable = p.readCreator(creator, loader); + if (listElementClass == null) { + listElementClass = parcelable.getClass(); + } else { + verifySameType(listElementClass, parcelable.getClass()); + } + + mList.add(parcelable); + if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1)); i++; } @@ -82,7 +100,11 @@ public class ParceledListSlice implements Parcelable { return; } while (i < N && reply.readInt() != 0) { - mList.add(reply.readCreator(creator, loader)); + final T parcelable = reply.readCreator(creator, loader); + verifySameType(listElementClass, parcelable.getClass()); + + mList.add(parcelable); + if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1)); i++; } @@ -91,6 +113,14 @@ public class ParceledListSlice implements Parcelable { } } + private static void verifySameType(final Class expected, final Class actual) { + if (!actual.equals(expected)) { + throw new IllegalArgumentException("Can't unparcel type " + + actual.getName() + " in list of type " + + expected.getName()); + } + } + public List getList() { return mList; } @@ -116,11 +146,16 @@ public class ParceledListSlice implements Parcelable { dest.writeInt(N); if (DEBUG) Log.d(TAG, "Writing " + N + " items"); if (N > 0) { + final Class listElementClass = mList.get(0).getClass(); dest.writeParcelableCreator(mList.get(0)); int i = 0; while (i < N && dest.dataSize() < MAX_FIRST_IPC_SIZE) { dest.writeInt(1); - mList.get(i).writeToParcel(dest, callFlags); + + final T parcelable = mList.get(i); + verifySameType(listElementClass, parcelable.getClass()); + parcelable.writeToParcel(dest, callFlags); + if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i)); i++; } @@ -137,7 +172,11 @@ public class ParceledListSlice implements Parcelable { if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N); while (i < N && reply.dataSize() < MAX_IPC_SIZE) { reply.writeInt(1); - mList.get(i).writeToParcel(reply, callFlags); + + final T parcelable = mList.get(i); + verifySameType(listElementClass, parcelable.getClass()); + parcelable.writeToParcel(reply, callFlags); + if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i)); i++; } -- cgit v1.2.3