Loading libs/binder/tests/parcel_fuzzer/binder.cpp +39 −34 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ struct BigStruct { }; #define PARCEL_READ_WITH_STATUS(T, FUN) \ [] (const ::android::Parcel& p, uint8_t /*data*/) {\ [](const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ T t{}; \ status_t status = p.FUN(&t); \ Loading @@ -82,7 +82,7 @@ struct BigStruct { } #define PARCEL_READ_NO_STATUS(T, FUN) \ [] (const ::android::Parcel& p, uint8_t /*data*/) {\ [](const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status"; \ T t = p.FUN(); \ (void)t; \ Loading @@ -102,7 +102,9 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, dataPosition), PARCEL_READ_NO_STATUS(size_t, dataCapacity), PARCEL_READ_NO_STATUS(::android::binder::Status, enforceNoDataAvail), [] (const ::android::Parcel& p, uint8_t pos) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { // aborts on larger values size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX); FUZZ_LOG() << "about to setDataPosition: " << pos; p.setDataPosition(pos); FUZZ_LOG() << "setDataPosition done"; Loading @@ -111,13 +113,13 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors), PARCEL_READ_NO_STATUS(std::vector<android::sp<android::IBinder>>, debugReadAllStrongBinders), PARCEL_READ_NO_STATUS(std::vector<int>, debugReadAllFileDescriptors), [] (const ::android::Parcel& p, uint8_t len) { std::string interface(len, 'a'); [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { std::string interface = provider.ConsumeRandomLengthString(); FUZZ_LOG() << "about to enforceInterface: " << interface; bool b = p.enforceInterface(::android::String16(interface.c_str())); FUZZ_LOG() << "enforced interface: " << b; }, [] (const ::android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to checkInterface"; android::sp<android::IBinder> aBinder = new android::BBinder(); bool b = p.checkInterface(aBinder.get()); Loading @@ -125,13 +127,16 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { }, PARCEL_READ_NO_STATUS(size_t, objectsCount), PARCEL_READ_NO_STATUS(status_t, errorCheck), [] (const ::android::Parcel& p, uint8_t len) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { // Read at least a bit. Unbounded allocation would OOM. size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); 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) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { size_t len = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readInplace"; const void* r = p.readInplace(len); FUZZ_LOG() << "readInplace done. pointer: " << r << " bytes: " << (r ? HexString(r, len) : "null"); Loading @@ -149,13 +154,13 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::string, readUtf8FromUtf16), PARCEL_READ_WITH_STATUS(std::unique_ptr<std::string>, readUtf8FromUtf16), PARCEL_READ_WITH_STATUS(std::optional<std::string>, readUtf8FromUtf16), [] (const ::android::Parcel& p, uint8_t /*data*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { 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), [] (const ::android::Parcel& p, uint8_t /*data*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readString8Inplace"; size_t outLen = 0; const char* str = p.readString8Inplace(&outLen); Loading @@ -165,7 +170,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_OPT_STATUS(android::String16, readString16), PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16), PARCEL_READ_WITH_STATUS(std::optional<android::String16>, readString16), [] (const ::android::Parcel& p, uint8_t /*data*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readString16Inplace"; size_t outLen = 0; const char16_t* str = p.readString16Inplace(&outLen); Loading Loading @@ -263,13 +268,13 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::optional<std::array<std::array<std::optional<ExampleParcelable> COMMA 3> COMMA 4>>, readFixedArray), #undef COMMA [] (const android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to read flattenable"; ExampleFlattenable f; status_t status = p.read(f); FUZZ_LOG() << "read flattenable: " << status; }, [] (const android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to read lite flattenable"; ExampleLightFlattenable f; status_t status = p.read(f); Loading @@ -284,7 +289,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<BigStruct>>, resizeOutVector), PARCEL_READ_NO_STATUS(int32_t, readExceptionCode), [] (const android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readNativeHandle"; native_handle_t* t = p.readNativeHandle(); FUZZ_LOG() << "readNativeHandle: " << t; Loading @@ -303,15 +308,16 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::optional<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) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { size_t len = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readBlob"; ::android::Parcel::ReadableBlob blob; status_t status = p.readBlob(len, &blob); FUZZ_LOG() << "readBlob status: " << status; }, [] (const android::Parcel& p, uint8_t options) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { FUZZ_LOG() << "about to readObject"; bool nullMetaData = options & 0x1; bool nullMetaData = provider.ConsumeBool(); const void* obj = static_cast<const void*>(p.readObject(nullMetaData)); FUZZ_LOG() << "readObject: " << obj; }, Loading @@ -319,20 +325,19 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize), // additional parcelable objects defined in libbinder [] (const ::android::Parcel& p, uint8_t data) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { using ::android::os::ParcelableHolder; using ::android::Parcelable; FUZZ_LOG() << "about to read ParcelableHolder using readParcelable with status"; Parcelable::Stability stability = Parcelable::Stability::STABILITY_LOCAL; if ( (data & 1) == 1 ) { stability = Parcelable::Stability::STABILITY_VINTF; } Parcelable::Stability stability = provider.ConsumeBool() ? Parcelable::Stability::STABILITY_LOCAL : Parcelable::Stability::STABILITY_VINTF; ParcelableHolder t = ParcelableHolder(stability); status_t status = p.readParcelable(&t); FUZZ_LOG() << "ParcelableHolder status: " << status; }, PARCEL_READ_WITH_STATUS(android::os::PersistableBundle, readParcelable), [] (const ::android::Parcel& p, uint8_t /* data */) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to call hasFileDescriptorsInRange() with status"; size_t offset = p.readUint32(); size_t length = p.readUint32(); Loading @@ -340,7 +345,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { status_t status = p.hasFileDescriptorsInRange(offset, length, &result); FUZZ_LOG() << " status: " << status << " result: " << result; }, [] (const ::android::Parcel& p, uint8_t /* data */) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to call compareDataInRange() with status"; size_t thisOffset = p.readUint32(); size_t otherOffset = p.readUint32(); Loading libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ binder_status_t ISomeInterface::readFromParcel(const AParcel* parcel, } #define PARCEL_READ(T, FUN) \ [](const NdkParcelAdapter& p, uint8_t /*data*/) { \ [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ T t{}; \ binder_status_t status = FUN(p.aParcel(), &t); \ Loading @@ -80,32 +80,37 @@ binder_status_t ISomeInterface::readFromParcel(const AParcel* parcel, // clang-format off std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ // methods from binder_parcel.h [](const NdkParcelAdapter& p, uint8_t pos) { [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) { // aborts on larger values size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX); FUZZ_LOG() << "about to set data position to " << pos; binder_status_t status = AParcel_setDataPosition(p.aParcel(), pos); FUZZ_LOG() << "set data position: " << status; }, [](const NdkParcelAdapter& p, uint8_t /*data*/) { [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to read status header"; ndk::ScopedAStatus t; binder_status_t status = AParcel_readStatusHeader(p.aParcel(), t.getR()); FUZZ_LOG() << "read status header: " << status; }, [](const NdkParcelAdapter& p, uint8_t /*data*/) { [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to getDataSize the parcel"; AParcel_getDataSize(p.aParcel()); FUZZ_LOG() << "getDataSize done"; }, [](const NdkParcelAdapter& p, uint8_t data) { [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) { FUZZ_LOG() << "about to read a ParcelableHolder"; ndk::AParcelableHolder ph {(data % 2 == 1) ? ndk::STABILITY_LOCAL : ndk::STABILITY_VINTF}; ndk::AParcelableHolder ph {provider.ConsumeBool() ? ndk::STABILITY_LOCAL : ndk::STABILITY_VINTF}; binder_status_t status = AParcel_readParcelable(p.aParcel(), &ph); FUZZ_LOG() << "read the ParcelableHolder: " << status; }, [](const NdkParcelAdapter& p, uint8_t data) { FUZZ_LOG() << "about to appendFrom"; [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) { size_t offset = provider.ConsumeIntegral<size_t>(); size_t pos = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to appendFrom " << pos; // TODO: create random parcel AParcel* parcel = AParcel_create(); binder_status_t status = AParcel_appendFrom(p.aParcel(), parcel, 0, data); binder_status_t status = AParcel_appendFrom(p.aParcel(), parcel, offset, pos); AParcel_delete(parcel); FUZZ_LOG() << "appendFrom: " << status; }, Loading libs/binder/tests/parcel_fuzzer/hwbinder.cpp +32 −25 Original line number Diff line number Diff line Loading @@ -36,14 +36,14 @@ std::ostream& operator<<(std::ostream& os, const ::android::sp<::android::hardwa PARCEL_READ_NO_STATUS(T, FUN), PARCEL_READ_WITH_STATUS(T, FUN) #define PARCEL_READ_NO_STATUS(T, FUN) \ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \ 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*/) {\ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ T t; \ status_t status = p.FUN(&t); \ Loading @@ -56,27 +56,30 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI 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) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { // aborts on larger values size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX); FUZZ_LOG() << "about to setDataPosition: " << pos; p.setDataPosition(pos); FUZZ_LOG() << "setDataPosition done"; }, [] (const ::android::hardware::Parcel& p, uint8_t length) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { FUZZ_LOG() << "about to enforceInterface"; std::string interfaceName(length, 'a'); bool okay = p.enforceInterface(interfaceName.c_str()); bool okay = p.enforceInterface(provider.ConsumeRandomLengthString().c_str()); FUZZ_LOG() << "enforceInterface status: " << okay; }, PARCEL_READ_NO_STATUS(size_t, objectsCount), [] (const ::android::hardware::Parcel& p, uint8_t length) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { // Read at least a bit. Unbounded allocation would OOM. size_t length = provider.ConsumeIntegralInRange<size_t>(0, 1024); FUZZ_LOG() << "about to read"; std::vector<uint8_t> data (length); status_t status = p.read(data.data(), length); FUZZ_LOG() << "read status: " << status << " data: " << HexString(data.data(), data.size()); }, [] (const ::android::hardware::Parcel& p, uint8_t length) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t length = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to read"; std::vector<uint8_t> data (length); const void* inplace = p.readInplace(length); FUZZ_LOG() << "read status: " << (inplace ? HexString(inplace, length) : "null"); }, Loading @@ -91,14 +94,14 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI PARCEL_READ_OPT_STATUS(float, readFloat), PARCEL_READ_OPT_STATUS(double, readDouble), PARCEL_READ_OPT_STATUS(bool, readBool), [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readCString"; const char* str = p.readCString(); FUZZ_LOG() << "readCString " << (str ? str : "<null>"); }, PARCEL_READ_OPT_STATUS(::android::String16, readString16), PARCEL_READ_WITH_STATUS(std::unique_ptr<::android::String16>, readString16), [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readString16Inplace"; size_t outSize = 0; const char16_t* str = p.readString16Inplace(&outSize); Loading @@ -106,7 +109,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI }, PARCEL_READ_OPT_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder), PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder), [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readBuffer"; size_t handle = 0; const void* data = nullptr; Loading @@ -116,7 +120,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readNullableBuffer"; size_t handle = 0; const void* data = nullptr; Loading @@ -126,7 +131,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readEmbeddedBuffer"; size_t handle = 0; size_t parent_buffer_handle = 0; Loading @@ -138,7 +144,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readNullableEmbeddedBuffer"; size_t handle = 0; size_t parent_buffer_handle = 0; Loading @@ -150,7 +157,7 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readNativeHandleNoDup"; const native_handle_t* handle = nullptr; status_t status = p.readNativeHandleNoDup(&handle); Loading libs/binder/tests/parcel_fuzzer/main.cpp +6 −11 Original line number Diff line number Diff line Loading @@ -83,19 +83,14 @@ void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize()); FUZZ_LOG() << "instructions: " << HexString(instructions.data(), instructions.size()); for (size_t i = 0; i + 1 < instructions.size(); i += 2) { uint8_t a = instructions[i]; uint8_t readIdx = a % reads.size(); FuzzedDataProvider instructionsProvider(instructions.data(), instructions.size()); while (instructionsProvider.remaining_bytes() > 0) { uint8_t idx = instructionsProvider.ConsumeIntegralInRange<uint8_t>(0, reads.size() - 1); uint8_t b = instructions[i + 1]; FUZZ_LOG() << "Instruction " << idx << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity(); FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2 << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx) << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize() << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity(); reads[readIdx](p, b); reads[idx](p, instructionsProvider); } } Loading libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h +5 −1 Original line number Diff line number Diff line Loading @@ -15,5 +15,9 @@ */ #pragma once #include <fuzzer/FuzzedDataProvider.h> #include <functional> template <typename P> using ParcelRead = std::function<void(const P& p, uint8_t data)>; using ParcelRead = std::function<void(const P& p, FuzzedDataProvider& provider)>; Loading
libs/binder/tests/parcel_fuzzer/binder.cpp +39 −34 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ struct BigStruct { }; #define PARCEL_READ_WITH_STATUS(T, FUN) \ [] (const ::android::Parcel& p, uint8_t /*data*/) {\ [](const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ T t{}; \ status_t status = p.FUN(&t); \ Loading @@ -82,7 +82,7 @@ struct BigStruct { } #define PARCEL_READ_NO_STATUS(T, FUN) \ [] (const ::android::Parcel& p, uint8_t /*data*/) {\ [](const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with no status"; \ T t = p.FUN(); \ (void)t; \ Loading @@ -102,7 +102,9 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, dataPosition), PARCEL_READ_NO_STATUS(size_t, dataCapacity), PARCEL_READ_NO_STATUS(::android::binder::Status, enforceNoDataAvail), [] (const ::android::Parcel& p, uint8_t pos) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { // aborts on larger values size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX); FUZZ_LOG() << "about to setDataPosition: " << pos; p.setDataPosition(pos); FUZZ_LOG() << "setDataPosition done"; Loading @@ -111,13 +113,13 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors), PARCEL_READ_NO_STATUS(std::vector<android::sp<android::IBinder>>, debugReadAllStrongBinders), PARCEL_READ_NO_STATUS(std::vector<int>, debugReadAllFileDescriptors), [] (const ::android::Parcel& p, uint8_t len) { std::string interface(len, 'a'); [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { std::string interface = provider.ConsumeRandomLengthString(); FUZZ_LOG() << "about to enforceInterface: " << interface; bool b = p.enforceInterface(::android::String16(interface.c_str())); FUZZ_LOG() << "enforced interface: " << b; }, [] (const ::android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to checkInterface"; android::sp<android::IBinder> aBinder = new android::BBinder(); bool b = p.checkInterface(aBinder.get()); Loading @@ -125,13 +127,16 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { }, PARCEL_READ_NO_STATUS(size_t, objectsCount), PARCEL_READ_NO_STATUS(status_t, errorCheck), [] (const ::android::Parcel& p, uint8_t len) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { // Read at least a bit. Unbounded allocation would OOM. size_t len = provider.ConsumeIntegralInRange<size_t>(0, 1024); 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) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { size_t len = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readInplace"; const void* r = p.readInplace(len); FUZZ_LOG() << "readInplace done. pointer: " << r << " bytes: " << (r ? HexString(r, len) : "null"); Loading @@ -149,13 +154,13 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::string, readUtf8FromUtf16), PARCEL_READ_WITH_STATUS(std::unique_ptr<std::string>, readUtf8FromUtf16), PARCEL_READ_WITH_STATUS(std::optional<std::string>, readUtf8FromUtf16), [] (const ::android::Parcel& p, uint8_t /*data*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { 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), [] (const ::android::Parcel& p, uint8_t /*data*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readString8Inplace"; size_t outLen = 0; const char* str = p.readString8Inplace(&outLen); Loading @@ -165,7 +170,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_OPT_STATUS(android::String16, readString16), PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16), PARCEL_READ_WITH_STATUS(std::optional<android::String16>, readString16), [] (const ::android::Parcel& p, uint8_t /*data*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readString16Inplace"; size_t outLen = 0; const char16_t* str = p.readString16Inplace(&outLen); Loading Loading @@ -263,13 +268,13 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::optional<std::array<std::array<std::optional<ExampleParcelable> COMMA 3> COMMA 4>>, readFixedArray), #undef COMMA [] (const android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to read flattenable"; ExampleFlattenable f; status_t status = p.read(f); FUZZ_LOG() << "read flattenable: " << status; }, [] (const android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to read lite flattenable"; ExampleLightFlattenable f; status_t status = p.read(f); Loading @@ -284,7 +289,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<BigStruct>>, resizeOutVector), PARCEL_READ_NO_STATUS(int32_t, readExceptionCode), [] (const android::Parcel& p, uint8_t /*len*/) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readNativeHandle"; native_handle_t* t = p.readNativeHandle(); FUZZ_LOG() << "readNativeHandle: " << t; Loading @@ -303,15 +308,16 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_WITH_STATUS(std::optional<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) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { size_t len = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readBlob"; ::android::Parcel::ReadableBlob blob; status_t status = p.readBlob(len, &blob); FUZZ_LOG() << "readBlob status: " << status; }, [] (const android::Parcel& p, uint8_t options) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { FUZZ_LOG() << "about to readObject"; bool nullMetaData = options & 0x1; bool nullMetaData = provider.ConsumeBool(); const void* obj = static_cast<const void*>(p.readObject(nullMetaData)); FUZZ_LOG() << "readObject: " << obj; }, Loading @@ -319,20 +325,19 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize), // additional parcelable objects defined in libbinder [] (const ::android::Parcel& p, uint8_t data) { [] (const ::android::Parcel& p, FuzzedDataProvider& provider) { using ::android::os::ParcelableHolder; using ::android::Parcelable; FUZZ_LOG() << "about to read ParcelableHolder using readParcelable with status"; Parcelable::Stability stability = Parcelable::Stability::STABILITY_LOCAL; if ( (data & 1) == 1 ) { stability = Parcelable::Stability::STABILITY_VINTF; } Parcelable::Stability stability = provider.ConsumeBool() ? Parcelable::Stability::STABILITY_LOCAL : Parcelable::Stability::STABILITY_VINTF; ParcelableHolder t = ParcelableHolder(stability); status_t status = p.readParcelable(&t); FUZZ_LOG() << "ParcelableHolder status: " << status; }, PARCEL_READ_WITH_STATUS(android::os::PersistableBundle, readParcelable), [] (const ::android::Parcel& p, uint8_t /* data */) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to call hasFileDescriptorsInRange() with status"; size_t offset = p.readUint32(); size_t length = p.readUint32(); Loading @@ -340,7 +345,7 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { status_t status = p.hasFileDescriptorsInRange(offset, length, &result); FUZZ_LOG() << " status: " << status << " result: " << result; }, [] (const ::android::Parcel& p, uint8_t /* data */) { [] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to call compareDataInRange() with status"; size_t thisOffset = p.readUint32(); size_t otherOffset = p.readUint32(); Loading
libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +14 −9 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ binder_status_t ISomeInterface::readFromParcel(const AParcel* parcel, } #define PARCEL_READ(T, FUN) \ [](const NdkParcelAdapter& p, uint8_t /*data*/) { \ [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ T t{}; \ binder_status_t status = FUN(p.aParcel(), &t); \ Loading @@ -80,32 +80,37 @@ binder_status_t ISomeInterface::readFromParcel(const AParcel* parcel, // clang-format off std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ // methods from binder_parcel.h [](const NdkParcelAdapter& p, uint8_t pos) { [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) { // aborts on larger values size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX); FUZZ_LOG() << "about to set data position to " << pos; binder_status_t status = AParcel_setDataPosition(p.aParcel(), pos); FUZZ_LOG() << "set data position: " << status; }, [](const NdkParcelAdapter& p, uint8_t /*data*/) { [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to read status header"; ndk::ScopedAStatus t; binder_status_t status = AParcel_readStatusHeader(p.aParcel(), t.getR()); FUZZ_LOG() << "read status header: " << status; }, [](const NdkParcelAdapter& p, uint8_t /*data*/) { [](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to getDataSize the parcel"; AParcel_getDataSize(p.aParcel()); FUZZ_LOG() << "getDataSize done"; }, [](const NdkParcelAdapter& p, uint8_t data) { [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) { FUZZ_LOG() << "about to read a ParcelableHolder"; ndk::AParcelableHolder ph {(data % 2 == 1) ? ndk::STABILITY_LOCAL : ndk::STABILITY_VINTF}; ndk::AParcelableHolder ph {provider.ConsumeBool() ? ndk::STABILITY_LOCAL : ndk::STABILITY_VINTF}; binder_status_t status = AParcel_readParcelable(p.aParcel(), &ph); FUZZ_LOG() << "read the ParcelableHolder: " << status; }, [](const NdkParcelAdapter& p, uint8_t data) { FUZZ_LOG() << "about to appendFrom"; [](const NdkParcelAdapter& p, FuzzedDataProvider& provider) { size_t offset = provider.ConsumeIntegral<size_t>(); size_t pos = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to appendFrom " << pos; // TODO: create random parcel AParcel* parcel = AParcel_create(); binder_status_t status = AParcel_appendFrom(p.aParcel(), parcel, 0, data); binder_status_t status = AParcel_appendFrom(p.aParcel(), parcel, offset, pos); AParcel_delete(parcel); FUZZ_LOG() << "appendFrom: " << status; }, Loading
libs/binder/tests/parcel_fuzzer/hwbinder.cpp +32 −25 Original line number Diff line number Diff line Loading @@ -36,14 +36,14 @@ std::ostream& operator<<(std::ostream& os, const ::android::sp<::android::hardwa PARCEL_READ_NO_STATUS(T, FUN), PARCEL_READ_WITH_STATUS(T, FUN) #define PARCEL_READ_NO_STATUS(T, FUN) \ [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \ 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*/) {\ [](const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { \ FUZZ_LOG() << "about to read " #T " using " #FUN " with status"; \ T t; \ status_t status = p.FUN(&t); \ Loading @@ -56,27 +56,30 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI 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) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { // aborts on larger values size_t pos = provider.ConsumeIntegralInRange<size_t>(0, INT32_MAX); FUZZ_LOG() << "about to setDataPosition: " << pos; p.setDataPosition(pos); FUZZ_LOG() << "setDataPosition done"; }, [] (const ::android::hardware::Parcel& p, uint8_t length) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { FUZZ_LOG() << "about to enforceInterface"; std::string interfaceName(length, 'a'); bool okay = p.enforceInterface(interfaceName.c_str()); bool okay = p.enforceInterface(provider.ConsumeRandomLengthString().c_str()); FUZZ_LOG() << "enforceInterface status: " << okay; }, PARCEL_READ_NO_STATUS(size_t, objectsCount), [] (const ::android::hardware::Parcel& p, uint8_t length) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { // Read at least a bit. Unbounded allocation would OOM. size_t length = provider.ConsumeIntegralInRange<size_t>(0, 1024); FUZZ_LOG() << "about to read"; std::vector<uint8_t> data (length); status_t status = p.read(data.data(), length); FUZZ_LOG() << "read status: " << status << " data: " << HexString(data.data(), data.size()); }, [] (const ::android::hardware::Parcel& p, uint8_t length) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t length = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to read"; std::vector<uint8_t> data (length); const void* inplace = p.readInplace(length); FUZZ_LOG() << "read status: " << (inplace ? HexString(inplace, length) : "null"); }, Loading @@ -91,14 +94,14 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI PARCEL_READ_OPT_STATUS(float, readFloat), PARCEL_READ_OPT_STATUS(double, readDouble), PARCEL_READ_OPT_STATUS(bool, readBool), [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readCString"; const char* str = p.readCString(); FUZZ_LOG() << "readCString " << (str ? str : "<null>"); }, PARCEL_READ_OPT_STATUS(::android::String16, readString16), PARCEL_READ_WITH_STATUS(std::unique_ptr<::android::String16>, readString16), [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readString16Inplace"; size_t outSize = 0; const char16_t* str = p.readString16Inplace(&outSize); Loading @@ -106,7 +109,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI }, PARCEL_READ_OPT_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder), PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder), [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readBuffer"; size_t handle = 0; const void* data = nullptr; Loading @@ -116,7 +120,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readNullableBuffer"; size_t handle = 0; const void* data = nullptr; Loading @@ -126,7 +131,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readEmbeddedBuffer"; size_t handle = 0; size_t parent_buffer_handle = 0; Loading @@ -138,7 +144,8 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t size) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& provider) { size_t size = provider.ConsumeIntegral<size_t>(); FUZZ_LOG() << "about to readNullableEmbeddedBuffer"; size_t handle = 0; size_t parent_buffer_handle = 0; Loading @@ -150,7 +157,7 @@ std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTI // should be null since we don't create any IPC objects CHECK(data == nullptr) << data; }, [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) { [] (const ::android::hardware::Parcel& p, FuzzedDataProvider& /*provider*/) { FUZZ_LOG() << "about to readNativeHandleNoDup"; const native_handle_t* handle = nullptr; status_t status = p.readNativeHandleNoDup(&handle); Loading
libs/binder/tests/parcel_fuzzer/main.cpp +6 −11 Original line number Diff line number Diff line Loading @@ -83,19 +83,14 @@ void doReadFuzz(const char* backend, const std::vector<ParcelRead<P>>& reads, FUZZ_LOG() << "input: " << HexString(p.data(), p.dataSize()); FUZZ_LOG() << "instructions: " << HexString(instructions.data(), instructions.size()); for (size_t i = 0; i + 1 < instructions.size(); i += 2) { uint8_t a = instructions[i]; uint8_t readIdx = a % reads.size(); FuzzedDataProvider instructionsProvider(instructions.data(), instructions.size()); while (instructionsProvider.remaining_bytes() > 0) { uint8_t idx = instructionsProvider.ConsumeIntegralInRange<uint8_t>(0, reads.size() - 1); uint8_t b = instructions[i + 1]; FUZZ_LOG() << "Instruction " << idx << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity(); FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2 << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx) << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize() << " avail: " << p.dataAvail() << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity(); reads[readIdx](p, b); reads[idx](p, instructionsProvider); } } Loading
libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h +5 −1 Original line number Diff line number Diff line Loading @@ -15,5 +15,9 @@ */ #pragma once #include <fuzzer/FuzzedDataProvider.h> #include <functional> template <typename P> using ParcelRead = std::function<void(const P& p, uint8_t data)>; using ParcelRead = std::function<void(const P& p, FuzzedDataProvider& provider)>;