Fuzzer for libbinder(_ndk)/libhwbinder
This tests most APIs (except for a couple which have known issues in
them). However, this is now in a place where we can run it in
continuous integration.
Bug: 131861045
Test: m SANITIZE_HOST=address binder_parcel_fuzzer && \
$ANDROID_HOST_OUT/fuzz/x86_64/binder_parcel_fuzzer/binder_parcel_fuzzer
Change-Id: Ic67e5d2bd9c31a3cbc5c526d1c92b9066a4e109e
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
new file mode 100644
index 0000000..f3e4229
--- /dev/null
+++ b/libs/binder/fuzzer/Android.bp
@@ -0,0 +1,31 @@
+cc_fuzz {
+ name: "binder_parcel_fuzzer",
+ host_supported: true,
+ srcs: [
+ "binder.cpp",
+ "hwbinder.cpp",
+ "main.cpp",
+ "util.cpp",
+ ],
+ static_libs: [
+ "libbase",
+ "libbinderthreadstate",
+ "libcgrouprc",
+ "libcgrouprc_format",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libprocessgroup",
+ "libjsoncpp",
+ "libutils",
+ ],
+
+ target: {
+ android: {
+ shared_libs: ["libbinder"],
+ },
+ host: {
+ static_libs: ["libbinder"],
+ },
+ },
+}
diff --git a/libs/binder/fuzzer/binder.cpp b/libs/binder/fuzzer/binder.cpp
new file mode 100644
index 0000000..ce21178
--- /dev/null
+++ b/libs/binder/fuzzer/binder.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "binder"
+
+#include "binder.h"
+#include "util.h"
+
+using ::android::status_t;
+
+#define PARCEL_READ_WITH_STATUS(T, FUN) \
+ [] (const ::android::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\
+ T t{};\
+ status_t status = p.FUN(&t);\
+ FUZZ_LOG() << #T " status: " << status /* << " value: " << t*/;\
+ }
+
+#define PARCEL_READ_NO_STATUS(T, FUN) \
+ [] (const ::android::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
+ T t = p.FUN();\
+ (void) t;\
+ FUZZ_LOG() << #T " done " /* << " value: " << t*/;\
+ }
+
+#define PARCEL_READ_OPT_STATUS(T, FUN) \
+ PARCEL_READ_WITH_STATUS(T, FUN), \
+ PARCEL_READ_NO_STATUS(T, FUN)
+
+std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
+ PARCEL_READ_NO_STATUS(size_t, dataSize),
+ PARCEL_READ_NO_STATUS(size_t, dataAvail),
+ PARCEL_READ_NO_STATUS(size_t, dataPosition),
+ PARCEL_READ_NO_STATUS(size_t, dataCapacity),
+ [] (const ::android::Parcel& p, uint8_t pos) {
+ FUZZ_LOG() << "about to setDataPosition: " << pos;
+ p.setDataPosition(pos);
+ FUZZ_LOG() << "setDataPosition done";
+ },
+ PARCEL_READ_NO_STATUS(size_t, allowFds),
+ PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors),
+ [] (const ::android::Parcel& p, uint8_t len) {
+#ifdef __ANDROID__
+ std::string interface(len, 'a');
+ FUZZ_LOG() << "about to enforceInterface: " << interface;
+ bool b = p.enforceInterface(::android::String16(interface.c_str()));
+ FUZZ_LOG() << "enforced interface: " << b;
+#else
+ FUZZ_LOG() << "skipping enforceInterface";
+ (void)p;
+ (void)len;
+#endif // __ANDROID__
+ },
+ [] (const ::android::Parcel& p, uint8_t /*len*/) {
+#ifdef __ANDROID__
+ FUZZ_LOG() << "about to checkInterface";
+ bool b = p.checkInterface(new android::BBinder());
+ FUZZ_LOG() << "checked interface: " << b;
+#else
+ FUZZ_LOG() << "skipping checkInterface";
+ (void)p;
+#endif // __ANDROID__
+ },
+ PARCEL_READ_NO_STATUS(size_t, objectsCount),
+ PARCEL_READ_NO_STATUS(status_t, errorCheck),
+ [] (const ::android::Parcel& p, uint8_t len) {
+ FUZZ_LOG() << "about to read void*";
+ std::vector<uint8_t> data(len);
+ status_t status = p.read(data.data(), len);
+ FUZZ_LOG() << "read status: " << status;
+ },
+ [] (const ::android::Parcel& p, uint8_t len) {
+ FUZZ_LOG() << "about to readInplace";
+ const void* r = p.readInplace(len);
+ FUZZ_LOG() << "readInplace done. pointer: " << r;
+ },
+ PARCEL_READ_OPT_STATUS(int32_t, readInt32),
+ PARCEL_READ_OPT_STATUS(uint32_t, readUint32),
+ PARCEL_READ_OPT_STATUS(int64_t, readInt64),
+ PARCEL_READ_OPT_STATUS(uint64_t, readUint64),
+ PARCEL_READ_OPT_STATUS(float, readFloat),
+ PARCEL_READ_OPT_STATUS(double, readDouble),
+ PARCEL_READ_OPT_STATUS(intptr_t, readIntPtr),
+ PARCEL_READ_OPT_STATUS(bool, readBool),
+ PARCEL_READ_OPT_STATUS(char16_t, readChar),
+ PARCEL_READ_OPT_STATUS(int8_t, readByte),
+
+ PARCEL_READ_WITH_STATUS(std::string, readUtf8FromUtf16),
+ PARCEL_READ_WITH_STATUS(std::unique_ptr<std::string>, readUtf8FromUtf16),
+ [] (const ::android::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to read c-str";
+ const char* str = p.readCString();
+ FUZZ_LOG() << "read c-str: " << (str ? str : "<empty string>");
+ },
+ PARCEL_READ_OPT_STATUS(android::String8, readString8),
+ PARCEL_READ_OPT_STATUS(android::String16, readString16),
+ PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16),
+ // TODO: readString16Inplace
+ PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readStrongBinder),
+ PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readNullableStrongBinder),
+
+ // TODO: all templated versions of readParcelableVector, readParcelable
+ // TODO: readParcelable
+ // TODO: templated versions of readStrongBinder, readNullableStrongBinder
+
+ // TODO(b/131868573): can force read of arbitrarily sized vector
+ // PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::IBinder>>, readStrongBinderVector),
+
+ // TODO(b/131868573): can force read of arbitrarily sized vector
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int8_t>>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<int8_t>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, readByteVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int32_t>>, readInt32Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<int32_t>, readInt32Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<int64_t>>, readInt64Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<int64_t>, readInt64Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint64_t>>, readUint64Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<uint64_t>, readUint64Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<float>>, readFloatVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<float>, readFloatVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<double>>, readDoubleVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<double>, readDoubleVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<bool>>, readBoolVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<bool>, readBoolVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<char16_t>>, readCharVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<char16_t>, readCharVector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<android::String16>>>, readString16Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<android::String16>, readString16Vector),
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<std::string>>>, readUtf8VectorFromUtf16Vector),
+ // PARCEL_READ_WITH_STATUS(std::vector<std::string>, readUtf8VectorFromUtf16Vector),
+
+ // TODO: read(Flattenable<T>)
+ // TODO: read(LightFlattenable<T>)
+ // TODO: resizeOutVector
+
+ PARCEL_READ_NO_STATUS(int32_t, readExceptionCode),
+ // TODO: readNativeHandle
+ PARCEL_READ_NO_STATUS(int, readFileDescriptor),
+ PARCEL_READ_NO_STATUS(int, readParcelFileDescriptor),
+ PARCEL_READ_WITH_STATUS(android::base::unique_fd, readUniqueFileDescriptor),
+
+ // TODO(b/131868573): can force read of arbitrarily sized vector
+ // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<android::base::unique_fd>>, readUniqueFileDescriptorVector),
+ // PARCEL_READ_WITH_STATUS(std::vector<android::base::unique_fd>, readUniqueFileDescriptorVector),
+
+ [] (const android::Parcel& p, uint8_t len) {
+ FUZZ_LOG() << "about to readBlob";
+ ::android::Parcel::ReadableBlob blob;
+ status_t status = p.readBlob(len, &blob);
+ FUZZ_LOG() << "readBlob status: " << status;
+ },
+ // TODO: readObject
+ PARCEL_READ_NO_STATUS(uid_t, readCallingWorkSourceUid),
+ PARCEL_READ_NO_STATUS(size_t, getBlobAshmemSize),
+ PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize),
+};
diff --git a/libs/binder/fuzzer/binder.h b/libs/binder/fuzzer/binder.h
new file mode 100644
index 0000000..32dcc79
--- /dev/null
+++ b/libs/binder/fuzzer/binder.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <binder/Parcel.h>
+#include <vector>
+
+#include "parcel.h"
+
+extern std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS;
diff --git a/libs/binder/fuzzer/hwbinder.cpp b/libs/binder/fuzzer/hwbinder.cpp
new file mode 100644
index 0000000..b8cce72
--- /dev/null
+++ b/libs/binder/fuzzer/hwbinder.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "hwbinder"
+
+#include "hwbinder.h"
+#include "util.h"
+
+#include <android-base/logging.h>
+#include <hwbinder/Parcel.h>
+
+using ::android::status_t;
+
+// TODO: support scatter-gather types
+
+std::ostream& operator<<(std::ostream& os, const ::android::sp<::android::hardware::IBinder>& binder) {
+ os << binder.get();
+ return os;
+}
+
+#define PARCEL_READ_NO_STATUS(T, FUN) \
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
+ T t = p.FUN();\
+ FUZZ_LOG() << #T " value: " << t;\
+ }
+
+#define PARCEL_READ_WITH_STATUS(T, FUN) \
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
+ FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\
+ T t;\
+ status_t status = p.FUN(&t);\
+ FUZZ_LOG() << #T " status: " << status << " value: " << t;\
+ }
+
+std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS {
+ PARCEL_READ_NO_STATUS(size_t, dataSize),
+ PARCEL_READ_NO_STATUS(size_t, dataAvail),
+ PARCEL_READ_NO_STATUS(size_t, dataPosition),
+ PARCEL_READ_NO_STATUS(size_t, dataCapacity),
+ [] (const ::android::hardware::Parcel& p, uint8_t pos) {
+ FUZZ_LOG() << "about to setDataPosition: " << pos;
+ p.setDataPosition(pos);
+ FUZZ_LOG() << "setDataPosition done";
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t length) {
+ FUZZ_LOG() << "about to enforceInterface";
+ std::string interfaceName(length, 'a');
+ bool okay = p.enforceInterface(interfaceName.c_str());
+ FUZZ_LOG() << "enforceInterface status: " << okay;
+ },
+ PARCEL_READ_NO_STATUS(size_t, objectsCount),
+ PARCEL_READ_WITH_STATUS(int8_t, readInt8),
+ PARCEL_READ_WITH_STATUS(uint8_t, readUint8),
+ PARCEL_READ_WITH_STATUS(int16_t, readInt16),
+ PARCEL_READ_WITH_STATUS(uint16_t, readUint16),
+ PARCEL_READ_WITH_STATUS(int32_t, readInt32),
+ PARCEL_READ_WITH_STATUS(uint32_t, readUint32),
+ PARCEL_READ_WITH_STATUS(int64_t, readInt64),
+ PARCEL_READ_WITH_STATUS(uint64_t, readUint64),
+ PARCEL_READ_WITH_STATUS(float, readFloat),
+ PARCEL_READ_WITH_STATUS(double, readDouble),
+ PARCEL_READ_WITH_STATUS(bool, readBool),
+ PARCEL_READ_WITH_STATUS(::android::String16, readString16),
+ PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
+ PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
+ [] (const ::android::hardware::Parcel& p, uint8_t amount) {
+ FUZZ_LOG() << "about to readInPlace " << amount;
+ const uint8_t* data = (const uint8_t*)p.readInplace(amount);
+ if (data) {
+ std::vector<uint8_t> vdata(data, data + amount);
+ FUZZ_LOG() << "readInPlace " << amount << " data: " << hexString(vdata);
+ } else {
+ FUZZ_LOG() << "readInPlace " << amount << " no data";
+ }
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readBuffer";
+ size_t handle = 0;
+ const void* data = nullptr;
+ status_t status = p.readBuffer(size, &handle, &data);
+ FUZZ_LOG() << "readBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readNullableBuffer";
+ size_t handle = 0;
+ const void* data = nullptr;
+ status_t status = p.readNullableBuffer(size, &handle, &data);
+ FUZZ_LOG() << "readNullableBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readEmbeddedBuffer";
+ size_t handle = 0;
+ size_t parent_buffer_handle = 0;
+ size_t parent_offset = 3;
+ const void* data = nullptr;
+ status_t status = p.readEmbeddedBuffer(size, &handle, parent_buffer_handle, parent_offset, &data);
+ FUZZ_LOG() << "readEmbeddedBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t size) {
+ FUZZ_LOG() << "about to readNullableEmbeddedBuffer";
+ size_t handle = 0;
+ size_t parent_buffer_handle = 0;
+ size_t parent_offset = 3;
+ const void* data = nullptr;
+ status_t status = p.readNullableEmbeddedBuffer(size, &handle, parent_buffer_handle, parent_offset, &data);
+ FUZZ_LOG() << "readNullableEmbeddedBuffer status: " << status << " handle: " << handle << " data: " << data;
+
+ // should be null since we don't create any IPC objects
+ CHECK(data == nullptr) << data;
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readNativeHandleNoDup";
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readNativeHandleNoDup(&handle);
+ FUZZ_LOG() << "readNativeHandleNoDup status: " << status << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ CHECK(status != ::android::OK);
+ },
+ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readNullableNativeHandleNoDup";
+ const native_handle_t* handle = nullptr;
+ status_t status = p.readNullableNativeHandleNoDup(&handle);
+ FUZZ_LOG() << "readNullableNativeHandleNoDup status: " << status << " handle: " << handle;
+
+ // should be null since we don't create any IPC objects
+ CHECK(handle == nullptr) << handle;
+ },
+};
diff --git a/libs/binder/fuzzer/hwbinder.h b/libs/binder/fuzzer/hwbinder.h
new file mode 100644
index 0000000..03ab510
--- /dev/null
+++ b/libs/binder/fuzzer/hwbinder.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <hwbinder/Parcel.h>
+#include <vector>
+
+#include "parcel.h"
+
+extern std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS;
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp
new file mode 100644
index 0000000..03fde3a
--- /dev/null
+++ b/libs/binder/fuzzer/main.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "main"
+
+#include "binder.h"
+#include "hwbinder.h"
+#include "util.h"
+
+#include <android-base/logging.h>
+
+#include <cstdlib>
+#include <ctime>
+
+template <typename P>
+void doFuzz(
+ const std::vector<ParcelRead<P>>& reads,
+ const std::vector<uint8_t>& input,
+ const std::vector<uint8_t>& instructions) {
+
+ P p;
+ p.setData(input.data(), input.size());
+
+ for (size_t i = 0; i < instructions.size() - 1; i += 2) {
+ uint8_t a = instructions[i];
+ uint8_t b = instructions[i + 1];
+
+ FUZZ_LOG() << "size: " << p.dataSize() << " avail: " << p.dataAvail()
+ << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity();
+
+ reads[a % reads.size()](p, b);
+ }
+}
+
+void fuzz(uint8_t options, const std::vector<uint8_t>& input, const std::vector<uint8_t>& instructions) {
+ (void) options;
+
+ // although they will do completely different things, might as well fuzz both
+ doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input, instructions);
+ doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size <= 1) return 0; // no use
+ uint8_t options = *data;
+ data++;
+ size--;
+
+ // TODO: generate 'objects' data
+
+ // data to fill out parcel
+ size_t inputLen = size / 2;
+ std::vector<uint8_t> input(data, data + inputLen);
+ data += inputLen;
+ size -= inputLen;
+
+ // data to use to determine what to do
+ size_t instructionLen = size;
+ std::vector<uint8_t> instructions(data, data + instructionLen);
+ data += instructionLen;
+ size -= instructionLen;
+
+ CHECK(size == 0) << "size: " << size;
+
+ FUZZ_LOG() << "options: " << (int)options << " inputLen: " << inputLen << " instructionLen: " << instructionLen;
+ FUZZ_LOG() << "input: " << hexString(input);
+ FUZZ_LOG() << "instructions: " << hexString(instructions);
+
+ fuzz(options, input, instructions);
+ return 0;
+}
diff --git a/libs/binder/fuzzer/parcel.h b/libs/binder/fuzzer/parcel.h
new file mode 100644
index 0000000..5f05335
--- /dev/null
+++ b/libs/binder/fuzzer/parcel.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+template <typename P>
+using ParcelRead = std::function<void(const P& p, uint8_t data)>;
+
+
diff --git a/libs/binder/fuzzer/util.cpp b/libs/binder/fuzzer/util.cpp
new file mode 100644
index 0000000..b3a4ee7
--- /dev/null
+++ b/libs/binder/fuzzer/util.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+#define FUZZ_LOG_TAG "util"
+#include "util.h"
+
+#include <android-base/logging.h>
+
+#include <iomanip>
+#include <sstream>
+
+std::string hexString(const std::vector<uint8_t>& hash) {
+ std::ostringstream s;
+ s << std::hex << std::setfill('0');
+ for (uint8_t i : hash) {
+ s << std::setw(2) << static_cast<int>(i);
+ }
+ return s.str();
+}
diff --git a/libs/binder/fuzzer/util.h b/libs/binder/fuzzer/util.h
new file mode 100644
index 0000000..07e68a8
--- /dev/null
+++ b/libs/binder/fuzzer/util.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#ifndef FUZZ_LOG_TAG
+#error "Must define FUZZ_LOG_TAG"
+#endif
+
+#define ENABLE_LOG_FUZZ 1
+#define FUZZ_LOG() FuzzLog(FUZZ_LOG_TAG, ENABLE_LOG_FUZZ).log()
+
+class FuzzLog {
+public:
+ FuzzLog(const std::string& tag, bool log) : mTag(tag), mLog(log) {}
+ ~FuzzLog() {
+ if (mLog) {
+ std::cout << mTag << ": " << mOs.str() << std::endl;
+ }
+ }
+
+ std::stringstream& log() {
+ return mOs;
+ }
+
+private:
+ std::string mTag;
+ bool mLog;
+ std::stringstream mOs;
+};
+
+std::string hexString(const std::vector<uint8_t>& hash);