From b5f59582cd4a0ed6b6205ad187d1ed639eff2a75 Mon Sep 17 00:00:00 2001 From: Daniel Parker Date: Wed, 11 Oct 2023 14:03:02 -0400 Subject: [PATCH] Fix alignment issue with heap_string --- include/jsoncons/detail/heap_string.hpp | 28 +++++++++++++++---- test/corelib/src/detail/heap_string_tests.cpp | 11 ++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/include/jsoncons/detail/heap_string.hpp b/include/jsoncons/detail/heap_string.hpp index c0eba3331e..f1ee97a1dd 100644 --- a/include/jsoncons/detail/heap_string.hpp +++ b/include/jsoncons/detail/heap_string.hpp @@ -18,6 +18,13 @@ namespace jsoncons { namespace detail { + inline void* + align_up(void* ptr, std::size_t alignment) noexcept + { + return reinterpret_cast(~(alignment - 1) & + (reinterpret_cast(ptr) + alignment - 1)); + } + template struct heap_string_base { @@ -52,6 +59,7 @@ namespace detail { pointer p_; std::size_t length_; + uint16_t offset_; ~heap_string() noexcept = default; @@ -114,23 +122,29 @@ namespace detail { heap_string_type data; char_type c[1]; }; - typedef typename jsoncons_aligned_storage::type json_storage_kind; + typedef typename jsoncons_aligned_storage::type storage_type; static size_t aligned_size(std::size_t n) { - return sizeof(json_storage_kind) + n; + return sizeof(storage_type) + n; } public: static pointer create(const char_type* s, std::size_t length, Extra extra, const Allocator& alloc) { - std::size_t mem_size = aligned_size(length*sizeof(char_type)); + std::size_t len = aligned_size(length*sizeof(char_type)); + + std::size_t align = alignof(storage_type); + std::size_t mem_len = align-1+len; byte_allocator_type byte_alloc(alloc); - byte_pointer ptr = byte_alloc.allocate(mem_size); + byte_pointer ptr = byte_alloc.allocate(mem_len); + + char* q = extension_traits::to_plain_pointer(ptr); + + void* storage = align_up(q, align); - char* storage = extension_traits::to_plain_pointer(ptr); heap_string_type* ps = new(storage)heap_string_type(extra, byte_alloc); auto psa = launder_cast(storage); @@ -149,7 +163,9 @@ namespace detail { { heap_string_type* rawp = extension_traits::to_plain_pointer(ptr); - char* p = launder_cast(rawp); + char* q = launder_cast(rawp); + + char* p = q - ptr->offset_; std::size_t mem_size = aligned_size(ptr->length_*sizeof(char_type)); byte_allocator_type byte_alloc(ptr->get_allocator()); diff --git a/test/corelib/src/detail/heap_string_tests.cpp b/test/corelib/src/detail/heap_string_tests.cpp index 46091352e3..f81f88aeb6 100644 --- a/test/corelib/src/detail/heap_string_tests.cpp +++ b/test/corelib/src/detail/heap_string_tests.cpp @@ -11,3 +11,14 @@ using namespace jsoncons; +using heap_string_factory_type = jsoncons::detail::heap_string_factory>; +using pointer = typename heap_string_factory_type::pointer; + +TEST_CASE("heap_string test") +{ + std::string s("Hello World"); + + pointer ptr = heap_string_factory_type::create(s.data(), s.length(), null_type(), std::allocator()); +} + +