Loading libs/binder/ndk/include_cpp/android/binder_parcel_utils.h +6 −0 Original line number Diff line number Diff line Loading @@ -910,6 +910,9 @@ static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::v if (err != STATUS_OK) return err; if (size < 0) return STATUS_UNEXPECTED_NULL; // TODO(b/188215728): delegate to libbinder_ndk if (size > 1000000) return STATUS_NO_MEMORY; vec->resize(static_cast<size_t>(size)); return STATUS_OK; } Loading @@ -931,6 +934,9 @@ static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, return STATUS_OK; } // TODO(b/188215728): delegate to libbinder_ndk if (size > 1000000) return STATUS_NO_MEMORY; *vec = std::optional<std::vector<T>>(std::vector<T>{}); (*vec)->resize(static_cast<size_t>(size)); return STATUS_OK; Loading libs/binder/ndk/parcel.cpp +32 −28 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ using ArrayGetter = T (*)(const void* arrayData, size_t index); template <typename T> using ArraySetter = void (*)(void* arrayData, size_t index, T value); binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) { static binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) { // only -1 can be used to represent a null array if (length < -1) return STATUS_BAD_VALUE; Loading @@ -61,12 +62,24 @@ binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int Parcel* rawParcel = parcel->get(); status_t status = rawParcel->writeInt32(static_cast<int32_t>(length)); status_t status = rawParcel->writeInt32(length); if (status != STATUS_OK) return PruneStatusT(status); return STATUS_OK; } static binder_status_t ReadAndValidateArraySize(const AParcel* parcel, int32_t* length) { if (status_t status = parcel->get()->readInt32(length); status != STATUS_OK) { return PruneStatusT(status); } if (*length < -1) return STATUS_BAD_VALUE; // libbinder_ndk reserves these if (*length <= 0) return STATUS_OK; // null if (static_cast<size_t>(*length) > parcel->get()->dataAvail()) return STATUS_NO_MEMORY; return STATUS_OK; } template <typename T> binder_status_t WriteArray(AParcel* parcel, const T* array, int32_t length) { binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length); Loading Loading @@ -111,10 +124,9 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } T* array; if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY; Loading @@ -140,10 +152,9 @@ binder_status_t ReadArray<char16_t>(const AParcel* parcel, void* arrayData, const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } char16_t* array; if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY; Loading @@ -155,7 +166,7 @@ binder_status_t ReadArray<char16_t>(const AParcel* parcel, void* arrayData, if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY; for (int32_t i = 0; i < length; i++) { status = rawParcel->readChar(array + i); status_t status = rawParcel->readChar(array + i); if (status != STATUS_OK) return PruneStatusT(status); } Loading Loading @@ -189,10 +200,9 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; Loading @@ -200,7 +210,7 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator for (int32_t i = 0; i < length; i++) { T readTarget; status = (rawParcel->*read)(&readTarget); status_t status = (rawParcel->*read)(&readTarget); if (status != STATUS_OK) return PruneStatusT(status); setter(arrayData, i, readTarget); Loading Loading @@ -402,13 +412,10 @@ struct StringArrayElementAllocationAdapter { binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData, AParcel_stringArrayAllocator allocator, AParcel_stringArrayElementAllocator elementAllocator) { const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; Loading Loading @@ -449,13 +456,10 @@ binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayD binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData, AParcel_parcelableArrayAllocator allocator, AParcel_readParcelableElement elementReader) { const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; Loading libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +22 −23 Original line number Diff line number Diff line Loading @@ -91,28 +91,27 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ PARCEL_READ(ndk::ScopedFileDescriptor, ndk::AParcel_readRequiredParcelFileDescriptor), PARCEL_READ(std::string, ndk::AParcel_readString), PARCEL_READ(std::optional<std::string>, ndk::AParcel_readString), // TODO(b/131868573): can force process to allocate arbitrary amount of // memory // PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, // ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>, // ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<float>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<double>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector), // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector), PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<float>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<double>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector), PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector), }; // clang-format on Loading
libs/binder/ndk/include_cpp/android/binder_parcel_utils.h +6 −0 Original line number Diff line number Diff line Loading @@ -910,6 +910,9 @@ static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::v if (err != STATUS_OK) return err; if (size < 0) return STATUS_UNEXPECTED_NULL; // TODO(b/188215728): delegate to libbinder_ndk if (size > 1000000) return STATUS_NO_MEMORY; vec->resize(static_cast<size_t>(size)); return STATUS_OK; } Loading @@ -931,6 +934,9 @@ static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, return STATUS_OK; } // TODO(b/188215728): delegate to libbinder_ndk if (size > 1000000) return STATUS_NO_MEMORY; *vec = std::optional<std::vector<T>>(std::vector<T>{}); (*vec)->resize(static_cast<size_t>(size)); return STATUS_OK; Loading
libs/binder/ndk/parcel.cpp +32 −28 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ using ArrayGetter = T (*)(const void* arrayData, size_t index); template <typename T> using ArraySetter = void (*)(void* arrayData, size_t index, T value); binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) { static binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) { // only -1 can be used to represent a null array if (length < -1) return STATUS_BAD_VALUE; Loading @@ -61,12 +62,24 @@ binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int Parcel* rawParcel = parcel->get(); status_t status = rawParcel->writeInt32(static_cast<int32_t>(length)); status_t status = rawParcel->writeInt32(length); if (status != STATUS_OK) return PruneStatusT(status); return STATUS_OK; } static binder_status_t ReadAndValidateArraySize(const AParcel* parcel, int32_t* length) { if (status_t status = parcel->get()->readInt32(length); status != STATUS_OK) { return PruneStatusT(status); } if (*length < -1) return STATUS_BAD_VALUE; // libbinder_ndk reserves these if (*length <= 0) return STATUS_OK; // null if (static_cast<size_t>(*length) > parcel->get()->dataAvail()) return STATUS_NO_MEMORY; return STATUS_OK; } template <typename T> binder_status_t WriteArray(AParcel* parcel, const T* array, int32_t length) { binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length); Loading Loading @@ -111,10 +124,9 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } T* array; if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY; Loading @@ -140,10 +152,9 @@ binder_status_t ReadArray<char16_t>(const AParcel* parcel, void* arrayData, const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } char16_t* array; if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY; Loading @@ -155,7 +166,7 @@ binder_status_t ReadArray<char16_t>(const AParcel* parcel, void* arrayData, if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY; for (int32_t i = 0; i < length; i++) { status = rawParcel->readChar(array + i); status_t status = rawParcel->readChar(array + i); if (status != STATUS_OK) return PruneStatusT(status); } Loading Loading @@ -189,10 +200,9 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; Loading @@ -200,7 +210,7 @@ binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator for (int32_t i = 0; i < length; i++) { T readTarget; status = (rawParcel->*read)(&readTarget); status_t status = (rawParcel->*read)(&readTarget); if (status != STATUS_OK) return PruneStatusT(status); setter(arrayData, i, readTarget); Loading Loading @@ -402,13 +412,10 @@ struct StringArrayElementAllocationAdapter { binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData, AParcel_stringArrayAllocator allocator, AParcel_stringArrayElementAllocator elementAllocator) { const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; Loading Loading @@ -449,13 +456,10 @@ binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayD binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData, AParcel_parcelableArrayAllocator allocator, AParcel_readParcelableElement elementReader) { const Parcel* rawParcel = parcel->get(); int32_t length; status_t status = rawParcel->readInt32(&length); if (status != STATUS_OK) return PruneStatusT(status); if (length < -1) return STATUS_BAD_VALUE; if (binder_status_t status = ReadAndValidateArraySize(parcel, &length); status != STATUS_OK) { return status; } if (!allocator(arrayData, length)) return STATUS_NO_MEMORY; Loading
libs/binder/tests/parcel_fuzzer/binder_ndk.cpp +22 −23 Original line number Diff line number Diff line Loading @@ -91,28 +91,27 @@ std::vector<ParcelRead<NdkParcelAdapter>> BINDER_NDK_PARCEL_READ_FUNCTIONS{ PARCEL_READ(ndk::ScopedFileDescriptor, ndk::AParcel_readRequiredParcelFileDescriptor), PARCEL_READ(std::string, ndk::AParcel_readString), PARCEL_READ(std::optional<std::string>, ndk::AParcel_readString), // TODO(b/131868573): can force process to allocate arbitrary amount of // memory // PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, // ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>, // ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<float>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<double>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector), // PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector), // PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector), // PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector), PARCEL_READ(std::vector<std::string>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<std::optional<std::string>>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<SomeParcelable>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<uint32_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<uint32_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int64_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<int64_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<uint64_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<uint64_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<float>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<float>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<double>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<double>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<bool>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<bool>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<char16_t>, ndk::AParcel_readVector), PARCEL_READ(std::optional<std::vector<char16_t>>, ndk::AParcel_readVector), PARCEL_READ(std::vector<int32_t>, ndk::AParcel_resizeVector), PARCEL_READ(std::optional<std::vector<int32_t>>, ndk::AParcel_resizeVector), }; // clang-format on