Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d4206be authored by Andy Hung's avatar Andy Hung Committed by Automerger Merge Worker
Browse files

Merge "Parcel: Add vector read size bounds check" am: e684a8b8

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1543985

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I8d0c516cf77735067ee04d0702b3a58f22b42386
parents 93a3c0b6 e684a8b8
Loading
Loading
Loading
Loading
+28 −3
Original line number Diff line number Diff line
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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;
+16 −8
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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;
@@ -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;
@@ -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;
    }
@@ -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;
    }
@@ -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;
    }
@@ -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;
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {