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.
This commit is contained in:
木头云 2025-12-03 07:53:29 +00:00
parent c9d0a94894
commit 52ff081770

View File

@ -90,12 +90,24 @@ class data_set {
public:
data_set() {
d_ = ::new(datas_) rand_buf[LoopCount];
// 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<rand_buf *>(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_;
}