From 659c9464e5beaf558fac2f2f99d62122778e9d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20G=C3=BCndling?= Date: Sun, 26 May 2024 22:53:12 +0200 Subject: [PATCH] string: fix self-assignment, fixes #222 --- CMakeLists.txt | 1 + include/cista/containers/string.h | 9 +++++++++ test/string_test.cc | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e72acbe..11aa026f 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR -Wno-unsafe-buffer-usage -Wno-deprecated-declarations -Wno-ctad-maybe-unsupported + -Wno-self-assign-overloaded -Werror ) elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") diff --git a/include/cista/containers/string.h b/include/cista/containers/string.h index 4b82369f..cfa39945 100644 --- a/include/cista/containers/string.h +++ b/include/cista/containers/string.h @@ -137,6 +137,9 @@ struct generic_string { } void move_from(generic_string&& s) noexcept { + if (&s == this) { + return; + } reset(); std::memcpy(static_cast(this), &s, sizeof(*this)); if constexpr (std::is_pointer_v) { @@ -151,6 +154,9 @@ struct generic_string { } void copy_from(generic_string const& s) { + if (&s == this) { + return; + } reset(); if (s.is_short()) { std::memcpy(static_cast(this), &s, sizeof(s)); @@ -434,6 +440,9 @@ struct basic_string : public generic_string { basic_string(basic_string&& o) { base::move_from(std::move(o)); } basic_string& operator=(basic_string const& o) { + if (&o == this) { + return; + } base::set_owning(o.data(), o.size()); return *this; } diff --git a/test/string_test.cc b/test/string_test.cc index 53bfe9b1..a3db4bb5 100644 --- a/test/string_test.cc +++ b/test/string_test.cc @@ -18,6 +18,24 @@ constexpr auto const CORNER_CASE_LONG_16 = "0123456789123456"; constexpr auto const LONG_STR = "hello world hello world"; constexpr auto const SHORT_STR = "hello world"; +TEST_CASE("self assignment") { + // case short string + cista::raw::string test_short{"test_short"}; + std::string output_short_pre{test_short}; + test_short = test_short; + std::string output_short_post{test_short}; + // test_short is empty now + CHECK(output_short_pre == output_short_post); + + // case long string + cista::raw::string test_long{"test_long_12345678901234567890123456789012"}; + std::string output_long_pre{test_long}; + test_long = test_long; + std::string output_long_post{test_long}; + // test_long is filled with 0x01 now + CHECK(output_long_pre == output_long_post); +} + TEST_CASE("string init") { auto s = string{}; CHECK(!s.is_short());