From c52b2ac7b1f675e6b1d34052239423b7f3634033 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Tue, 7 Jul 2026 18:06:05 +0200 Subject: [PATCH] Fix etl::mem_cast cross-size copy constructor and assignment (#1488) The templated cross-size copy constructor and assignment operator were broken in two ways: - They accessed other.buffer / rhs.buffer, which is private in a different mem_cast instantiation, so the cross-size overloads failed to compile whenever they were actually instantiated. - They copied Size_ (the destination size) bytes from a source buffer that is only Other_Size bytes large, reading past the end of the source when the destination was larger. Use the public data() accessor and copy Other_Size bytes. The existing static_assert(Size >= Other_Size) guarantees the destination is big enough. Add test_mem_cast_copy_and_assign_from_smaller regression test. Co-authored-by: John Wellbelove --- include/etl/mem_cast.h | 4 ++-- test/test_mem_cast.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index 853aa18c..35980787 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -115,7 +115,7 @@ namespace etl { ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large"); - memcpy(buffer, other.buffer, Size_); + memcpy(buffer, other.data(), Other_Size); } //*********************************** @@ -126,7 +126,7 @@ namespace etl { ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); - memcpy(buffer, rhs.buffer, Size_); + memcpy(buffer, rhs.data(), Other_Size); return *this; } diff --git a/test/test_mem_cast.cpp b/test/test_mem_cast.cpp index 85bdae8f..717fe1d9 100644 --- a/test/test_mem_cast.cpp +++ b/test/test_mem_cast.cpp @@ -152,6 +152,24 @@ namespace CHECK_EQUAL(3, memCast.ref().a[2]); } + //************************************************************************* + // Cross-size copy/assignment must copy only the source's bytes and must + // not read past the end of the (smaller) source buffer. + TEST(test_mem_cast_copy_and_assign_from_smaller) + { + etl::mem_cast smaller; + smaller.assign(0x12345678UL); + + // Cross-size copy construct (destination larger than source). + etl::mem_cast larger_copy(smaller); + CHECK_EQUAL(0x12345678UL, larger_copy.ref()); + + // Cross-size assignment (destination larger than source). + etl::mem_cast larger_assign; + larger_assign = smaller; + CHECK_EQUAL(0x12345678UL, larger_assign.ref()); + } + //************************************************************************* TEST(test_mem_cast_assign_type_at_dynamic_offset) {