Loading libs/binder/Parcel.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -1466,6 +1466,29 @@ const void* Parcel::readInplace(size_t len) const return nullptr; } status_t Parcel::readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const { if (status_t status = readInt32(size); status != OK) return status; if (*size < 0) return OK; // may be null, client to handle LOG_ALWAYS_FATAL_IF(elmSize > INT32_MAX, "Cannot have element as big as %zu", elmSize); // approximation, can't know max element size (e.g. if it makes heap // allocations) static_assert(sizeof(int) == sizeof(int32_t), "Android is LP64"); int32_t allocationSize; if (__builtin_smul_overflow(elmSize, *size, &allocationSize)) return NO_MEMORY; // High limit of 1MB since something this big could never be returned. Could // probably scope this down, but might impact very specific usecases. constexpr int32_t kMaxAllocationSize = 1 * 1000 * 1000; if (allocationSize >= kMaxAllocationSize) { return NO_MEMORY; } return OK; } template<class T> status_t Parcel::readAligned(T *pArg) const { static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); Loading libs/binder/include/binder/Parcel.h +5 −3 Original line number Diff line number Diff line Loading @@ -561,6 +561,8 @@ private: status_t flattenBinder(const sp<IBinder>& binder); status_t unflattenBinder(sp<IBinder>* out) const; status_t readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const; template<class T> status_t readAligned(T *pArg) const; Loading Loading @@ -1315,7 +1317,7 @@ status_t Parcel::writeVectorSize(const std::unique_ptr<std::vector<T>>& val) { template<typename T> status_t Parcel::resizeOutVector(std::vector<T>* val) const { int32_t size; status_t err = readInt32(&size); status_t err = readOutVectorSizeWithCheck(sizeof(T), &size); if (err != NO_ERROR) { return err; } Loading @@ -1330,7 +1332,7 @@ status_t Parcel::resizeOutVector(std::vector<T>* val) const { template<typename T> status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const { int32_t size; status_t err = readInt32(&size); status_t err = readOutVectorSizeWithCheck(sizeof(T), &size); if (err != NO_ERROR) { return err; } Loading @@ -1346,7 +1348,7 @@ status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const { template<typename T> status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const { int32_t size; status_t err = readInt32(&size); status_t err = readOutVectorSizeWithCheck(sizeof(T), &size); if (err != NO_ERROR) { return err; } Loading libs/binder/tests/parcel_fuzzer/binder.cpp +10 −2 Original line number Diff line number Diff line Loading @@ -66,6 +66,10 @@ struct ExampleLightFlattenable : public android::LightFlattenablePod<ExampleLigh int32_t mValue = 0; }; struct BigStruct { uint8_t data[1337]; }; #define PARCEL_READ_WITH_STATUS(T, FUN) \ [] (const ::android::Parcel& p, uint8_t /*data*/) {\ FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\ Loading Loading @@ -231,8 +235,12 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << "read lite flattenable: " << status; }, // TODO(b/131868573): can force read of arbitrarily sized vector // TODO: resizeOutVector PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint8_t>>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::vector<BigStruct>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<BigStruct>>, resizeOutVector), 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*/) { Loading Loading
libs/binder/Parcel.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -1466,6 +1466,29 @@ const void* Parcel::readInplace(size_t len) const return nullptr; } status_t Parcel::readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const { if (status_t status = readInt32(size); status != OK) return status; if (*size < 0) return OK; // may be null, client to handle LOG_ALWAYS_FATAL_IF(elmSize > INT32_MAX, "Cannot have element as big as %zu", elmSize); // approximation, can't know max element size (e.g. if it makes heap // allocations) static_assert(sizeof(int) == sizeof(int32_t), "Android is LP64"); int32_t allocationSize; if (__builtin_smul_overflow(elmSize, *size, &allocationSize)) return NO_MEMORY; // High limit of 1MB since something this big could never be returned. Could // probably scope this down, but might impact very specific usecases. constexpr int32_t kMaxAllocationSize = 1 * 1000 * 1000; if (allocationSize >= kMaxAllocationSize) { return NO_MEMORY; } return OK; } template<class T> status_t Parcel::readAligned(T *pArg) const { static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); Loading
libs/binder/include/binder/Parcel.h +5 −3 Original line number Diff line number Diff line Loading @@ -561,6 +561,8 @@ private: status_t flattenBinder(const sp<IBinder>& binder); status_t unflattenBinder(sp<IBinder>* out) const; status_t readOutVectorSizeWithCheck(size_t elmSize, int32_t* size) const; template<class T> status_t readAligned(T *pArg) const; Loading Loading @@ -1315,7 +1317,7 @@ status_t Parcel::writeVectorSize(const std::unique_ptr<std::vector<T>>& val) { template<typename T> status_t Parcel::resizeOutVector(std::vector<T>* val) const { int32_t size; status_t err = readInt32(&size); status_t err = readOutVectorSizeWithCheck(sizeof(T), &size); if (err != NO_ERROR) { return err; } Loading @@ -1330,7 +1332,7 @@ status_t Parcel::resizeOutVector(std::vector<T>* val) const { template<typename T> status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const { int32_t size; status_t err = readInt32(&size); status_t err = readOutVectorSizeWithCheck(sizeof(T), &size); if (err != NO_ERROR) { return err; } Loading @@ -1346,7 +1348,7 @@ status_t Parcel::resizeOutVector(std::optional<std::vector<T>>* val) const { template<typename T> status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const { int32_t size; status_t err = readInt32(&size); status_t err = readOutVectorSizeWithCheck(sizeof(T), &size); if (err != NO_ERROR) { return err; } Loading
libs/binder/tests/parcel_fuzzer/binder.cpp +10 −2 Original line number Diff line number Diff line Loading @@ -66,6 +66,10 @@ struct ExampleLightFlattenable : public android::LightFlattenablePod<ExampleLigh int32_t mValue = 0; }; struct BigStruct { uint8_t data[1337]; }; #define PARCEL_READ_WITH_STATUS(T, FUN) \ [] (const ::android::Parcel& p, uint8_t /*data*/) {\ FUZZ_LOG() << "about to read " #T " using " #FUN " with status";\ Loading Loading @@ -231,8 +235,12 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS { FUZZ_LOG() << "read lite flattenable: " << status; }, // TODO(b/131868573): can force read of arbitrarily sized vector // TODO: resizeOutVector PARCEL_READ_WITH_STATUS(std::vector<uint8_t>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<uint8_t>>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<uint8_t>>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::vector<BigStruct>, resizeOutVector), PARCEL_READ_WITH_STATUS(std::optional<std::vector<BigStruct>>, resizeOutVector), 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*/) { Loading