Skip to content

Commit fcefd7e

Browse files
committed
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.
1 parent 5d56ef7 commit fcefd7e

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

test/test_ipc.cpp

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,22 +84,34 @@ void test_basic(char const * name) {
8484
EXPECT_EQ(que2.recv(), test2);
8585
}
8686

87-
class data_set {
88-
alignas(rand_buf) char datas_[sizeof(rand_buf[LoopCount])];
89-
rand_buf *d_;
90-
91-
public:
92-
data_set() {
93-
d_ = ::new(datas_) rand_buf[LoopCount];
94-
for (int i = 0; i < LoopCount; ++i) {
95-
d_[i].set_id(i);
96-
}
97-
}
98-
99-
rand_buf const *get() const noexcept {
100-
return d_;
101-
}
102-
} const data_set__;
87+
class data_set {
88+
alignas(rand_buf) char datas_[sizeof(rand_buf[LoopCount])];
89+
rand_buf *d_;
90+
91+
public:
92+
data_set() {
93+
// Use individual placement new instead of array placement new
94+
// Array placement new adds a cookie (array size) before the array,
95+
// which would overflow the buffer. MSVC's implementation stores this
96+
// cookie, causing buffer overflow and subsequent memory corruption.
97+
d_ = reinterpret_cast<rand_buf *>(datas_);
98+
for (int i = 0; i < LoopCount; ++i) {
99+
::new(d_ + i) rand_buf;
100+
d_[i].set_id(i);
101+
}
102+
}
103+
104+
~data_set() {
105+
// Manually destroy each element since we used individual placement new
106+
for (int i = 0; i < LoopCount; ++i) {
107+
d_[i].~rand_buf();
108+
}
109+
}
110+
111+
rand_buf const *get() const noexcept {
112+
return d_;
113+
}
114+
} const data_set__;
103115

104116
template <relat Rp, relat Rc, trans Ts, typename Que = chan<Rp, Rc, Ts>>
105117
void test_sr(char const * name, int s_cnt, int r_cnt) {

0 commit comments

Comments
 (0)