aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/mmgr/aset.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index 77872e77bcd..5beebc1c129 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -1076,22 +1076,22 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
{
AllocSet set = (AllocSet) context;
AllocChunk chunk = AllocPointerGetChunk(pointer);
- Size oldsize;
+ Size oldchksize;
/* Allow access to private part of chunk header. */
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
- oldsize = chunk->size;
+ oldchksize = chunk->size;
#ifdef MEMORY_CONTEXT_CHECKING
/* Test for someone scribbling on unused space in chunk */
- if (chunk->requested_size < oldsize)
+ if (chunk->requested_size < oldchksize)
if (!sentinel_ok(pointer, chunk->requested_size))
elog(WARNING, "detected write past chunk end in %s %p",
set->header.name, chunk);
#endif
- if (oldsize > set->allocChunkLimit)
+ if (oldchksize > set->allocChunkLimit)
{
/*
* The chunk must have been allocated as a single-chunk block. Use
@@ -1111,7 +1111,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
if (block->aset != set ||
block->freeptr != block->endptr ||
block->freeptr != ((char *) block) +
- (oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
+ (oldchksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
elog(ERROR, "could not find block containing chunk %p", chunk);
/*
@@ -1154,21 +1154,29 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
#ifdef MEMORY_CONTEXT_CHECKING
#ifdef RANDOMIZE_ALLOCATED_MEMORY
- /* We can only fill the extra space if we know the prior request */
+
+ /*
+ * We can only randomize the extra space if we know the prior request.
+ * When using Valgrind, randomize_mem() also marks memory UNDEFINED.
+ */
if (size > chunk->requested_size)
randomize_mem((char *) pointer + chunk->requested_size,
size - chunk->requested_size);
-#endif
+#else
/*
- * realloc() (or randomize_mem()) will have left any newly-allocated
- * part UNDEFINED, but we may need to adjust trailing bytes from the
- * old allocation.
+ * If this is an increase, realloc() will have marked any
+ * newly-allocated part (from oldchksize to chksize) UNDEFINED, but we
+ * also need to adjust trailing bytes from the old allocation (from
+ * chunk->requested_size to oldchksize) as they are marked NOACCESS.
+ * Make sure not to mark too many bytes in case chunk->requested_size
+ * < size < oldchksize.
*/
#ifdef USE_VALGRIND
- if (oldsize > chunk->requested_size)
+ if (Min(size, oldchksize) > chunk->requested_size)
VALGRIND_MAKE_MEM_UNDEFINED((char *) pointer + chunk->requested_size,
- oldsize - chunk->requested_size);
+ Min(size, oldchksize) - chunk->requested_size);
+#endif
#endif
chunk->requested_size = size;
@@ -1179,11 +1187,14 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
#else /* !MEMORY_CONTEXT_CHECKING */
/*
- * We don't know how much of the old chunk size was the actual
- * allocation; it could have been as small as one byte. We have to be
- * conservative and just mark the entire old portion DEFINED.
+ * We may need to adjust marking of bytes from the old allocation as
+ * some of them may be marked NOACCESS. We don't know how much of the
+ * old chunk size was the requested size; it could have been as small
+ * as one byte. We have to be conservative and just mark the entire
+ * old portion DEFINED. Make sure not to mark memory beyond the new
+ * allocation in case it's smaller than the old one.
*/
- VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
+ VALGRIND_MAKE_MEM_DEFINED(pointer, Min(size, oldchksize));
#endif
/* Ensure any padding bytes are marked NOACCESS. */
@@ -1200,7 +1211,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
* allocated area already is >= the new size. (In particular, we will
* fall out here if the requested size is a decrease.)
*/
- else if (oldsize >= size)
+ else if (oldchksize >= size)
{
#ifdef MEMORY_CONTEXT_CHECKING
Size oldrequest = chunk->requested_size;
@@ -1223,10 +1234,10 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
size - oldrequest);
else
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size,
- oldsize - size);
+ oldchksize - size);
/* set mark to catch clobber of "unused" space */
- if (size < oldsize)
+ if (size < oldchksize)
set_sentinel(pointer, size);
#else /* !MEMORY_CONTEXT_CHECKING */
@@ -1235,7 +1246,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
* the old request or shrinking it, so we conservatively mark the
* entire new allocation DEFINED.
*/
- VALGRIND_MAKE_MEM_NOACCESS(pointer, oldsize);
+ VALGRIND_MAKE_MEM_NOACCESS(pointer, oldchksize);
VALGRIND_MAKE_MEM_DEFINED(pointer, size);
#endif
@@ -1258,6 +1269,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
* memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
*/
AllocPointer newPointer;
+ Size oldsize;
/* allocate new chunk */
newPointer = AllocSetAlloc((MemoryContext) set, size);
@@ -1282,6 +1294,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
#ifdef MEMORY_CONTEXT_CHECKING
oldsize = chunk->requested_size;
#else
+ oldsize = oldchksize;
VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
#endif