/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "parcel.h" #include "securec.h" #include "utils_log.h" namespace OHOS { static const size_t DEFAULT_CPACITY = 204800; // 200K static const size_t CAPACITY_THRESHOLD = 4096; // 4k static const int BINDER_TYPE_HANDLE = 0x73682a85; // binder header type handle static const int BINDER_TYPE_FD = 0x66642a85; // binder header type fd Parcelable::Parcelable() : Parcelable(false) {} Parcelable::Parcelable(bool asRemote) { asRemote_ = asRemote; behavior_ = 0; } Parcel::Parcel(Allocator *allocator) { if (allocator != nullptr) { allocator_ = allocator; } else { allocator_ = new DefaultAllocator(); } writeCursor_ = 0; readCursor_ = 0; data_ = nullptr; dataSize_ = 0; dataCapacity_ = 0; maxDataCapacity_ = DEFAULT_CPACITY; objectOffsets_ = nullptr; nextObjectIdx_ = 0; objectCursor_ = 0; objectsCapacity_ = 0; } Parcel::Parcel() : Parcel(new DefaultAllocator()) {} Parcel::~Parcel() { FlushBuffer(); delete allocator_; allocator_ = nullptr; } size_t Parcel::GetWritableBytes() const { if (dataCapacity_ > writeCursor_) { return dataCapacity_ - writeCursor_; } return 0; } size_t Parcel::GetReadableBytes() const { if (dataSize_ > readCursor_) { return dataSize_ - readCursor_; } return 0; } size_t Parcel::CalcNewCapacity(size_t minNewCapacity) { size_t threshold = CAPACITY_THRESHOLD; if (minNewCapacity == threshold) { return threshold; } // If over threshold, step by threshold. if (minNewCapacity > threshold) { size_t newCapacity = minNewCapacity / threshold * threshold; if ((maxDataCapacity_ > 0) && (newCapacity > maxDataCapacity_ - threshold)) { newCapacity = maxDataCapacity_; } else { newCapacity += threshold; } return newCapacity; } // Not over threshold. Double it. size_t newCapacity = 64; while (newCapacity < minNewCapacity) { // resize capacity by 2 times newCapacity = newCapacity * 2; } if ((maxDataCapacity_ > 0) && (newCapacity > maxDataCapacity_)) { newCapacity = maxDataCapacity_; } return newCapacity; } bool Parcel::EnsureWritableCapacity(size_t desireCapacity) { if (!writable_) { UTILS_LOGW("this parcel data is alloc by driver, which is can not be writen"); return false; } if (desireCapacity <= GetWritableBytes()) { return true; } size_t minNewCapacity = desireCapacity + writeCursor_; size_t newCapacity = CalcNewCapacity(minNewCapacity); if ((newCapacity <= dataCapacity_) || (newCapacity < minNewCapacity)) { UTILS_LOGW("Failed to ensure parcel capacity, newCapacity = %{public}zu, dataCapacity_ = %{public}zu, " "minNewCapacity = %{public}zu", newCapacity, dataCapacity_, minNewCapacity); return false; } if (allocator_ != nullptr) { void *newData = allocator_->Realloc(data_, newCapacity); if (newData != nullptr) { data_ = reinterpret_cast(newData); dataCapacity_ = newCapacity; return true; } UTILS_LOGW("Failed to realloc parcel capacity, newCapacity = %{public}zu, dataCapacity_ = %{public}zu", newCapacity, dataCapacity_); } return false; } bool Parcel::IsReadObjectData(const size_t nextObj, const size_t upperBound) { binder_size_t *objects = objectOffsets_; auto offset = objects[nextObj]; auto currentObject = reinterpret_cast(data_ + offset); if (currentObject->hdr.type == BINDER_TYPE_FD || currentObject->hdr.type == BINDER_TYPE_HANDLE) { return true; } UTILS_LOGE("Non-object Read object data, readPos = %{public}zu, upperBound = %{public}zu", readCursor_, upperBound); return false; } // ValidateReadData only works in basic type read. It doesn't work when read remote object. // And read/write remote object has no effect on "nextObjectIdx_". bool Parcel::ValidateReadData([[maybe_unused]]size_t upperBound) { #ifdef PARCEL_OBJECT_CHECK if (objectOffsets_ == nullptr || objectCursor_ == 0) { return true; } size_t readPos = readCursor_; size_t objSize = objectCursor_; binder_size_t *objects = objectOffsets_; if (nextObjectIdx_ < objSize && upperBound > objects[nextObjectIdx_]) { size_t nextObj = nextObjectIdx_; do { if (readPos < objects[nextObj] + sizeof(parcel_flat_binder_object)) { return IsReadObjectData(nextObj, upperBound); } nextObj++; } while (nextObj < objSize && upperBound > objects[nextObj]); nextObjectIdx_ = nextObj; } #endif return true; } size_t Parcel::GetDataSize() const { return dataSize_; } uintptr_t Parcel::GetData() const { return reinterpret_cast(data_); } binder_size_t Parcel::GetObjectOffsets() const { return reinterpret_cast(objectOffsets_); } size_t Parcel::GetOffsetsSize() const { return objectCursor_; } size_t Parcel::GetDataCapacity() const { return dataCapacity_; } size_t Parcel::GetMaxCapacity() const { return maxDataCapacity_; } bool Parcel::SetMaxCapacity(size_t maxCapacity) { if (maxCapacity > maxDataCapacity_) { maxDataCapacity_ = maxCapacity; return true; } return false; } bool Parcel::SetAllocator(Allocator *allocator) { if ((allocator == nullptr) || (allocator_ == allocator)) { return false; } if ((data_ != nullptr) && (dataSize_ > 0)) { if (allocator_ == nullptr) { return false; } void *newData = allocator->Alloc(dataSize_); if (newData == nullptr) { UTILS_LOGE("Failed to alloc parcel size, dataSize_ = %{public}zu", dataSize_); return false; } if (memcpy_s(newData, dataSize_, data_, dataSize_) != EOK) { allocator->Dealloc(newData); return false; } allocator_->Dealloc(data_); data_ = reinterpret_cast(newData); dataCapacity_ = dataSize_; } delete allocator_; allocator_ = allocator; return true; } bool Parcel::CheckOffsets() { size_t readPos = readCursor_; if ((readPos + sizeof(parcel_flat_binder_object)) > dataSize_) { UTILS_LOGD("CheckOffsets Invalid obj, obj size overflow. objSize:%{public}zu, dataSize:%{public}zu", readPos + sizeof(parcel_flat_binder_object), dataSize_); return false; } size_t objSize = objectCursor_; binder_size_t *objects = objectOffsets_; size_t objCount = 0; while (objCount < objSize) { if (objects[objCount] == readPos) { return true; } objCount++; } UTILS_LOGW("CheckOffsets Invalid obj: obj not found."); return false; } void Parcel::InjectOffsets(binder_size_t offsets, size_t offsetSize) { if (offsetSize <= 0) { return; } auto *newObjectOffsets = reinterpret_cast(offsets); for (size_t index = 0; index < offsetSize; index++) { if (EnsureObjectsCapacity()) { WriteObjectOffset(newObjectOffsets[index]); } } } void Parcel::ClearObjects() { objectHolder_.clear(); free(objectOffsets_); nextObjectIdx_ = 0; objectCursor_ = 0; objectOffsets_ = nullptr; objectsCapacity_ = 0; } void Parcel::FlushBuffer() { if (allocator_ == nullptr) { return; } if (data_ != nullptr) { allocator_->Dealloc(data_); dataSize_ = 0; writeCursor_ = 0; readCursor_ = 0; dataCapacity_ = 0; data_ = nullptr; } if (objectOffsets_) { ClearObjects(); } } bool Parcel::SetDataCapacity(size_t newCapacity) { if (allocator_ == nullptr || dataSize_ >= newCapacity) { return false; } void *newData = allocator_->Realloc(data_, newCapacity); if (newData != nullptr) { data_ = reinterpret_cast(newData); dataCapacity_ = newCapacity; return true; } return false; } bool Parcel::SetDataSize(size_t dataSize) { if (dataSize > dataCapacity_) { return false; } dataSize_ = dataSize; return true; } bool Parcel::WriteDataBytes(const void *data, size_t size) { void *dest = data_ + writeCursor_; size_t writableBytes = GetWritableBytes(); if (memcpy_s(dest, writableBytes, data, size) != EOK) { return false; } writeCursor_ += size; dataSize_ += size; return true; } void Parcel::WritePadBytes(size_t padSize) { uint8_t *dest = data_ + writeCursor_; static const int MAX_MASK_NUM = 4; #if __BYTE_ORDER == __LITTLE_ENDIAN static const size_t mask[MAX_MASK_NUM] = { 0xFFFFFFFF, 0x00ffffff, 0x0000ffff, 0x000000ff }; #else static const size_t mask[MAX_MASK_NUM] = { 0xFFFFFFFF, 0xffffff00, 0xffff0000, 0xff000000 }; #endif *reinterpret_cast(dest + padSize - MAX_MASK_NUM) &= mask[padSize]; writeCursor_ += padSize; dataSize_ += padSize; } bool Parcel::WriteBuffer(const void *data, size_t size) { if (data == nullptr || size == 0) { return false; } size_t padSize = GetPadSize(size); size_t desireCapacity = size + padSize; // in case of desireCapacity overflow if (desireCapacity < size || desireCapacity < padSize) { return false; } if (EnsureWritableCapacity(desireCapacity)) { if (!WriteDataBytes(data, size)) { return false; } WritePadBytes(padSize); return true; } return false; } bool Parcel::WriteBufferAddTerminator(const void *data, size_t size, size_t typeSize) { if (data == nullptr || size < typeSize) { return false; } size_t padSize = GetPadSize(size); size_t desireCapacity = size + padSize; // in case of desireCapacity overflow if (desireCapacity < size || desireCapacity < padSize) { return false; } if (EnsureWritableCapacity(desireCapacity)) { if (!WriteDataBytes(data, size - typeSize)) { return false; } // Reserved for 32 bits const char terminator[] = {0, 0, 0, 0}; if (!WriteDataBytes(terminator, typeSize)) { return false; } WritePadBytes(padSize); return true; } return false; } bool Parcel::WriteUnpadBuffer(const void *data, size_t size) { return WriteBuffer(data, size); } template bool Parcel::Write(T value) { size_t desireCapacity = sizeof(T); if (EnsureWritableCapacity(desireCapacity)) { *reinterpret_cast(data_ + writeCursor_) = value; writeCursor_ += desireCapacity; dataSize_ += desireCapacity; return true; } return false; } bool Parcel::WriteBool(bool value) { return Write(static_cast(value)); } bool Parcel::WriteBoolUnaligned(bool value) { return Write(value); } bool Parcel::WriteInt8(int8_t value) { return Write(static_cast(value)); } bool Parcel::WriteInt8Unaligned(int8_t value) { return Write(value); } bool Parcel::WriteInt16(int16_t value) { return Write(static_cast(value)); } bool Parcel::WriteInt16Unaligned(int16_t value) { return Write(value); } bool Parcel::WriteInt32(int32_t value) { return Write(value); } bool Parcel::WriteInt64(int64_t value) { return Write(value); } bool Parcel::WriteUint8(uint8_t value) { return Write(static_cast(value)); } bool Parcel::WriteUint8Unaligned(uint8_t value) { return Write(value); } bool Parcel::WriteUint16(uint16_t value) { return Write(static_cast(value)); } bool Parcel::WriteUint16Unaligned(uint16_t value) { return Write(value); } bool Parcel::WriteUint32(uint32_t value) { return Write(value); } bool Parcel::WriteUint64(uint64_t value) { return Write(value); } bool Parcel::WriteFloat(float value) { return Write(value); } bool Parcel::WriteDouble(double value) { return Write(value); } bool Parcel::WritePointer(uintptr_t value) { return Write(value); } bool Parcel::WriteCString(const char *value) { if (value == nullptr) { return false; } int32_t dataLength = strlen(value); if (dataLength < 0 || dataLength >= INT32_MAX) { return false; } int32_t desireCapacity = (dataLength + 1) * sizeof(char); return WriteBuffer(value, desireCapacity); } bool Parcel::WriteString(const std::string &value) { if (value.data() == nullptr) { return WriteInt32(-1); } int32_t dataLength = value.length(); if (dataLength < 0 || dataLength >= INT32_MAX) { return false; } int32_t typeSize = sizeof(char); int32_t desireCapacity = dataLength + typeSize; if (!Write(dataLength)) { return false; } return WriteBufferAddTerminator(value.data(), desireCapacity, typeSize); } bool Parcel::WriteString16(const std::u16string &value) { if (value.data() == nullptr) { return WriteInt32(-1); } int32_t dataLength = value.length(); int32_t typeSize = sizeof(char16_t); if (dataLength < 0 || dataLength > ((static_cast(INT32_MAX)) / typeSize - 1)) { return false; } int32_t desireCapacity = (dataLength + 1) * typeSize; if (!Write(dataLength)) { return false; } return WriteBufferAddTerminator(value.data(), desireCapacity, typeSize); } bool Parcel::WriteString16WithLength(const char16_t *value, size_t len) { if (!value) { return WriteInt32(-1); } int32_t dataLength = len; int32_t typeSize = sizeof(char16_t); if (dataLength < 0 || dataLength > ((static_cast(INT32_MAX)) / typeSize - 1)) { return false; } int32_t desireCapacity = (dataLength + 1) * typeSize; std::u16string u16str(reinterpret_cast(value), len); if (!Write(dataLength)) { return false; } return WriteBufferAddTerminator(u16str.data(), desireCapacity, typeSize); } bool Parcel::WriteString8WithLength(const char *value, size_t len) { if (!value) { return WriteInt32(-1); } int32_t dataLength = len; if (dataLength < 0 || dataLength >= INT32_MAX) { return false; } int32_t typeSize = sizeof(char); int32_t desireCapacity = (dataLength + 1) * typeSize; if (!Write(dataLength)) { return false; } return WriteBufferAddTerminator(value, desireCapacity, typeSize); } bool Parcel::EnsureObjectsCapacity() { if ((objectsCapacity_ - objectCursor_) >= 1) { return true; } if (allocator_ == nullptr) { return false; } const int NEW_CAPACITY_ADD = 2; const int NEW_CAPACITY_MULTI = 3; const int NEW_CAPACITY_DIV = 2; size_t newCapacity = ((objectsCapacity_ + NEW_CAPACITY_ADD) * NEW_CAPACITY_MULTI) / NEW_CAPACITY_DIV; size_t newBytes = newCapacity * sizeof(binder_size_t); void *newOffsets = realloc(objectOffsets_, newBytes); if (newOffsets == nullptr) { return false; } objectOffsets_ = reinterpret_cast(newOffsets); objectsCapacity_ = newCapacity; return true; } const uint8_t *Parcel::ReadBuffer(size_t length, bool isValidate) { if (GetReadableBytes() >= length) { uint8_t *buffer = data_ + readCursor_; #ifdef PARCEL_OBJECT_CHECK size_t upperBound = readCursor_ + length; if (isValidate && !ValidateReadData(upperBound)) { return nullptr; } #endif readCursor_ += length; return buffer; } return nullptr; } bool Parcel::WriteObjectOffset(binder_size_t offset) { if (offset > dataSize_) { return false; } for (size_t index = 0; index < objectCursor_; index++) { if (objectOffsets_[index] == offset) { return false; } } objectOffsets_[objectCursor_] = offset; objectCursor_++; return true; } bool Parcel::WriteRemoteObject(const Parcelable *object) { size_t placeholder = writeCursor_; // Parcelable is nullptr if ((object == nullptr) || (!object->asRemote_)) { return false; } if (!EnsureObjectsCapacity()) { return false; } if (!object->Marshalling(*this)) { return false; } WriteObjectOffset(placeholder); if (object->TestBehavior(Parcelable::BehaviorFlag::HOLD_OBJECT)) { sptr tmp(const_cast(object)); objectHolder_.push_back(tmp); } return true; } bool Parcel::WriteParcelable(const Parcelable *object) { size_t placeholder = writeCursor_; size_t restorSize = dataSize_; // Parcelable is nullptr if (object == nullptr) { // write the meta data to indicate pass an null object. return WriteInt32(0); } if (!object->asRemote_) { // meta data indicate we have an parcelable object. if (!WriteInt32(1)) { return false; } return object->Marshalling(*this); } // Write the remote object flag if (!WriteInt32(1)) { return false; } if (WriteRemoteObject(const_cast(object))) { return true; } // rollback the write position. writeCursor_ = placeholder; dataSize_ = restorSize; return false; } bool Parcel::WriteStrongParcelable(const sptr &object) { if (object == nullptr) { WriteInt32(0); return true; } object->SetBehavior(Parcelable::BehaviorFlag::HOLD_OBJECT); return WriteParcelable(object.GetRefPtr()); } template bool Parcel::Read(T &value) { size_t desireCapacity = sizeof(T); if (desireCapacity <= GetReadableBytes()) { const void *data = data_ + readCursor_; #ifdef PARCEL_OBJECT_CHECK size_t upperBound = readCursor_ + desireCapacity; if (!ValidateReadData(upperBound)) { readCursor_ += desireCapacity; return false; } #endif readCursor_ += desireCapacity; value = *reinterpret_cast(data); return true; } return false; } template T Parcel::Read() { T lvalue {}; return Read(lvalue) ? lvalue : 0; } bool Parcel::ParseFrom(uintptr_t data, size_t size) { if (data_ != nullptr) { return false; } data_ = reinterpret_cast(data); dataCapacity_ = size; dataSize_ = size; /* data is alloc by driver, can not write again */ writable_ = false; #ifdef PARCEL_OBJECT_CHECK if (objectOffsets_) { ClearObjects(); } #endif return true; } const uint8_t *Parcel::ReadBuffer(size_t length) { if (GetReadableBytes() >= length) { uint8_t *buffer = data_ + readCursor_; #ifdef PARCEL_OBJECT_CHECK size_t upperBound = readCursor_ + length; if (!ValidateReadData(upperBound)) { return nullptr; } #endif readCursor_ += length; return buffer; } return nullptr; } const uint8_t *Parcel::BasicReadBuffer([[maybe_unused]]size_t length) { #ifdef PARCEL_OBJECT_CHECK if (GetReadableBytes() >= length) { uint8_t *buffer = data_ + readCursor_; size_t upperBound = readCursor_ + length; if (!ValidateReadData(upperBound)) { readCursor_ += length; return nullptr; } readCursor_ += length; return buffer; } #endif return nullptr; } const uint8_t *Parcel::ReadUnpadBuffer(size_t length) { if (GetReadableBytes() >= length) { uint8_t *buffer = data_ + readCursor_; #ifdef PARCEL_OBJECT_CHECK size_t upperBound = readCursor_ + length; if (!ValidateReadData(upperBound)) { return nullptr; } #endif readCursor_ += length; SkipBytes(GetPadSize(length)); return buffer; } return nullptr; } void Parcel::SkipBytes(size_t bytes) { if (GetReadableBytes() >= bytes) { readCursor_ += bytes; } else if (readCursor_ < dataCapacity_) { readCursor_ = dataCapacity_; } } size_t Parcel::GetReadPosition() { return readCursor_; } bool Parcel::RewindRead(size_t newPosition) { if (newPosition > dataSize_) { return false; } readCursor_ = newPosition; nextObjectIdx_ = 0; return true; } size_t Parcel::GetWritePosition() { return writeCursor_; } bool Parcel::RewindWrite(size_t newPosition) { if (newPosition > dataSize_) { return false; } writeCursor_ = newPosition; dataSize_ = newPosition; #ifdef PARCEL_OBJECT_CHECK if (objectOffsets_ == nullptr || objectCursor_ == 0) { return true; } size_t objectSize = objectCursor_; if (objectOffsets_[objectSize - 1] + sizeof(parcel_flat_binder_object) > newPosition) { while (objectSize > 0) { if (objectOffsets_[objectSize - 1] + sizeof(parcel_flat_binder_object) <= newPosition) { break; } objectSize--; } if (objectSize == 0) { ClearObjects(); return true; } size_t newBytes = objectSize * sizeof(binder_size_t); void *newOffsets = realloc(objectOffsets_, newBytes); if (newOffsets == nullptr) { return false; } objectOffsets_ = reinterpret_cast(newOffsets); objectCursor_ = objectSize; objectsCapacity_ = objectCursor_; objectHolder_.resize(objectSize); nextObjectIdx_ = 0; return true; } #endif return true; } bool Parcel::ReadBool() { int32_t temp = Read(); return (temp != 0); } bool Parcel::ReadBoolUnaligned() { return Read(); } int8_t Parcel::ReadInt8() { int32_t temp = Read(); return static_cast(temp); } int16_t Parcel::ReadInt16() { int32_t temp = Read(); return static_cast(temp); } int32_t Parcel::ReadInt32() { return Read(); } int64_t Parcel::ReadInt64() { return Read(); } uint8_t Parcel::ReadUint8() { uint32_t temp = Read(); return static_cast(temp); } uint16_t Parcel::ReadUint16() { uint32_t temp = Read(); return static_cast(temp); } uint32_t Parcel::ReadUint32() { return Read(); } uint64_t Parcel::ReadUint64() { return Read(); } float Parcel::ReadFloat() { return Read(); } double Parcel::ReadDouble() { return Read(); } template bool Parcel::ReadPadded(T &value) { int32_t temp; bool result = Read(temp); if (result) { value = static_cast(temp); } return result; } bool Parcel::ReadBool(bool &value) { return ReadPadded(value); } bool Parcel::ReadInt8(int8_t &value) { return ReadPadded(value); } bool Parcel::ReadInt8Unaligned(int8_t &value) { return Read(value); } bool Parcel::ReadInt16(int16_t &value) { return ReadPadded(value); } bool Parcel::ReadInt16Unaligned(int16_t &value) { return Read(value); } bool Parcel::ReadInt32(int32_t &value) { return Read(value); } bool Parcel::ReadInt64(int64_t &value) { return Read(value); } bool Parcel::ReadUint8(uint8_t &value) { return ReadPadded(value); } bool Parcel::ReadUint8Unaligned(uint8_t &value) { return Read(value); } bool Parcel::ReadUint16(uint16_t &value) { return ReadPadded(value); } bool Parcel::ReadUint16Unaligned(uint16_t &value) { return Read(value); } bool Parcel::ReadUint32(uint32_t &value) { return Read(value); } bool Parcel::ReadUint64(uint64_t &value) { return Read(value); } bool Parcel::ReadFloat(float &value) { return Read(value); } bool Parcel::ReadDouble(double &value) { return Read(value); } uintptr_t Parcel::ReadPointer() { return Read(); } const char *Parcel::ReadCString() { size_t oldCursor = readCursor_; const size_t avail = GetReadableBytes(); const char* cstr = reinterpret_cast(data_ + readCursor_); // is the string's trailing NUL within the parcel's valid bounds? const char* eos = reinterpret_cast(memchr(cstr, 0, avail)); if (eos != nullptr) { const size_t dataLength = eos - cstr; readCursor_ += (dataLength + 1); SkipBytes(GetPadSize(dataLength + 1)); return cstr; } readCursor_ = oldCursor; return nullptr; } const std::string Parcel::ReadString() { int32_t dataLength = 0; size_t oldCursor = readCursor_; if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { return std::string(); } size_t readCapacity = static_cast(dataLength) + 1; if (readCapacity <= GetReadableBytes()) { #ifdef PARCEL_OBJECT_CHECK const uint8_t *dest = BasicReadBuffer(readCapacity); #else const uint8_t *dest = ReadBuffer(readCapacity); #endif if (dest != nullptr) { const auto *str = reinterpret_cast(dest); SkipBytes(GetPadSize(readCapacity)); if (str[dataLength] == 0) { return std::string(str, dataLength); } } } readCursor_ = oldCursor; return std::string(); } bool Parcel::ReadString(std::string &value) { int32_t dataLength = 0; size_t oldCursor = readCursor_; if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { value = std::string(); return false; } size_t readCapacity = static_cast(dataLength) + 1; if (readCapacity <= GetReadableBytes()) { #ifdef PARCEL_OBJECT_CHECK const uint8_t *dest = BasicReadBuffer(readCapacity); #else const uint8_t *dest = ReadBuffer(readCapacity); #endif if (dest != nullptr) { const auto *str = reinterpret_cast(dest); SkipBytes(GetPadSize(readCapacity)); if (str[dataLength] == 0) { value = std::string(str, dataLength); return true; } } } readCursor_ = oldCursor; value = std::string(); return false; } const std::u16string Parcel::ReadString16() { int32_t dataLength = 0; size_t oldCursor = readCursor_; if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { return std::u16string(); } size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { #ifdef PARCEL_OBJECT_CHECK const uint8_t *str = BasicReadBuffer(readCapacity); #else const uint8_t *str = ReadBuffer(readCapacity); #endif if (str != nullptr) { const auto *u16Str = reinterpret_cast(str); SkipBytes(GetPadSize(readCapacity)); if (u16Str[dataLength] == 0) { return std::u16string(u16Str, dataLength); } } } readCursor_ = oldCursor; return std::u16string(); } bool Parcel::ReadString16(std::u16string &value) { int32_t dataLength = 0; size_t oldCursor = readCursor_; if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { value = std::u16string(); return false; } size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { #ifdef PARCEL_OBJECT_CHECK const uint8_t *str = BasicReadBuffer(readCapacity); #else const uint8_t *str = ReadBuffer(readCapacity); #endif if (str != nullptr) { const auto *u16Str = reinterpret_cast(str); SkipBytes(GetPadSize(readCapacity)); if (u16Str[dataLength] == 0) { value = std::u16string(u16Str, dataLength); return true; } } } readCursor_ = oldCursor; value = std::u16string(); return false; } const std::u16string Parcel::ReadString16WithLength(int32_t &readLength) { int32_t dataLength = 0; size_t oldCursor = readCursor_; if (!Read(dataLength)) { return std::u16string(); } if (dataLength < 0 || dataLength >= INT32_MAX) { readLength = dataLength; return std::u16string(); } size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { #ifdef PARCEL_OBJECT_CHECK const uint8_t *str = BasicReadBuffer(readCapacity); #else const uint8_t *str = ReadBuffer(readCapacity); #endif if (str != nullptr) { const auto *u16Str = reinterpret_cast(str); SkipBytes(GetPadSize(readCapacity)); if (u16Str[dataLength] == 0) { readLength = dataLength; return std::u16string(u16Str, dataLength); } } } readCursor_ = oldCursor; return std::u16string(); } const std::string Parcel::ReadString8WithLength(int32_t &readLength) { int32_t dataLength = 0; size_t oldCursor = readCursor_; if (!Read(dataLength)) { return std::string(); } if (dataLength < 0 || dataLength >= INT32_MAX) { readLength = dataLength; return std::string(); } size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char); if (readCapacity <= GetReadableBytes()) { #ifdef PARCEL_OBJECT_CHECK const uint8_t *str = BasicReadBuffer(readCapacity); #else const uint8_t *str = ReadBuffer(readCapacity); #endif if (str != nullptr) { const auto *u8Str = reinterpret_cast(str); SkipBytes(GetPadSize(readCapacity)); if (u8Str[dataLength] == 0) { readLength = dataLength; return std::string(u8Str, dataLength); } } } readCursor_ = oldCursor; return std::string(); } void *DefaultAllocator::Alloc(size_t size) { return malloc(size); } void DefaultAllocator::Dealloc(void *data) { if (data != nullptr) { free(data); } } void *DefaultAllocator::Realloc(void *data, size_t newSize) { return realloc(data, newSize); } template bool Parcel::WriteVector(const std::vector &val, bool (Parcel::*Write)(T2)) { if (val.size() > INT_MAX) { return false; } if (!this->WriteInt32(static_cast(val.size()))) { return false; } for (const auto &v : val) { if (!(this->*Write)(v)) { return false; } } size_t padSize = this->GetPadSize(val.size() * sizeof(T1)); if (!EnsureWritableCapacity(padSize)) { return false; } this->WritePadBytes(padSize); return true; } template bool Parcel::WriteFixedAlignVector(const std::vector &originVal, bool (Parcel::*SpecialWrite)(T2)) { if (originVal.size() > INT_MAX) { return false; } if (!this->WriteInt32(static_cast(originVal.size()))) { return false; } // Use the specified interface to write a single element. for (const auto &v : originVal) { if (!(this->*SpecialWrite)(v)) { return false; } } // The write length of these interfaces is different from the original type. // They need to use the specified write length and calculate the padSize based on this. size_t padSize = this->GetPadSize(originVal.size() * sizeof(Type)); if (!EnsureWritableCapacity(padSize)) { return false; } this->WritePadBytes(padSize); return true; } bool Parcel::WriteBoolVector(const std::vector &val) { return WriteFixedAlignVector(val, &Parcel::WriteBool); } bool Parcel::WriteInt8Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteInt8Unaligned); } bool Parcel::WriteInt16Vector(const std::vector &val) { return WriteFixedAlignVector(val, &Parcel::WriteInt16); } bool Parcel::WriteInt32Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteInt32); } bool Parcel::WriteInt64Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteInt64); } bool Parcel::WriteUInt8Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteUint8Unaligned); } bool Parcel::WriteUInt16Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteUint16Unaligned); } bool Parcel::WriteUInt32Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteUint32); } bool Parcel::WriteUInt64Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteUint64); } bool Parcel::WriteFloatVector(const std::vector &val) { return WriteVector(val, &Parcel::WriteFloat); } bool Parcel::WriteDoubleVector(const std::vector &val) { return WriteVector(val, &Parcel::WriteDouble); } bool Parcel::WriteStringVector(const std::vector &val) { return WriteVector(val, &Parcel::WriteString); } bool Parcel::WriteString16Vector(const std::vector &val) { return WriteVector(val, &Parcel::WriteString16); } template bool Parcel::ReadVector(std::vector *val, bool (Parcel::*Read)(T &)) { if (val == nullptr) { return false; } int32_t len = this->ReadInt32(); if (len < 0) { return false; } size_t readAbleSize = this->GetReadableBytes() / sizeof(T); size_t size = static_cast(len); if ((size > readAbleSize) || (size > val->max_size())) { UTILS_LOGE("Failed to read vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); return false; } val->resize(size); if (val->size() < size) { return false; } for (auto &v : *val) { if (!(this->*Read)(v)) { return false; } } size_t padSize = this->GetPadSize(size * sizeof(T)); this->SkipBytes(padSize); return true; } template bool Parcel::ReadFixedAlignVector(std::vector *val, bool (Parcel::*SpecialRead)(T2 &)) { if (val == nullptr) { return false; } int32_t len = this->ReadInt32(); if (len < 0) { return false; } size_t readAbleSize = this->GetReadableBytes() / sizeof(Type); size_t size = static_cast(len); if ((size > readAbleSize) || (size > val->max_size())) { UTILS_LOGE("Failed to fixed aligned read vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); return false; } val->resize(size); if (val->size() < size) { return false; } for (size_t i = 0; i < size; ++i) { T2 parcelVal; if (!(this->*SpecialRead)(parcelVal)) { return false; } (*val)[i] = parcelVal; } size_t padSize = this->GetPadSize(size * sizeof(Type)); this->SkipBytes(padSize); return true; } bool Parcel::ReadBoolVector(std::vector *val) { return ReadFixedAlignVector(val, &Parcel::ReadBool); } bool Parcel::ReadInt8Vector(std::vector *val) { return ReadVector(val, &Parcel::ReadInt8Unaligned); } bool Parcel::ReadInt16Vector(std::vector *val) { return ReadFixedAlignVector(val, &Parcel::ReadInt16); } bool Parcel::ReadInt32Vector(std::vector *val) { return ReadVector(val, &Parcel::ReadInt32); } bool Parcel::ReadInt64Vector(std::vector *val) { return ReadVector(val, &Parcel::ReadInt64); } bool Parcel::ReadUInt8Vector(std::vector *val) { return ReadVector(val, &Parcel::ReadUint8Unaligned); } bool Parcel::ReadUInt16Vector(std::vector *val) { return ReadVector(val, &Parcel::ReadUint16Unaligned); } bool Parcel::ReadUInt32Vector(std::vector *val) { return ReadVector(val, &Parcel::ReadUint32); } bool Parcel::ReadUInt64Vector(std::vector *val) { return ReadVector(val, &Parcel::ReadUint64); } bool Parcel::ReadFloatVector(std::vector *val) { return ReadVector(val, &Parcel::ReadFloat); } bool Parcel::ReadDoubleVector(std::vector *val) { return ReadVector(val, &Parcel::ReadDouble); } bool Parcel::ReadStringVector(std::vector *val) { if (val == nullptr) { return false; } int32_t len = this->ReadInt32(); if (len < 0) { return false; } size_t readAbleSize = this->GetReadableBytes(); size_t size = static_cast(len); if ((size > readAbleSize) || (val->max_size() < size)) { UTILS_LOGE("Failed to read string vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); return false; } val->resize(size); if (val->size() < size) { return false; } for (auto &v : *val) { v = ReadString(); } return true; } bool Parcel::ReadString16Vector(std::vector *val) { if (val == nullptr) { return false; } int32_t len = this->ReadInt32(); if (len < 0) { return false; } size_t readAbleSize = this->GetReadableBytes(); size_t size = static_cast(len); if ((size > readAbleSize) || (val->max_size() < size)) { UTILS_LOGE("Failed to read u16string vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); return false; } val->resize(size); if (val->size() < size) { return false; } for (auto &v : *val) { v = ReadString16(); } return true; } } // namespace OHOS