Skip to content

Commit 6b73eaa

Browse files
Ray-Eldathzhangwenchao-123
authored andcommitted
Fix SEGFAULT memory bugs
There're weird SEGFAULT bug due to custom allocation erroneously paired with std::free (should be custom free) and we're unable to solve them. This is a workaround.
1 parent c8b1864 commit 6b73eaa

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/ports/postgres/dbconnector/Allocator_impl.hpp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ Allocator::reallocate(void *inPtr, const size_t inSize) const {
172172
*
173173
* @see See also the notes for PGAllocator::allocate(const size_t) and
174174
* PGAllocator::allocate(const size_t, const std::nothrow_t&)
175+
* CBDB_FIX: see Allocator::makeAligned
175176
*/
176177
template <dbal::MemoryContext MC>
177178
inline
@@ -186,7 +187,8 @@ Allocator::free(void *inPtr) const {
186187
*/
187188
HOLD_INTERRUPTS();
188189
PG_TRY(); {
189-
pfree(unaligned(inPtr));
190+
void* ptr = unaligned(inPtr);
191+
ptr ? pfree(ptr) : std::free(inPtr);
190192
} PG_CATCH(); {
191193
FlushErrorState();
192194
} PG_END_TRY();
@@ -214,11 +216,11 @@ Allocator::internalPalloc(size_t inSize) const {
214216
#if MAXIMUM_ALIGNOF >= 16
215217
return (ZM == dbal::DoZero) ? palloc0(inSize) : palloc(inSize);
216218
#else
217-
if (inSize > std::numeric_limits<size_t>::max() - 16)
219+
if (inSize > std::numeric_limits<size_t>::max() - 32)
218220
return NULL;
219221

220222
/* Precondition: inSize <= std::numeric_limits<size_t>::max() - 16 */
221-
const size_t size = inSize + 16;
223+
const size_t size = inSize + 32;
222224
void *raw = (ZM == dbal::DoZero) ? palloc0(size) : palloc(size);
223225
return makeAligned(raw);
224226
#endif
@@ -246,14 +248,18 @@ Allocator::internalRePalloc(void *inPtr, size_t inSize) const {
246248
#if MAXIMUM_ALIGNOF >= 16
247249
return repalloc(inPtr, inSize);
248250
#else
249-
if (inSize > std::numeric_limits<size_t>::max() - 16) {
250-
pfree(unaligned(inPtr));
251+
void* ptr = unaligned(inPtr);
252+
if (!ptr)
253+
return std::realloc(inPtr, inSize);
254+
255+
if (inSize > std::numeric_limits<size_t>::max() - 32) {
256+
pfree(ptr);
251257
return NULL;
252258
}
253259

254260
/* Precondition: inSize <= std::numeric_limits<size_t>::max() - 16 */
255-
const size_t size = inSize + 16;
256-
void *raw = repalloc(unaligned(inPtr), size);
261+
const size_t size = inSize + 32;
262+
void *raw = repalloc(ptr, size);
257263

258264
if (ZM == dbal::DoZero) {
259265
std::fill(
@@ -269,6 +275,9 @@ Allocator::internalRePalloc(void *inPtr, size_t inSize) const {
269275
* @internal
270276
* @brief Return next 16-byte boundary after inPtr and store inPtr in word
271277
* immediately before that
278+
* CBDB_FIX: A weird bug causes std::malloc to be called for allocation,
279+
* but custom free for destruction. Hacky workacound this by prepending
280+
* each chunk with a magic number 0xCBDBCBDB to indicate custom allocation.
272281
*/
273282
inline
274283
void *
@@ -282,15 +291,17 @@ Allocator::makeAligned(void *inPtr) const {
282291
* to us an can be written to safely.
283292
*/
284293
void *aligned = reinterpret_cast<void*>(
285-
(reinterpret_cast<uintptr_t>(inPtr) & ~(uintptr_t(15))) + 16);
294+
(reinterpret_cast<uintptr_t>(inPtr) & ~(uintptr_t(15))) + 32);
286295
*(reinterpret_cast<void**>(aligned) - 1) = inPtr;
296+
*(reinterpret_cast<size_t*>(aligned) - 2) = 0xCBDBCBDB;
287297
return aligned;
288298
}
289299

290300
/**
291301
* @internal
292302
* @brief Return the address of memory block that corresponds to the given
293303
* 16-byte aligned address
304+
* @see CBDB_FIX: see Allocator::makeAligned
294305
*
295306
* Unless <tt>MAXIMUM_ALIGNOF >= 16</tt>, we free the block of memory pointed to
296307
* by the word immediately in front of the memory pointed to by \c inPtr.
@@ -301,6 +312,11 @@ Allocator::unaligned(void *inPtr) const {
301312
#if MAXIMUM_ALIGNOF >= 16
302313
return inPtr;
303314
#else
315+
size_t magic = *(reinterpret_cast<size_t*>(inPtr) - 2);
316+
if (magic != 0xCBDBCBDB) {
317+
elog(WARNING, "non-custom-allocator allocation detected");
318+
return nullptr;
319+
}
304320
return (*(reinterpret_cast<void**>(inPtr) - 1));
305321
#endif
306322
}

0 commit comments

Comments
 (0)