Loading libs/binder/include/binder/Parcel.h +27 −0 Original line number Original line Diff line number Diff line Loading @@ -207,6 +207,23 @@ public: status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead"))); status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead"))); status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val); status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val); // Write an IInterface or a vector of IInterface's template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinder(const sp<T>& val) { return writeStrongBinder(T::asBinder(val)); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::vector<sp<T>>& val) { return writeData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::optional<std::vector<sp<T>>>& val) { return writeData(val); } // Write an Enum vector with underlying type int8_t. // Write an Enum vector with underlying type int8_t. // Does not use padding; each byte is contiguous. // Does not use padding; each byte is contiguous. template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> Loading Loading @@ -421,6 +438,16 @@ public: status_t readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const; status_t readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const; status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead"))); status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead"))); status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const; status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const; template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::vector<sp<T>>* val) const { return readData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::optional<std::vector<sp<T>>>* val) const { return readData(val); } status_t readByteVector(std::optional<std::vector<int8_t>>* val) const; status_t readByteVector(std::optional<std::vector<int8_t>>* val) const; status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead"))); status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead"))); Loading libs/binder/ndk/ibinder.cpp +12 −1 Original line number Original line Diff line number Diff line Loading @@ -104,6 +104,17 @@ std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz return {}; return {}; } } // b/175635923 libcxx causes "implicit-conversion" with a string with invalid char static std::string SanitizeString(const String16& str) { std::string sanitized{String8(str)}; for (auto& c : sanitized) { if (!isprint(c)) { c = '?'; } } return sanitized; } bool AIBinder::associateClass(const AIBinder_Class* clazz) { bool AIBinder::associateClass(const AIBinder_Class* clazz) { if (clazz == nullptr) return false; if (clazz == nullptr) return false; Loading @@ -118,7 +129,7 @@ bool AIBinder::associateClass(const AIBinder_Class* clazz) { if (descriptor != newDescriptor) { if (descriptor != newDescriptor) { if (getBinder()->isBinderAlive()) { if (getBinder()->isBinderAlive()) { LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor << "' but descriptor is actually '" << descriptor << "'."; << "' but descriptor is actually '" << SanitizeString(descriptor) << "'."; } else { } else { // b/155793159 // b/155793159 LOG(ERROR) << __func__ << ": Cannot associate class '" << newDescriptor LOG(ERROR) << __func__ << ": Cannot associate class '" << newDescriptor Loading libs/binder/ndk/include_cpp/android/binder_parcel_utils.h +123 −67 Original line number Original line Diff line number Diff line Loading @@ -27,15 +27,67 @@ #pragma once #pragma once #include <android/binder_auto_utils.h> #include <android/binder_auto_utils.h> #include <android/binder_interface_utils.h> #include <android/binder_internal_logging.h> #include <android/binder_internal_logging.h> #include <android/binder_parcel.h> #include <android/binder_parcel.h> #include <optional> #include <optional> #include <string> #include <string> #include <type_traits> #include <vector> #include <vector> namespace ndk { namespace ndk { namespace { template <typename Test, template <typename...> class Ref> struct is_specialization : std::false_type {}; template <template <typename...> class Ref, typename... Args> struct is_specialization<Ref<Args...>, Ref> : std::true_type {}; template <typename Test, template <typename...> class Ref> static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value; // Get the first template type from a container, the T from MyClass<T, ...>. template <typename T> struct first_template_type { using type = void; }; template <template <typename...> class V, typename T, typename... Args> struct first_template_type<V<T, Args...>> { using type = T; }; template <typename T> using first_template_type_t = typename first_template_type<T>::type; // Tells if T represents NDK interface (shared_ptr<ICInterface-derived>) template <typename T> static inline constexpr bool is_interface_v = is_specialization_v<T, std::shared_ptr>&& std::is_base_of_v<::ndk::ICInterface, first_template_type_t<T>>; // Tells if T represents NDK parcelable with readFromParcel/writeToParcel methods defined template <typename T, typename = void> struct is_parcelable : std::false_type {}; template <typename T> struct is_parcelable< T, std::void_t<decltype(std::declval<T>().readFromParcel(std::declval<const AParcel*>())), decltype(std::declval<T>().writeToParcel(std::declval<AParcel*>()))>> : std::true_type {}; template <typename T> static inline constexpr bool is_parcelable_v = is_parcelable<T>::value; // Tells if T represents nullable NDK parcelable (optional<parcelable> or unique_ptr<parcelable>) template <typename T> static inline constexpr bool is_nullable_parcelable_v = is_parcelable_v<first_template_type_t<T>> && (is_specialization_v<T, std::optional> || is_specialization_v<T, std::unique_ptr>); } // namespace /** /** * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. */ */ Loading Loading @@ -429,18 +481,36 @@ static inline binder_status_t AParcel_readVector( */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { if constexpr (is_interface_v<P>) { if (!p) { return STATUS_UNEXPECTED_NULL; } return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_parcelable_v<P>); binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { if (status != STATUS_OK) { return status; return status; } } return p.writeToParcel(parcel); return p.writeToParcel(parcel); } } } /** /** * Convenience API for reading a non-null parcelable. * Convenience API for reading a non-null parcelable. */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { if constexpr (is_interface_v<P>) { binder_status_t status = first_template_type_t<P>::readFromParcel(parcel, p); if (status == STATUS_OK) { if (!*p) { return STATUS_UNEXPECTED_NULL; } } return status; } else { static_assert(is_parcelable_v<P>); int32_t null; int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { if (status != STATUS_OK) { Loading @@ -451,29 +521,17 @@ static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p } } return p->readFromParcel(parcel); return p->readFromParcel(parcel); } } /** * Convenience API for writing a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const std::optional<P>& p) { if (p == std::nullopt) { return AParcel_writeInt32(parcel, 0); // null } binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p->writeToParcel(parcel); } } /** /** * Convenience API for writing a nullable parcelable. * Convenience API for writing a nullable parcelable. */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const P& p) { const std::unique_ptr<P>& p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_nullable_parcelable_v<P>); if (!p) { if (!p) { return AParcel_writeInt32(parcel, 0); // null return AParcel_writeInt32(parcel, 0); // null } } Loading @@ -483,13 +541,16 @@ static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, } } return p->writeToParcel(parcel); return p->writeToParcel(parcel); } } } /** /** * Convenience API for reading a nullable parcelable. * Convenience API for reading a nullable parcelable. */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, P* p) { std::optional<P>* p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::readFromParcel(parcel, p); } else if constexpr (is_specialization_v<P, std::optional>) { int32_t null; int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { if (status != STATUS_OK) { Loading @@ -499,16 +560,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc *p = std::nullopt; *p = std::nullopt; return STATUS_OK; return STATUS_OK; } } *p = std::optional<P>(P{}); *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{}); return (*p)->readFromParcel(parcel); return (*p)->readFromParcel(parcel); } } else { static_assert(is_specialization_v<P, std::unique_ptr>); /** * Convenience API for reading a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, std::unique_ptr<P>* p) { int32_t null; int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { if (status != STATUS_OK) { Loading @@ -518,9 +573,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc p->reset(); p->reset(); return STATUS_OK; return STATUS_OK; } } *p = std::make_unique<P>(); *p = std::make_unique<first_template_type_t<P>>(); return (*p)->readFromParcel(parcel); return (*p)->readFromParcel(parcel); } } } /** /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. Loading libs/binder/rust/src/parcel/parcelable.rs +4 −0 Original line number Original line Diff line number Diff line Loading @@ -702,6 +702,8 @@ impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { } } } } impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {} impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { fn deserialize(parcel: &Parcel) -> Result<Self> { fn deserialize(parcel: &Parcel) -> Result<Self> { let ibinder: SpIBinder = parcel.read()?; let ibinder: SpIBinder = parcel.read()?; Loading @@ -716,6 +718,8 @@ impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { } } } } impl<T: FromIBinder + ?Sized> DeserializeArray for Strong<T> {} // We need these to support Option<&T> for all T // We need these to support Option<&T> for all T impl<T: Serialize + ?Sized> Serialize for &T { impl<T: Serialize + ?Sized> Serialize for &T { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Loading libs/binder/tests/parcel_fuzzer/binder.cpp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -192,6 +192,8 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { // only reading one binder type for now // only reading one binder type for now PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder), PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::os::IServiceManager>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::sp<android::os::IServiceManager>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), Loading Loading
libs/binder/include/binder/Parcel.h +27 −0 Original line number Original line Diff line number Diff line Loading @@ -207,6 +207,23 @@ public: status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead"))); status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead"))); status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val); status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val); // Write an IInterface or a vector of IInterface's template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinder(const sp<T>& val) { return writeStrongBinder(T::asBinder(val)); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::vector<sp<T>>& val) { return writeData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t writeStrongBinderVector(const std::optional<std::vector<sp<T>>>& val) { return writeData(val); } // Write an Enum vector with underlying type int8_t. // Write an Enum vector with underlying type int8_t. // Does not use padding; each byte is contiguous. // Does not use padding; each byte is contiguous. template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0> Loading Loading @@ -421,6 +438,16 @@ public: status_t readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const; status_t readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const; status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead"))); status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead"))); status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const; status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const; template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::vector<sp<T>>* val) const { return readData(val); } template <typename T, std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true> status_t readStrongBinderVector(std::optional<std::vector<sp<T>>>* val) const { return readData(val); } status_t readByteVector(std::optional<std::vector<int8_t>>* val) const; status_t readByteVector(std::optional<std::vector<int8_t>>* val) const; status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead"))); status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead"))); Loading
libs/binder/ndk/ibinder.cpp +12 −1 Original line number Original line Diff line number Diff line Loading @@ -104,6 +104,17 @@ std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz return {}; return {}; } } // b/175635923 libcxx causes "implicit-conversion" with a string with invalid char static std::string SanitizeString(const String16& str) { std::string sanitized{String8(str)}; for (auto& c : sanitized) { if (!isprint(c)) { c = '?'; } } return sanitized; } bool AIBinder::associateClass(const AIBinder_Class* clazz) { bool AIBinder::associateClass(const AIBinder_Class* clazz) { if (clazz == nullptr) return false; if (clazz == nullptr) return false; Loading @@ -118,7 +129,7 @@ bool AIBinder::associateClass(const AIBinder_Class* clazz) { if (descriptor != newDescriptor) { if (descriptor != newDescriptor) { if (getBinder()->isBinderAlive()) { if (getBinder()->isBinderAlive()) { LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor << "' but descriptor is actually '" << descriptor << "'."; << "' but descriptor is actually '" << SanitizeString(descriptor) << "'."; } else { } else { // b/155793159 // b/155793159 LOG(ERROR) << __func__ << ": Cannot associate class '" << newDescriptor LOG(ERROR) << __func__ << ": Cannot associate class '" << newDescriptor Loading
libs/binder/ndk/include_cpp/android/binder_parcel_utils.h +123 −67 Original line number Original line Diff line number Diff line Loading @@ -27,15 +27,67 @@ #pragma once #pragma once #include <android/binder_auto_utils.h> #include <android/binder_auto_utils.h> #include <android/binder_interface_utils.h> #include <android/binder_internal_logging.h> #include <android/binder_internal_logging.h> #include <android/binder_parcel.h> #include <android/binder_parcel.h> #include <optional> #include <optional> #include <string> #include <string> #include <type_traits> #include <vector> #include <vector> namespace ndk { namespace ndk { namespace { template <typename Test, template <typename...> class Ref> struct is_specialization : std::false_type {}; template <template <typename...> class Ref, typename... Args> struct is_specialization<Ref<Args...>, Ref> : std::true_type {}; template <typename Test, template <typename...> class Ref> static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value; // Get the first template type from a container, the T from MyClass<T, ...>. template <typename T> struct first_template_type { using type = void; }; template <template <typename...> class V, typename T, typename... Args> struct first_template_type<V<T, Args...>> { using type = T; }; template <typename T> using first_template_type_t = typename first_template_type<T>::type; // Tells if T represents NDK interface (shared_ptr<ICInterface-derived>) template <typename T> static inline constexpr bool is_interface_v = is_specialization_v<T, std::shared_ptr>&& std::is_base_of_v<::ndk::ICInterface, first_template_type_t<T>>; // Tells if T represents NDK parcelable with readFromParcel/writeToParcel methods defined template <typename T, typename = void> struct is_parcelable : std::false_type {}; template <typename T> struct is_parcelable< T, std::void_t<decltype(std::declval<T>().readFromParcel(std::declval<const AParcel*>())), decltype(std::declval<T>().writeToParcel(std::declval<AParcel*>()))>> : std::true_type {}; template <typename T> static inline constexpr bool is_parcelable_v = is_parcelable<T>::value; // Tells if T represents nullable NDK parcelable (optional<parcelable> or unique_ptr<parcelable>) template <typename T> static inline constexpr bool is_nullable_parcelable_v = is_parcelable_v<first_template_type_t<T>> && (is_specialization_v<T, std::optional> || is_specialization_v<T, std::unique_ptr>); } // namespace /** /** * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. */ */ Loading Loading @@ -429,18 +481,36 @@ static inline binder_status_t AParcel_readVector( */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { if constexpr (is_interface_v<P>) { if (!p) { return STATUS_UNEXPECTED_NULL; } return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_parcelable_v<P>); binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { if (status != STATUS_OK) { return status; return status; } } return p.writeToParcel(parcel); return p.writeToParcel(parcel); } } } /** /** * Convenience API for reading a non-null parcelable. * Convenience API for reading a non-null parcelable. */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { if constexpr (is_interface_v<P>) { binder_status_t status = first_template_type_t<P>::readFromParcel(parcel, p); if (status == STATUS_OK) { if (!*p) { return STATUS_UNEXPECTED_NULL; } } return status; } else { static_assert(is_parcelable_v<P>); int32_t null; int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { if (status != STATUS_OK) { Loading @@ -451,29 +521,17 @@ static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p } } return p->readFromParcel(parcel); return p->readFromParcel(parcel); } } /** * Convenience API for writing a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const std::optional<P>& p) { if (p == std::nullopt) { return AParcel_writeInt32(parcel, 0); // null } binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null if (status != STATUS_OK) { return status; } return p->writeToParcel(parcel); } } /** /** * Convenience API for writing a nullable parcelable. * Convenience API for writing a nullable parcelable. */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const P& p) { const std::unique_ptr<P>& p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::writeToParcel(parcel, p); } else { static_assert(is_nullable_parcelable_v<P>); if (!p) { if (!p) { return AParcel_writeInt32(parcel, 0); // null return AParcel_writeInt32(parcel, 0); // null } } Loading @@ -483,13 +541,16 @@ static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, } } return p->writeToParcel(parcel); return p->writeToParcel(parcel); } } } /** /** * Convenience API for reading a nullable parcelable. * Convenience API for reading a nullable parcelable. */ */ template <typename P> template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, P* p) { std::optional<P>* p) { if constexpr (is_interface_v<P>) { return first_template_type_t<P>::readFromParcel(parcel, p); } else if constexpr (is_specialization_v<P, std::optional>) { int32_t null; int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { if (status != STATUS_OK) { Loading @@ -499,16 +560,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc *p = std::nullopt; *p = std::nullopt; return STATUS_OK; return STATUS_OK; } } *p = std::optional<P>(P{}); *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{}); return (*p)->readFromParcel(parcel); return (*p)->readFromParcel(parcel); } } else { static_assert(is_specialization_v<P, std::unique_ptr>); /** * Convenience API for reading a nullable parcelable. */ template <typename P> static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, std::unique_ptr<P>* p) { int32_t null; int32_t null; binder_status_t status = AParcel_readInt32(parcel, &null); binder_status_t status = AParcel_readInt32(parcel, &null); if (status != STATUS_OK) { if (status != STATUS_OK) { Loading @@ -518,9 +573,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc p->reset(); p->reset(); return STATUS_OK; return STATUS_OK; } } *p = std::make_unique<P>(); *p = std::make_unique<first_template_type_t<P>>(); return (*p)->readFromParcel(parcel); return (*p)->readFromParcel(parcel); } } } /** /** * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. Loading
libs/binder/rust/src/parcel/parcelable.rs +4 −0 Original line number Original line Diff line number Diff line Loading @@ -702,6 +702,8 @@ impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { } } } } impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {} impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { fn deserialize(parcel: &Parcel) -> Result<Self> { fn deserialize(parcel: &Parcel) -> Result<Self> { let ibinder: SpIBinder = parcel.read()?; let ibinder: SpIBinder = parcel.read()?; Loading @@ -716,6 +718,8 @@ impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { } } } } impl<T: FromIBinder + ?Sized> DeserializeArray for Strong<T> {} // We need these to support Option<&T> for all T // We need these to support Option<&T> for all T impl<T: Serialize + ?Sized> Serialize for &T { impl<T: Serialize + ?Sized> Serialize for &T { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Loading
libs/binder/tests/parcel_fuzzer/binder.cpp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -192,6 +192,8 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { // only reading one binder type for now // only reading one binder type for now PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder), PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder), PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::os::IServiceManager>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::sp<android::os::IServiceManager>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector), Loading