diff options
-rw-r--r-- | libs/binder/RpcState.cpp | 26 | ||||
-rw-r--r-- | libs/binder/Utils.h | 8 |
2 files changed, 25 insertions, 9 deletions
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 28730ffc2b..633fea9b03 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -648,14 +648,21 @@ status_t RpcState::waitForReply(const sp<RpcSession::RpcConnection>& connection, Span<const uint32_t> objectTableSpan; if (session->getProtocolVersion().value() >= RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE) { - Span<const uint8_t> objectTableBytes = parcelSpan.splitOff(rpcReply.parcelDataSize); + std::optional<Span<const uint8_t>> objectTableBytes = + parcelSpan.splitOff(rpcReply.parcelDataSize); + if (!objectTableBytes.has_value()) { + ALOGE("Parcel size larger than available bytes: %" PRId32 " vs %zu. Terminating!", + rpcReply.parcelDataSize, parcelSpan.byteSize()); + (void)session->shutdownAndWait(false); + return BAD_VALUE; + } std::optional<Span<const uint32_t>> maybeSpan = - objectTableBytes.reinterpret<const uint32_t>(); + objectTableBytes->reinterpret<const uint32_t>(); if (!maybeSpan.has_value()) { ALOGE("Bad object table size inferred from RpcWireReply. Saw bodySize=%" PRId32 " sizeofHeader=%zu parcelSize=%" PRId32 " objectTableBytesSize=%zu. Terminating!", command.bodySize, rpcReplyWireSize, rpcReply.parcelDataSize, - objectTableBytes.size); + objectTableBytes->size); return BAD_VALUE; } objectTableSpan = *maybeSpan; @@ -898,15 +905,22 @@ processTransactInternalTailCall: Span<const uint32_t> objectTableSpan; if (session->getProtocolVersion().value() > RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_SIZE) { - Span<const uint8_t> objectTableBytes = parcelSpan.splitOff(transaction->parcelDataSize); + std::optional<Span<const uint8_t>> objectTableBytes = + parcelSpan.splitOff(transaction->parcelDataSize); + if (!objectTableBytes.has_value()) { + ALOGE("Parcel size (%" PRId32 ") greater than available bytes (%zu). Terminating!", + transaction->parcelDataSize, parcelSpan.byteSize()); + (void)session->shutdownAndWait(false); + return BAD_VALUE; + } std::optional<Span<const uint32_t>> maybeSpan = - objectTableBytes.reinterpret<const uint32_t>(); + objectTableBytes->reinterpret<const uint32_t>(); if (!maybeSpan.has_value()) { ALOGE("Bad object table size inferred from RpcWireTransaction. Saw bodySize=%zu " "sizeofHeader=%zu parcelSize=%" PRId32 " objectTableBytesSize=%zu. Terminating!", transactionData.size(), sizeof(RpcWireTransaction), - transaction->parcelDataSize, objectTableBytes.size); + transaction->parcelDataSize, objectTableBytes->size); return BAD_VALUE; } objectTableSpan = *maybeSpan; diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h index 7c6d6f17b1..e04199c75a 100644 --- a/libs/binder/Utils.h +++ b/libs/binder/Utils.h @@ -48,9 +48,11 @@ struct Span { // Truncates `this` to a length of `offset` and returns a span with the // remainder. // - // Aborts if offset > size. - Span<T> splitOff(size_t offset) { - LOG_ALWAYS_FATAL_IF(offset > size); + // `std::nullopt` iff offset > size. + std::optional<Span<T>> splitOff(size_t offset) { + if (offset > size) { + return std::nullopt; + } Span<T> rest = {data + offset, size - offset}; size = offset; return rest; |