Merge "Fuzz java parcel surfaces" am: 8a09c9a244
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2321414 Change-Id: Icf70bcaaf3c335a5e51413361188f2d1d3811046 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -432,6 +432,7 @@ filegroup {
|
|||||||
"android/os/IInterface.java",
|
"android/os/IInterface.java",
|
||||||
"android/os/Binder.java",
|
"android/os/Binder.java",
|
||||||
"android/os/IBinder.java",
|
"android/os/IBinder.java",
|
||||||
|
"android/os/Parcelable.java",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ public class FuzzBinder {
|
|||||||
fuzzServiceInternal(binder, data);
|
fuzzServiceInternal(binder, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This API creates random parcel object
|
// This API fills parcel object
|
||||||
public static void createRandomParcel(Parcel parcel, byte[] data) {
|
public static void fillRandomParcel(Parcel parcel, byte[] data) {
|
||||||
getRandomParcel(parcel, data);
|
fillParcelInternal(parcel, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native void fuzzServiceInternal(IBinder binder, byte[] data);
|
private static native void fuzzServiceInternal(IBinder binder, byte[] data);
|
||||||
private static native void getRandomParcel(Parcel parcel, byte[] data);
|
private static native void fillParcelInternal(Parcel parcel, byte[] data);
|
||||||
private static native int registerNatives();
|
private static native int registerNatives();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ JNIEXPORT jint JNICALL Java_randomparcel_FuzzBinder_registerNatives(JNIEnv* env)
|
|||||||
return registerFrameworkNatives(env);
|
return registerFrameworkNatives(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_getRandomParcel(JNIEnv *env, jobject thiz, jobject jparcel, jbyteArray fuzzData) {
|
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_fillParcelInternal(JNIEnv *env, jobject thiz, jobject jparcel, jbyteArray fuzzData) {
|
||||||
size_t len = static_cast<size_t>(env->GetArrayLength(fuzzData));
|
size_t len = static_cast<size_t>(env->GetArrayLength(fuzzData));
|
||||||
uint8_t data[len];
|
uint8_t data[len];
|
||||||
env->GetByteArrayRegion(fuzzData, 0, len, reinterpret_cast<jbyte*>(data));
|
env->GetByteArrayRegion(fuzzData, 0, len, reinterpret_cast<jbyte*>(data));
|
||||||
|
|||||||
@@ -24,5 +24,5 @@ extern "C" {
|
|||||||
// Function from AndroidRuntime
|
// Function from AndroidRuntime
|
||||||
jint registerFrameworkNatives(JNIEnv* env);
|
jint registerFrameworkNatives(JNIEnv* env);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_getRandomParcel(JNIEnv *env, jobject thiz, jobject parcel, jbyteArray fuzzData);
|
JNIEXPORT void JNICALL Java_randomparcel_FuzzBinder_fillParcelInternal(JNIEnv *env, jobject thiz, jobject parcel, jbyteArray fuzzData);
|
||||||
}
|
}
|
||||||
|
|||||||
40
core/tests/fuzzers/ParcelFuzzer/Android.bp
Normal file
40
core/tests/fuzzers/ParcelFuzzer/Android.bp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package {
|
||||||
|
default_applicable_licenses: ["frameworks_base_license"],
|
||||||
|
}
|
||||||
|
|
||||||
|
java_fuzz {
|
||||||
|
name: "java_binder_parcel_fuzzer",
|
||||||
|
srcs: [
|
||||||
|
"ParcelFuzzer.java",
|
||||||
|
"ReadUtils.java",
|
||||||
|
"FuzzUtils.java",
|
||||||
|
"FuzzOperation.java",
|
||||||
|
"ReadOperation.java",
|
||||||
|
":framework-core-sources-for-fuzzers",
|
||||||
|
],
|
||||||
|
static_libs: [
|
||||||
|
"jazzer",
|
||||||
|
"random_parcel_lib",
|
||||||
|
"binderReadParcelIface-java",
|
||||||
|
],
|
||||||
|
jni_libs: [
|
||||||
|
"librandom_parcel_jni",
|
||||||
|
"libc++",
|
||||||
|
"libandroid_runtime",
|
||||||
|
],
|
||||||
|
libs: [
|
||||||
|
"framework",
|
||||||
|
"unsupportedappusage",
|
||||||
|
"ext",
|
||||||
|
"framework-res",
|
||||||
|
],
|
||||||
|
native_bridge_supported: true,
|
||||||
|
fuzz_config: {
|
||||||
|
cc: [
|
||||||
|
"smoreland@google.com",
|
||||||
|
"waghpawan@google.com",
|
||||||
|
],
|
||||||
|
// Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer
|
||||||
|
hotlists: ["4637097"],
|
||||||
|
},
|
||||||
|
}
|
||||||
22
core/tests/fuzzers/ParcelFuzzer/FuzzOperation.java
Normal file
22
core/tests/fuzzers/ParcelFuzzer/FuzzOperation.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package parcelfuzzer;
|
||||||
|
|
||||||
|
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||||
|
|
||||||
|
public interface FuzzOperation {
|
||||||
|
void doFuzz(FuzzedDataProvider data);
|
||||||
|
}
|
||||||
87
core/tests/fuzzers/ParcelFuzzer/FuzzUtils.java
Normal file
87
core/tests/fuzzers/ParcelFuzzer/FuzzUtils.java
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package parcelfuzzer;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
|
||||||
|
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||||
|
|
||||||
|
import randomparcel.FuzzBinder;
|
||||||
|
|
||||||
|
public class FuzzUtils {
|
||||||
|
public static FuzzOperation[] FUZZ_OPERATIONS =
|
||||||
|
new FuzzOperation[] {
|
||||||
|
new FuzzOperation() {
|
||||||
|
@java.lang.Override
|
||||||
|
public void doFuzz(FuzzedDataProvider provider) {
|
||||||
|
// Fuzz Append
|
||||||
|
int start = provider.consumeInt();
|
||||||
|
int len = provider.consumeInt();
|
||||||
|
Parcel p1 = null;
|
||||||
|
Parcel p2 = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
p1 = Parcel.obtain();
|
||||||
|
p2 = Parcel.obtain();
|
||||||
|
|
||||||
|
byte[] data =
|
||||||
|
provider.consumeBytes(
|
||||||
|
provider.consumeInt(0, provider.remainingBytes()));
|
||||||
|
FuzzBinder.fillRandomParcel(p1, data);
|
||||||
|
FuzzBinder.fillRandomParcel(p2, provider.consumeRemainingAsBytes());
|
||||||
|
|
||||||
|
p1.appendFrom(p2, start, len);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Rethrow exception as runtime exceptions are catched
|
||||||
|
// at highest level.
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
p1.recycle();
|
||||||
|
p2.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new FuzzOperation() {
|
||||||
|
@java.lang.Override
|
||||||
|
public void doFuzz(FuzzedDataProvider provider) {
|
||||||
|
// Fuzz Read
|
||||||
|
// Use maximum bytes to generate read instructions and remaining for parcel
|
||||||
|
// creation
|
||||||
|
int maxParcelBytes = provider.remainingBytes() / 3;
|
||||||
|
byte[] data = provider.consumeBytes(maxParcelBytes);
|
||||||
|
Parcel randomParcel = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
randomParcel = Parcel.obtain();
|
||||||
|
FuzzBinder.fillRandomParcel(randomParcel, data);
|
||||||
|
|
||||||
|
while (provider.remainingBytes() > 0) {
|
||||||
|
provider.pickValue(ReadUtils.READ_OPERATIONS)
|
||||||
|
.readParcel(randomParcel, provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Rethrow exception as runtime exceptions are catched
|
||||||
|
// at highest level.
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
randomParcel.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
42
core/tests/fuzzers/ParcelFuzzer/ParcelFuzzer.java
Normal file
42
core/tests/fuzzers/ParcelFuzzer/ParcelFuzzer.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package parcelfuzzer;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||||
|
|
||||||
|
import randomparcel.FuzzBinder;
|
||||||
|
|
||||||
|
public class ParcelFuzzer {
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Initialize JNI dependencies
|
||||||
|
FuzzBinder.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fuzzerTestOneInput(FuzzedDataProvider provider) {
|
||||||
|
// Default behavior for Java APIs is to throw RuntimeException.
|
||||||
|
// We need to fuzz to detect other problems which are not handled explicitly.
|
||||||
|
// TODO(b/150808347): Change known API exceptions to subclass of
|
||||||
|
// RuntimeExceptions and catch those only.
|
||||||
|
try {
|
||||||
|
provider.pickValue(FuzzUtils.FUZZ_OPERATIONS).doFuzz(provider);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Log.e("ParcelFuzzer", "Exception occurred while fuzzing ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
core/tests/fuzzers/ParcelFuzzer/ReadOperation.java
Normal file
24
core/tests/fuzzers/ParcelFuzzer/ReadOperation.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package parcelfuzzer;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
|
||||||
|
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
|
||||||
|
|
||||||
|
public interface ReadOperation {
|
||||||
|
void readParcel(Parcel parcel, FuzzedDataProvider provider);
|
||||||
|
}
|
||||||
435
core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
Normal file
435
core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package parcelfuzzer;
|
||||||
|
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.IInterface;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import parcelables.EmptyParcelable;
|
||||||
|
import parcelables.GenericDataParcelable;
|
||||||
|
import parcelables.SingleDataParcelable;
|
||||||
|
|
||||||
|
public class ReadUtils {
|
||||||
|
public static int MAX_LEN = 1000000;
|
||||||
|
public static int MIN_LEN = 0;
|
||||||
|
|
||||||
|
private static class SomeParcelable implements Parcelable {
|
||||||
|
private final int mValue;
|
||||||
|
|
||||||
|
private SomeParcelable(Parcel in) {
|
||||||
|
this.mValue = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
|
out.writeInt(mValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Parcelable.Creator<SomeParcelable> CREATOR =
|
||||||
|
new Parcelable.Creator<SomeParcelable>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SomeParcelable createFromParcel(Parcel source) {
|
||||||
|
return new SomeParcelable(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SomeParcelable[] newArray(int size) {
|
||||||
|
return new SomeParcelable[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestClassLoader extends ClassLoader {
|
||||||
|
TestClassLoader() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestInterface implements IInterface {
|
||||||
|
public Binder binder;
|
||||||
|
private static final String DESCRIPTOR = "TestInterface";
|
||||||
|
|
||||||
|
TestInterface() {
|
||||||
|
binder = new Binder();
|
||||||
|
binder.attachInterface(this, DESCRIPTOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBinder asBinder() {
|
||||||
|
return binder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestInterface asInterface(IBinder binder) {
|
||||||
|
if (binder != null) {
|
||||||
|
IInterface iface = binder.queryLocalInterface(DESCRIPTOR);
|
||||||
|
if (iface != null && iface instanceof TestInterface) {
|
||||||
|
return (TestInterface) iface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ReadOperation[] READ_OPERATIONS =
|
||||||
|
new ReadOperation[] {
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.setDataPosition(provider.consumeInt());
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.setDataCapacity(provider.consumeInt());
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.setDataSize(provider.consumeInt());
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.dataSize();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.dataPosition();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.dataCapacity();
|
||||||
|
},
|
||||||
|
|
||||||
|
// read basic types
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readByte();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readBoolean();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readInt();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readLong();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readFloat();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readDouble();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readString();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readString8();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readString16();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readBlob();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readStrongBinder();
|
||||||
|
},
|
||||||
|
|
||||||
|
// read arrays of random length
|
||||||
|
(parcel, provider) -> {
|
||||||
|
byte[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new byte[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new byte[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readByteArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
char[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new char[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new char[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readCharArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
int[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new int[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new int[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readIntArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
double[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new double[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new double[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readDoubleArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
float[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new float[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new float[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readFloatArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
boolean[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new boolean[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new boolean[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readBooleanArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
long[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new long[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new long[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readLongArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
IBinder[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new IBinder[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new IBinder[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readBinderArray(array);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
ArrayList<IBinder> arrayList = new ArrayList<IBinder>();
|
||||||
|
parcel.readBinderList(arrayList);
|
||||||
|
},
|
||||||
|
|
||||||
|
// unmarshall from random parcel data and random bytes
|
||||||
|
(parcel, provider) -> {
|
||||||
|
byte[] data = parcel.marshall();
|
||||||
|
Parcel p = Parcel.obtain();
|
||||||
|
p.unmarshall(data, provider.consumeInt(), provider.consumeInt());
|
||||||
|
p.recycle();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
byte[] data = provider.consumeRemainingAsBytes();
|
||||||
|
Parcel p = Parcel.obtain();
|
||||||
|
p.unmarshall(data, provider.consumeInt(), provider.consumeInt());
|
||||||
|
p.recycle();
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.hasFileDescriptors(provider.consumeInt(), provider.consumeInt());
|
||||||
|
},
|
||||||
|
|
||||||
|
// read AIDL generated parcelables
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelable(loader, SingleDataParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelableArray(loader, SingleDataParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
SingleDataParcelable[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new SingleDataParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new SingleDataParcelable[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readTypedArray(array, SingleDataParcelable.CREATOR);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelable(loader, EmptyParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelableArray(loader, EmptyParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
EmptyParcelable[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new EmptyParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new EmptyParcelable[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readTypedArray(array, EmptyParcelable.CREATOR);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelable(loader, GenericDataParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelableArray(loader, GenericDataParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
GenericDataParcelable[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new GenericDataParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
int len = provider.consumeInt(MIN_LEN, MAX_LEN);
|
||||||
|
array = new GenericDataParcelable[len];
|
||||||
|
}
|
||||||
|
parcel.readTypedArray(array, GenericDataParcelable.CREATOR);
|
||||||
|
},
|
||||||
|
|
||||||
|
// read parcelables
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelable(loader, SomeParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelableArray(loader, SomeParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
SomeParcelable[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new SomeParcelable[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new SomeParcelable[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readTypedArray(array, SomeParcelable.CREATOR);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelableArray(loader);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.hasFileDescriptors(provider.consumeInt(), provider.consumeInt());
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readParcelableArray(loader);
|
||||||
|
},
|
||||||
|
|
||||||
|
// read lists
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readArrayList(loader);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readArrayList(loader, Object.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readArrayList(loader, SomeParcelable.class);
|
||||||
|
},
|
||||||
|
|
||||||
|
// read sparse arrays
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readSparseArray(loader);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readSparseArray(loader, Object.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readSparseArray(loader, SomeParcelable.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readSerializable(loader, Object.class);
|
||||||
|
},
|
||||||
|
|
||||||
|
// read interface
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestInterface[] array;
|
||||||
|
if (provider.consumeBoolean()) {
|
||||||
|
int pos = parcel.dataPosition();
|
||||||
|
array = new TestInterface[Math.min(MAX_LEN, parcel.readInt())];
|
||||||
|
parcel.setDataPosition(pos);
|
||||||
|
} else {
|
||||||
|
array = new TestInterface[provider.consumeInt(MIN_LEN, MAX_LEN)];
|
||||||
|
}
|
||||||
|
parcel.readInterfaceArray(array, TestInterface::asInterface);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
int w = provider.consumeInt(MIN_LEN, MAX_LEN);
|
||||||
|
int h = provider.consumeInt(MIN_LEN, MAX_LEN);
|
||||||
|
TestInterface[][] array = new TestInterface[w][h];
|
||||||
|
parcel.readFixedArray(array, TestInterface::asInterface);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
ArrayList<TestInterface> array = new ArrayList<TestInterface>();
|
||||||
|
parcel.readInterfaceList(array, TestInterface::asInterface);
|
||||||
|
},
|
||||||
|
|
||||||
|
// read bundle
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readBundle(loader);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
parcel.readBundle();
|
||||||
|
},
|
||||||
|
|
||||||
|
// read HashMap
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readHashMap(loader);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readHashMap(loader, String.class, String.class);
|
||||||
|
},
|
||||||
|
(parcel, provider) -> {
|
||||||
|
HashMap<String, String> hashMap = new HashMap<>();
|
||||||
|
TestClassLoader loader = new TestClassLoader();
|
||||||
|
parcel.readMap(hashMap, loader, String.class, String.class);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user