diff options
author | Doyle <doylet@protonmail.com> | 2020-05-19 18:45:32 +1000 |
---|---|---|
committer | Doyle <doylet@protonmail.com> | 2020-05-20 10:21:21 +1000 |
commit | 438b84690e818b136b84f31a12e67a83fec8979b (patch) | |
tree | 9024b925aa0b2c4ce9276403915242769279316b | |
parent | Merge pull request #6554 (diff) | |
download | monero-438b84690e818b136b84f31a12e67a83fec8979b.tar.xz |
ByteSlice: Fix persisting ptr to std::moved SSO buffer
The Bug:
1. Construct `byte_slice.portion_` with `epee::span(buffer)` which copies a pointer to the SSO buffer to `byte_slice.portion_`
2. It constructs `byte_slice.storage_` with `std::move(buffer)` (normally this swap pointers, but SSO means a memcpy and clear on the original SSO buffer)
3. `slice.data()` returns a pointer from `slice.portion_` that points to the original SSO cleared buffer, `slice.storage_` has the actual string.
-rw-r--r-- | contrib/epee/src/byte_slice.cpp | 5 | ||||
-rw-r--r-- | tests/unit_tests/epee_utils.cpp | 23 |
2 files changed, 27 insertions, 1 deletions
diff --git a/contrib/epee/src/byte_slice.cpp b/contrib/epee/src/byte_slice.cpp index 12cc83e6c..faf7689be 100644 --- a/contrib/epee/src/byte_slice.cpp +++ b/contrib/epee/src/byte_slice.cpp @@ -133,10 +133,13 @@ namespace epee template<typename T> byte_slice::byte_slice(const adapt_buffer, T&& buffer) - : storage_(nullptr), portion_(to_byte_span(to_span(buffer))) + : storage_(nullptr), portion_(nullptr) { if (!buffer.empty()) + { storage_ = allocate_slice<adapted_byte_slice<T>>(0, std::move(buffer)); + portion_ = to_byte_span(to_span(static_cast<adapted_byte_slice<T> *>(storage_.get())->buffer)); + } } byte_slice::byte_slice(std::initializer_list<span<const std::uint8_t>> sources) diff --git a/tests/unit_tests/epee_utils.cpp b/tests/unit_tests/epee_utils.cpp index a2cec965e..0f91671a7 100644 --- a/tests/unit_tests/epee_utils.cpp +++ b/tests/unit_tests/epee_utils.cpp @@ -387,6 +387,29 @@ TEST(ByteSlice, Construction) EXPECT_FALSE(std::is_copy_assignable<epee::byte_slice>()); } +TEST(ByteSlice, DataReturnedMatches) +{ + for (int i = 64; i > 0; i--) + { + std::string sso_string(i, 'a'); + std::string original = sso_string; + epee::byte_slice slice{std::move(sso_string)}; + + EXPECT_EQ(slice.size(), original.size()); + EXPECT_EQ(memcmp(slice.data(), original.data(), original.size()), 0); + } + + for (int i = 64; i > 0; i--) + { + std::vector<uint8_t> sso_vector(i, 'a'); + std::vector<uint8_t> original = sso_vector; + epee::byte_slice slice{std::move(sso_vector)}; + + EXPECT_EQ(slice.size(), original.size()); + EXPECT_EQ(memcmp(slice.data(), original.data(), original.size()), 0); + } +} + TEST(ByteSlice, NoExcept) { EXPECT_TRUE(std::is_nothrow_default_constructible<epee::byte_slice>()); |