diff options
| author | Jon Larimer <jlarimer@google.com> | 2015-01-29 17:48:57 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-01-29 17:48:58 +0000 |
| commit | fc731e6e40f6f449b8e7ac72c2cd36a57c04a32b (patch) | |
| tree | c4fb1b68922375ab0b66607f5d1e7e54d6f5ee78 /core/java/android | |
| parent | 7dd12d7633663c7f5802bdaaf8e7232a48aba811 (diff) | |
| parent | f741c3727383008b131cd3877cbdb3857e07fc9b (diff) | |
Merge "Fix ParceledListSlice to enforce the same concrete types among its elements." into jb-mr2-dev
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/content/pm/ParceledListSlice.java | 47 |
1 files changed, 43 insertions, 4 deletions
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<T extends Parcelable> implements Parcelable { @@ -56,13 +62,25 @@ public class ParceledListSlice<T extends Parcelable> implements Parcelable { if (N <= 0) { return; } + Parcelable.Creator<T> 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<T extends Parcelable> 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<T extends Parcelable> 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<T> getList() { return mList; } @@ -116,11 +146,16 @@ public class ParceledListSlice<T extends Parcelable> 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<T extends Parcelable> 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++; } |
