From 6a89e22a29865a16818efab5b0927c4550ab3639 Mon Sep 17 00:00:00 2001 From: pythonology Date: Sat, 15 Jun 2019 23:12:04 -0400 Subject: [PATCH] serialization: Fix incorrect byte alignment when... ...dynamic properties contain object pointers that end with bit-based properties. --- include/ki/util/BitStream.h | 5 +++++ src/serialization/BinarySerializer.cpp | 20 ++++++++++++++------ src/util/BitStream.cpp | 5 +++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/ki/util/BitStream.h b/include/ki/util/BitStream.h index 8d6ac5a..5deb841 100644 --- a/include/ki/util/BitStream.h +++ b/include/ki/util/BitStream.h @@ -278,6 +278,11 @@ namespace ki */ void seek(stream_pos position, bool expand = true); + /** + * Realigns the position of the stream so that it lies directly on a byte. + */ + void realign(); + /** * @returns The current size of the internal buffer. */ diff --git a/src/serialization/BinarySerializer.cpp b/src/serialization/BinarySerializer.cpp index a3ecd1d..dad2bc7 100644 --- a/src/serialization/BinarySerializer.cpp +++ b/src/serialization/BinarySerializer.cpp @@ -163,9 +163,9 @@ namespace serialization void BinarySerializer::save_property(const pclass::IProperty &prop, BitStream &stream) const { - // Determine if we need to re-align the stream so that our position lies on a byte - if (prop.get_type().is_byte_based() || prop.is_dynamic() || m_is_file) - stream.seek(BitStream::stream_pos(stream.tell().as_bytes(), 0)); + // Realign the stream if we're going to write a prefix for this property + if (prop.is_dynamic() || m_is_file) + stream.realign(); // Remember where we started writing the property data const auto start_pos = stream.tell(); @@ -196,6 +196,10 @@ namespace serialization for (auto i = 0; i < prop.get_element_count(); ++i) { + // Realign the stream if this property works in bytes + if (prop.get_type().is_byte_based()) + stream.realign(); + if (prop.is_pointer() && prop.get_type().get_kind() == pclass::Type::Kind::CLASS) { @@ -369,9 +373,9 @@ namespace serialization void BinarySerializer::load_property(pclass::IProperty &prop, BitStream &stream) const { - // Determine if we need to re-align the stream so that our position lies on a byte - if (prop.get_type().is_byte_based() || prop.is_dynamic()) - stream.seek(BitStream::stream_pos(stream.tell().as_bytes(), 0)); + // Re-align the stream if we're going to read a prefix for this property + if (prop.is_dynamic()) + stream.realign(); // If the property is dynamic, we need to load the element count if (prop.is_dynamic()) @@ -393,6 +397,10 @@ namespace serialization for (auto i = 0; i < prop.get_element_count(); ++i) { + // Realign the stream if this property works in bytes + if (prop.get_type().is_byte_based()) + stream.realign(); + if (prop.is_pointer() && prop.get_type().get_kind() == pclass::Type::Kind::CLASS) { diff --git a/src/util/BitStream.cpp b/src/util/BitStream.cpp index 9f8f78e..112b733 100644 --- a/src/util/BitStream.cpp +++ b/src/util/BitStream.cpp @@ -386,6 +386,11 @@ namespace ki m_position = position; } + void realign() + { + seek(stream_pos(tell().as_bytes(), 0), false); + } + std::size_t BitStream::capacity() const { return m_buffer->size();