Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b67fc383 authored by Hao Ke's avatar Hao Ke
Browse files

Adding typed Parcel readParcelableList API.

Added typed Parcel readParcelableList API that takes extra clazz
parameters check that the class written on the wire is the same,
or a descendant from the one provided as the key and value arguments.

Doing so could enhance the security of Parcel deserialization,
as it would prevent unexpected types of objects being deserialized.
More details can be found at go/safer-parcel.

Test: atest -d android.os.cts.ParcelTest
Bug: 195622897
Change-Id: Ibdb90fa622ef6eaa0bd2b9de629f51fc4fa7091a
parent 92a4b54d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -31513,6 +31513,7 @@ package android.os {
    method @Deprecated @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
    method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
    method @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
    method @NonNull public <T> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader, @NonNull Class<T>);
    method @Nullable public android.os.PersistableBundle readPersistableBundle();
    method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
    method @Deprecated @Nullable public java.io.Serializable readSerializable();
+34 −9
Original line number Diff line number Diff line
@@ -3650,22 +3650,47 @@ public final class Parcel {
    @NonNull
    public final <T extends Parcelable> List<T> readParcelableList(@NonNull List<T> list,
            @Nullable ClassLoader cl) {
        final int N = readInt();
        if (N == -1) {
        return readParcelableListInternal(list, cl, /*clazz*/ null);
    }

    /**
     * Same as {@link #readParcelableList(List, ClassLoader)} but accepts {@code clazz} parameter as
     * the type required for each item.
     *
     * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
     * is not an instance of that class or any of its children classes or there was an error
     * trying to instantiate an element.
     */
    @NonNull
    public <T> List<T> readParcelableList(@NonNull List<T> list,
            @Nullable ClassLoader cl, @NonNull Class<T> clazz) {
        Objects.requireNonNull(list);
        Objects.requireNonNull(clazz);
        return readParcelableListInternal(list, cl, clazz);
    }

    /**
     * @param clazz The type of the object expected or {@code null} for performing no checks.
     */
    @NonNull
    private <T> List<T> readParcelableListInternal(@NonNull List<T> list,
            @Nullable ClassLoader cl, @Nullable Class<T> clazz) {
        final int n = readInt();
        if (n == -1) {
            list.clear();
            return list;
        }

        final int M = list.size();
        final int m = list.size();
        int i = 0;
        for (; i < M && i < N; i++) {
            list.set(i, (T) readParcelable(cl));
        for (; i < m && i < n; i++) {
            list.set(i, (T) readParcelableInternal(cl, clazz));
        }
        for (; i<N; i++) {
            list.add((T) readParcelable(cl));
        for (; i < n; i++) {
            list.add((T) readParcelableInternal(cl, clazz));
        }
        for (; i<M; i++) {
            list.remove(N);
        for (; i < m; i++) {
            list.remove(n);
        }
        return list;
    }