Loading libs/binder/Parcel.cpp +28 −3 Original line number Diff line number Diff line Loading @@ -1477,6 +1477,31 @@ data_unsorted: goto data_sorted; } status_t Parcel::readVectorSizeWithCoarseBoundCheck(int32_t *size) const { int32_t requestedSize; const status_t status = readInt32(&requestedSize); if (status != NO_ERROR) return status; // We permit negative sizes, which indicate presence of a nullable vector, // i.e. a vector embedded in std::optional, std::unique_ptr, or std::shared_ptr. if (requestedSize > 0) { // Check if there are fewer bytes than vector elements. // A lower bound is 1 byte per element, satisfied by some enum and int8_t and uint8_t. const size_t availableBytes = dataAvail(); if (static_cast<size_t>(requestedSize) > availableBytes) { // We have a size that is greater than the number of bytes available. // On bounds failure we do not 'rewind' position by 4 bytes of the size already read. ALOGW("%s: rejecting out of bounds vector size (requestedSize):%d " "Parcel{dataAvail:%zu mDataSize:%zu mDataPos:%zu mDataCapacity:%zu}", __func__, requestedSize, availableBytes, mDataSize, mDataPos, mDataCapacity); return BAD_VALUE; } } *size = requestedSize; return NO_ERROR; } status_t Parcel::read(void* outData, size_t len) const { if (len > INT32_MAX) { Loading Loading @@ -1699,7 +1724,7 @@ status_t Parcel::readDoubleVector(std::vector<double>* val) const { status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { const int32_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -1721,7 +1746,7 @@ status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { const int32_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -1742,7 +1767,7 @@ status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { status_t Parcel::readBoolVector(std::vector<bool>* val) const { int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); if (status != OK) { return status; Loading libs/binder/include/binder/Parcel.h +16 −8 Original line number Diff line number Diff line Loading @@ -517,6 +517,11 @@ private: void initState(); void scanForFds() const; status_t validateReadData(size_t len) const; // Reads an int32 size and does a coarse bounds check against the number // of available bytes in the Parcel. status_t readVectorSizeWithCoarseBoundCheck(int32_t *size) const; void updateWorkSourceRequestHeaderPosition() const; status_t finishFlattenBinder(const sp<IBinder>& binder); Loading Loading @@ -787,6 +792,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; // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here status_t err = readInt32(&size); if (err != NO_ERROR) { return err; Loading @@ -802,6 +808,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; // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here status_t err = readInt32(&size); if (err != NO_ERROR) { return err; Loading @@ -818,6 +825,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; // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here status_t err = readInt32(&size); if (err != NO_ERROR) { return err; Loading @@ -834,7 +842,7 @@ status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const { template<typename T> status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const { int32_t read_size; status_t err = readInt32(&read_size); status_t err = readVectorSizeWithCoarseBoundCheck(&read_size); if (err != NO_ERROR) { return err; } Loading @@ -850,7 +858,7 @@ status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const { template<typename T> status_t Parcel::reserveOutVector(std::optional<std::vector<T>>* val, size_t* size) const { int32_t read_size; status_t err = readInt32(&read_size); status_t err = readVectorSizeWithCoarseBoundCheck(&read_size); if (err != NO_ERROR) { return err; } Loading @@ -870,7 +878,7 @@ template<typename T> status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val, size_t* size) const { int32_t read_size; status_t err = readInt32(&read_size); status_t err = readVectorSizeWithCoarseBoundCheck(&read_size); if (err != NO_ERROR) { return err; } Loading Loading @@ -923,7 +931,7 @@ status_t Parcel::unsafeReadTypedVector( std::vector<T>* val, status_t(Parcel::*read_func)(U*) const) const { int32_t size; status_t status = this->readInt32(&size); status_t status = this->readVectorSizeWithCoarseBoundCheck(&size); if (status != OK) { return status; Loading Loading @@ -965,7 +973,7 @@ status_t Parcel::readNullableTypedVector(std::optional<std::vector<T>>* val, status_t(Parcel::*read_func)(T*) const) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -989,7 +997,7 @@ status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val, status_t(Parcel::*read_func)(T*) const) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading Loading @@ -1093,7 +1101,7 @@ template<typename T> status_t Parcel::readParcelableVector(std::optional<std::vector<std::optional<T>>>* val) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -1117,7 +1125,7 @@ template<typename T> status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading Loading
libs/binder/Parcel.cpp +28 −3 Original line number Diff line number Diff line Loading @@ -1477,6 +1477,31 @@ data_unsorted: goto data_sorted; } status_t Parcel::readVectorSizeWithCoarseBoundCheck(int32_t *size) const { int32_t requestedSize; const status_t status = readInt32(&requestedSize); if (status != NO_ERROR) return status; // We permit negative sizes, which indicate presence of a nullable vector, // i.e. a vector embedded in std::optional, std::unique_ptr, or std::shared_ptr. if (requestedSize > 0) { // Check if there are fewer bytes than vector elements. // A lower bound is 1 byte per element, satisfied by some enum and int8_t and uint8_t. const size_t availableBytes = dataAvail(); if (static_cast<size_t>(requestedSize) > availableBytes) { // We have a size that is greater than the number of bytes available. // On bounds failure we do not 'rewind' position by 4 bytes of the size already read. ALOGW("%s: rejecting out of bounds vector size (requestedSize):%d " "Parcel{dataAvail:%zu mDataSize:%zu mDataPos:%zu mDataCapacity:%zu}", __func__, requestedSize, availableBytes, mDataSize, mDataPos, mDataCapacity); return BAD_VALUE; } } *size = requestedSize; return NO_ERROR; } status_t Parcel::read(void* outData, size_t len) const { if (len > INT32_MAX) { Loading Loading @@ -1699,7 +1724,7 @@ status_t Parcel::readDoubleVector(std::vector<double>* val) const { status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { const int32_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -1721,7 +1746,7 @@ status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { const int32_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -1742,7 +1767,7 @@ status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { status_t Parcel::readBoolVector(std::vector<bool>* val) const { int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); if (status != OK) { return status; Loading
libs/binder/include/binder/Parcel.h +16 −8 Original line number Diff line number Diff line Loading @@ -517,6 +517,11 @@ private: void initState(); void scanForFds() const; status_t validateReadData(size_t len) const; // Reads an int32 size and does a coarse bounds check against the number // of available bytes in the Parcel. status_t readVectorSizeWithCoarseBoundCheck(int32_t *size) const; void updateWorkSourceRequestHeaderPosition() const; status_t finishFlattenBinder(const sp<IBinder>& binder); Loading Loading @@ -787,6 +792,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; // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here status_t err = readInt32(&size); if (err != NO_ERROR) { return err; Loading @@ -802,6 +808,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; // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here status_t err = readInt32(&size); if (err != NO_ERROR) { return err; Loading @@ -818,6 +825,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; // used for allocating 'out' vector args, do not use readVectorSizeWithCoarseBoundCheck() here status_t err = readInt32(&size); if (err != NO_ERROR) { return err; Loading @@ -834,7 +842,7 @@ status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const { template<typename T> status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const { int32_t read_size; status_t err = readInt32(&read_size); status_t err = readVectorSizeWithCoarseBoundCheck(&read_size); if (err != NO_ERROR) { return err; } Loading @@ -850,7 +858,7 @@ status_t Parcel::reserveOutVector(std::vector<T>* val, size_t* size) const { template<typename T> status_t Parcel::reserveOutVector(std::optional<std::vector<T>>* val, size_t* size) const { int32_t read_size; status_t err = readInt32(&read_size); status_t err = readVectorSizeWithCoarseBoundCheck(&read_size); if (err != NO_ERROR) { return err; } Loading @@ -870,7 +878,7 @@ template<typename T> status_t Parcel::reserveOutVector(std::unique_ptr<std::vector<T>>* val, size_t* size) const { int32_t read_size; status_t err = readInt32(&read_size); status_t err = readVectorSizeWithCoarseBoundCheck(&read_size); if (err != NO_ERROR) { return err; } Loading Loading @@ -923,7 +931,7 @@ status_t Parcel::unsafeReadTypedVector( std::vector<T>* val, status_t(Parcel::*read_func)(U*) const) const { int32_t size; status_t status = this->readInt32(&size); status_t status = this->readVectorSizeWithCoarseBoundCheck(&size); if (status != OK) { return status; Loading Loading @@ -965,7 +973,7 @@ status_t Parcel::readNullableTypedVector(std::optional<std::vector<T>>* val, status_t(Parcel::*read_func)(T*) const) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -989,7 +997,7 @@ status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val, status_t(Parcel::*read_func)(T*) const) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading Loading @@ -1093,7 +1101,7 @@ template<typename T> status_t Parcel::readParcelableVector(std::optional<std::vector<std::optional<T>>>* val) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading @@ -1117,7 +1125,7 @@ template<typename T> status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const { const size_t start = dataPosition(); int32_t size; status_t status = readInt32(&size); status_t status = readVectorSizeWithCoarseBoundCheck(&size); val->reset(); if (status != OK || size < 0) { Loading