From 52ff081770085ab96d511246b291eebc3c9bd1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Wed, 3 Dec 2025 07:53:29 +0000 Subject: [PATCH] fix(test): Fix buffer overflow in data_set caused by array placement new ROOT CAUSE: Array placement new (::new(buffer) T[N]) adds a hidden cookie (array size) before the array elements in some compiler implementations (particularly MSVC). The cookie is used for proper array destruction. However, the data_set buffer was sized only for sizeof(T[N]), not accounting for the cookie overhead. ISSUE: - Buffer allocated: sizeof(rand_buf[LoopCount]) - Actual space needed: sizeof(cookie) + sizeof(rand_buf[LoopCount]) - Result: Cookie and part of array written beyond buffer boundary - Consequence: Memory corruption, leading to invalid pointers in buffer objects SYMPTOM: In IPC.1v1 test, memcpy(buf, data, size) crashed because 'data' pointer (from buffer::data()) pointed to corrupted/invalid memory address. SOLUTION: Replace array placement new with individual element placement new: - Cast buffer to array pointer directly (no cookie needed) - Construct each element individually with placement new - Manually destroy each element in destructor This approach: - Eliminates cookie overhead - Provides precise control over object lifetime - Works consistently across all compilers Fixes crash in IPC.1v1 test case on MSVC. --- test/archive/test_ipc.cpp | 44 +++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/test/archive/test_ipc.cpp b/test/archive/test_ipc.cpp index 00dcd27..d69c69a 100755 --- a/test/archive/test_ipc.cpp +++ b/test/archive/test_ipc.cpp @@ -84,22 +84,34 @@ void test_basic(char const * name) { EXPECT_EQ(que2.recv(), test2); } -class data_set { - alignas(rand_buf) char datas_[sizeof(rand_buf[LoopCount])]; - rand_buf *d_; - -public: - data_set() { - d_ = ::new(datas_) rand_buf[LoopCount]; - for (int i = 0; i < LoopCount; ++i) { - d_[i].set_id(i); - } - } - - rand_buf const *get() const noexcept { - return d_; - } -} const data_set__; +class data_set { + alignas(rand_buf) char datas_[sizeof(rand_buf[LoopCount])]; + rand_buf *d_; + +public: + data_set() { + // Use individual placement new instead of array placement new + // Array placement new adds a cookie (array size) before the array, + // which would overflow the buffer. MSVC's implementation stores this + // cookie, causing buffer overflow and subsequent memory corruption. + d_ = reinterpret_cast(datas_); + for (int i = 0; i < LoopCount; ++i) { + ::new(d_ + i) rand_buf; + d_[i].set_id(i); + } + } + + ~data_set() { + // Manually destroy each element since we used individual placement new + for (int i = 0; i < LoopCount; ++i) { + d_[i].~rand_buf(); + } + } + + rand_buf const *get() const noexcept { + return d_; + } +} const data_set__; template > void test_sr(char const * name, int s_cnt, int r_cnt) {