diff --git a/base/include/flat_obj.h b/base/include/flat_obj.h index 0c7dd7c..0af092e 100644 --- a/base/include/flat_obj.h +++ b/base/include/flat_obj.h @@ -40,4 +40,13 @@ struct parcel_flat_binder_object { binder_uintptr_t cookie; }; +#ifndef B_PACK_CHARS +#define B_PACK_CHARS(c1, c2, c3, c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4)) +#endif + +#ifndef B_TYPE_LARGE +#define B_TYPE_LARGE 0x85 +#endif + +#define PARCEL_BINDER_TYPE_FD B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE) #endif diff --git a/base/include/parcel.h b/base/include/parcel.h index b69981f..519d9fa 100644 --- a/base/include/parcel.h +++ b/base/include/parcel.h @@ -297,9 +297,7 @@ public: bool ReadInt16Unaligned(int16_t &value); bool ReadUint8Unaligned(uint8_t &value); bool ReadUint16Unaligned(uint16_t &value); - - bool EnsureObjectsCapacity(); - bool WriteObjectOffset(binder_size_t offset); + bool ParcelAppend(Parcel &data); private: DISALLOW_COPY_AND_MOVE(Parcel); @@ -323,12 +321,16 @@ private: size_t CalcNewCapacity(size_t minCapacity); + bool WriteObjectOffset(binder_size_t offset); + bool WriteDataBytes(const void *data, size_t size); void WritePadBytes(size_t padded); bool EnsureWritableCapacity(size_t desireCapacity); + bool EnsureObjectsCapacity(); + bool WriteParcelableOffset(size_t offset); private: diff --git a/base/src/parcel.cpp b/base/src/parcel.cpp index c3b6a98..0eddc97 100644 --- a/base/src/parcel.cpp +++ b/base/src/parcel.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "parcel.h" #include "securec.h" @@ -1396,4 +1397,44 @@ bool Parcel::ReadString16Vector(std::vector *val) return true; } + +bool Parcel::ParcelAppend(Parcel &data) +{ + size_t dataSize = data.GetDataSize(); + if (dataSize == 0) { + return true; + } + uintptr_t dataPtr = data.GetData(); + size_t writeCursorOld = writeCursor_; + + if (EnsureWritableCapacity(dataSize)) { + if (!WriteDataBytes(reinterpret_cast(dataPtr), dataSize)) { + UTILS_LOGE("Failed to append data whit WriteBuffer"); + return false; + } + } + size_t objectSize = data.GetOffsetsSize(); + if (objectSize == 0) { + return true; + } + binder_size_t objectOffsets = data.GetObjectOffsets(); + auto *newObjectOffsets = reinterpret_cast(objectOffsets); + for (size_t index = 0; index < objectSize; index++) { + if (EnsureObjectsCapacity()) { + size_t offset = writeCursorOld + newObjectOffsets[index]; + if (!WriteObjectOffset(offset)) { + UTILS_LOGE("Failed to write object offset"); + return false; + } + parcel_flat_binder_object *flat = reinterpret_cast(data_ + offset); + if (flat->hdr.type == PARCEL_BINDER_TYPE_FD) { + flat->handle = dup(flat->handle); + } + } else { + UTILS_LOGE("Failed to ensure object capacity"); + return false; + } + } + return true; +} } // namespace OHOS diff --git a/base/test/unittest/common/utils_parcel_test.cpp b/base/test/unittest/common/utils_parcel_test.cpp index 63fe2ee..88185f4 100644 --- a/base/test/unittest/common/utils_parcel_test.cpp +++ b/base/test/unittest/common/utils_parcel_test.cpp @@ -967,3 +967,40 @@ HWTEST_F(UtilsParcelTest, test_SetMaxCapacity_002, TestSize.Level0) ret = parcel.ReadString16Vector(&val); EXPECT_EQ(false, ret); } + +/** + * @tc.name: test_ParcelAppend + * @tc.desc: test parcel append function. + * @tc.type: FUNC + */ +HWTEST_F(UtilsParcelTest, test_ParcelAppend, TestSize.Level0) +{ + Parcel dstParcel, srcParcel; + bool res = dstParcel.ParcelAppend(srcParcel); + ASSERT_TRUE(res); + + const int32_t num = 5767168; + const std::string strwrite1 = + "test for write string padded**********************************************************##################"; + dstParcel.WriteInt32(num); + dstParcel.WriteString(strwrite1); + srcParcel.WriteInt32(num); + srcParcel.WriteString(strwrite1); + srcParcel.WriteString(strwrite1); + + res = dstParcel.ParcelAppend(srcParcel); + ASSERT_TRUE(res); + EXPECT_EQ(num, dstParcel.ReadInt32()); + EXPECT_EQ(strwrite1, dstParcel.ReadString()); + EXPECT_EQ(num, dstParcel.ReadInt32()); + EXPECT_EQ(strwrite1, dstParcel.ReadString()); + EXPECT_EQ(strwrite1, dstParcel.ReadString()); + + res = srcParcel.ParcelAppend(dstParcel); + ASSERT_TRUE(res); + EXPECT_EQ(num, srcParcel.ReadInt32()); + EXPECT_EQ(strwrite1, srcParcel.ReadString()); + EXPECT_EQ(strwrite1, srcParcel.ReadString()); + EXPECT_EQ(num, srcParcel.ReadInt32()); + EXPECT_EQ(strwrite1, srcParcel.ReadString()); +} \ No newline at end of file