From 4762e7e8db6ba90d8a78ed815d84a4ac17fdbe41 Mon Sep 17 00:00:00 2001 From: Stanislav Zholnin Date: Wed, 5 May 2021 13:44:07 +0100 Subject: [PATCH] Fix bug in BaseParceledListSlice implementation. Under specific conditions, parceled list can be written in such a way that writing of new list starts when destination parcel is just above MAX_IPC_SIZE. In that case "0" is written to parcel to indicate that there will be no inline items written and writing of the list will start with extra items. When unparcelling such list, listElementClass is not determined and stays equal to null, because it only can be determined if there were some inline items read first, before switching to extra. This leads to random unparcelling failures with the following error message: Can't unparcel type in list of type null. Test: manually verified Bug: 186193371 Fix: 151481291 Bug: 156514418 Fix: 169191099 Change-Id: I849bf46158b6d9b109139b19b93a6a1ba16ecc77 --- .../content/pm/BaseParceledListSlice.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java index 5c7a5488076b3..7bade740c9be1 100644 --- a/core/java/android/content/pm/BaseParceledListSlice.java +++ b/core/java/android/content/pm/BaseParceledListSlice.java @@ -75,16 +75,7 @@ abstract class BaseParceledListSlice implements Parcelable { if (p.readInt() == 0) { break; } - - final T parcelable = readCreator(creator, p, loader); - if (listElementClass == null) { - listElementClass = parcelable.getClass(); - } else { - verifySameType(listElementClass, parcelable.getClass()); - } - - mList.add(parcelable); - + listElementClass = readVerifyAndAddElement(creator, p, loader, listElementClass); if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1)); i++; } @@ -104,11 +95,8 @@ abstract class BaseParceledListSlice implements Parcelable { return; } while (i < N && reply.readInt() != 0) { - final T parcelable = readCreator(creator, reply, loader); - verifySameType(listElementClass, parcelable.getClass()); - - mList.add(parcelable); - + listElementClass = readVerifyAndAddElement(creator, reply, loader, + listElementClass); if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1)); i++; } @@ -117,6 +105,18 @@ abstract class BaseParceledListSlice implements Parcelable { } } + private Class readVerifyAndAddElement(Parcelable.Creator creator, Parcel p, + ClassLoader loader, Class listElementClass) { + final T parcelable = readCreator(creator, p, loader); + if (listElementClass == null) { + listElementClass = parcelable.getClass(); + } else { + verifySameType(listElementClass, parcelable.getClass()); + } + mList.add(parcelable); + return listElementClass; + } + private T readCreator(Parcelable.Creator creator, Parcel p, ClassLoader loader) { if (creator instanceof Parcelable.ClassLoaderCreator) { Parcelable.ClassLoaderCreator classLoaderCreator =