mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Adjust Valgrind macro usage to protect chunk headers
Prior to this commit we only ever protected MemoryChunk's requested_size
field with Valgrind NOACCESS. This means that if the hdrmask field is
ever accessed accidentally then we're not going to get any warnings from
Valgrind about it. Valgrind would have warned us about the problem fixed
in 92957ed98
had we already been doing this.
Per suggestion from Tom Lane
Reviewed-by: Richard Guo
Discussion: https://postgr.es/m/1650235.1672694719@sss.pgh.pa.us
Discussion: https://postgr.es/m/CAApHDvr=FZNGbj252Z6M9BSFKoq6BMxgkQ2yEAGUYoo7RquqZg@mail.gmail.com
This commit is contained in:
@ -31,6 +31,8 @@ AlignedAllocFree(void *pointer)
|
|||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
void *unaligned;
|
void *unaligned;
|
||||||
|
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, sizeof(MemoryChunk));
|
||||||
|
|
||||||
Assert(!MemoryChunkIsExternal(chunk));
|
Assert(!MemoryChunkIsExternal(chunk));
|
||||||
|
|
||||||
/* obtain the original (unaligned) allocated pointer */
|
/* obtain the original (unaligned) allocated pointer */
|
||||||
@ -58,12 +60,17 @@ void *
|
|||||||
AlignedAllocRealloc(void *pointer, Size size)
|
AlignedAllocRealloc(void *pointer, Size size)
|
||||||
{
|
{
|
||||||
MemoryChunk *redirchunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *redirchunk = PointerGetMemoryChunk(pointer);
|
||||||
Size alignto = MemoryChunkGetValue(redirchunk);
|
Size alignto;
|
||||||
void *unaligned = MemoryChunkGetBlock(redirchunk);
|
void *unaligned;
|
||||||
MemoryContext ctx;
|
MemoryContext ctx;
|
||||||
Size old_size;
|
Size old_size;
|
||||||
void *newptr;
|
void *newptr;
|
||||||
|
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(redirchunk, sizeof(MemoryChunk));
|
||||||
|
|
||||||
|
alignto = MemoryChunkGetValue(redirchunk);
|
||||||
|
unaligned = MemoryChunkGetBlock(redirchunk);
|
||||||
|
|
||||||
/* sanity check this is a power of 2 value */
|
/* sanity check this is a power of 2 value */
|
||||||
Assert((alignto & (alignto - 1)) == 0);
|
Assert((alignto & (alignto - 1)) == 0);
|
||||||
|
|
||||||
@ -110,11 +117,18 @@ AlignedAllocRealloc(void *pointer, Size size)
|
|||||||
MemoryContext
|
MemoryContext
|
||||||
AlignedAllocGetChunkContext(void *pointer)
|
AlignedAllocGetChunkContext(void *pointer)
|
||||||
{
|
{
|
||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *redirchunk = PointerGetMemoryChunk(pointer);
|
||||||
|
MemoryContext cxt;
|
||||||
|
|
||||||
Assert(!MemoryChunkIsExternal(chunk));
|
VALGRIND_MAKE_MEM_DEFINED(redirchunk, sizeof(MemoryChunk));
|
||||||
|
|
||||||
return GetMemoryChunkContext(MemoryChunkGetBlock(chunk));
|
Assert(!MemoryChunkIsExternal(redirchunk));
|
||||||
|
|
||||||
|
cxt = GetMemoryChunkContext(MemoryChunkGetBlock(redirchunk));
|
||||||
|
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(redirchunk, sizeof(MemoryChunk));
|
||||||
|
|
||||||
|
return cxt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -126,7 +140,15 @@ Size
|
|||||||
AlignedAllocGetChunkSpace(void *pointer)
|
AlignedAllocGetChunkSpace(void *pointer)
|
||||||
{
|
{
|
||||||
MemoryChunk *redirchunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *redirchunk = PointerGetMemoryChunk(pointer);
|
||||||
void *unaligned = MemoryChunkGetBlock(redirchunk);
|
void *unaligned;
|
||||||
|
Size space;
|
||||||
|
|
||||||
return GetMemoryChunkSpace(unaligned);
|
VALGRIND_MAKE_MEM_DEFINED(redirchunk, sizeof(MemoryChunk));
|
||||||
|
|
||||||
|
unaligned = MemoryChunkGetBlock(redirchunk);
|
||||||
|
space = GetMemoryChunkSpace(unaligned);
|
||||||
|
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(redirchunk, sizeof(MemoryChunk));
|
||||||
|
|
||||||
|
return space;
|
||||||
}
|
}
|
||||||
|
@ -188,14 +188,6 @@ typedef struct AllocBlockData
|
|||||||
char *endptr; /* end of space in this block */
|
char *endptr; /* end of space in this block */
|
||||||
} AllocBlockData;
|
} AllocBlockData;
|
||||||
|
|
||||||
/*
|
|
||||||
* Only the "hdrmask" field should be accessed outside this module.
|
|
||||||
* We keep the rest of an allocated chunk's header marked NOACCESS when using
|
|
||||||
* valgrind. But note that chunk headers that are in a freelist are kept
|
|
||||||
* accessible, for simplicity.
|
|
||||||
*/
|
|
||||||
#define ALLOCCHUNK_PRIVATE_LEN offsetof(MemoryChunk, hdrmask)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AllocPointerIsValid
|
* AllocPointerIsValid
|
||||||
* True iff pointer is valid allocation pointer.
|
* True iff pointer is valid allocation pointer.
|
||||||
@ -777,8 +769,8 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|||||||
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
||||||
chunk_size - size);
|
chunk_size - size);
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
return MemoryChunkGetPointer(chunk);
|
return MemoryChunkGetPointer(chunk);
|
||||||
}
|
}
|
||||||
@ -801,6 +793,9 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|||||||
{
|
{
|
||||||
AllocFreeListLink *link = GetFreeListLink(chunk);
|
AllocFreeListLink *link = GetFreeListLink(chunk);
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
Assert(fidx == MemoryChunkGetValue(chunk));
|
Assert(fidx == MemoryChunkGetValue(chunk));
|
||||||
|
|
||||||
/* pop this chunk off the freelist */
|
/* pop this chunk off the freelist */
|
||||||
@ -823,8 +818,8 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|||||||
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
||||||
GetChunkSizeFromFreeListIdx(fidx) - size);
|
GetChunkSizeFromFreeListIdx(fidx) - size);
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
return MemoryChunkGetPointer(chunk);
|
return MemoryChunkGetPointer(chunk);
|
||||||
}
|
}
|
||||||
@ -989,8 +984,8 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|||||||
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
||||||
chunk_size - size);
|
chunk_size - size);
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
return MemoryChunkGetPointer(chunk);
|
return MemoryChunkGetPointer(chunk);
|
||||||
}
|
}
|
||||||
@ -1005,8 +1000,8 @@ AllocSetFree(void *pointer)
|
|||||||
AllocSet set;
|
AllocSet set;
|
||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
|
|
||||||
/* Allow access to private part of chunk header. */
|
/* Allow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
@ -1115,8 +1110,8 @@ AllocSetRealloc(void *pointer, Size size)
|
|||||||
Size oldchksize;
|
Size oldchksize;
|
||||||
int fidx;
|
int fidx;
|
||||||
|
|
||||||
/* Allow access to private part of chunk header. */
|
/* Allow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
@ -1164,8 +1159,8 @@ AllocSetRealloc(void *pointer, Size size)
|
|||||||
block = (AllocBlock) realloc(block, blksize);
|
block = (AllocBlock) realloc(block, blksize);
|
||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
{
|
{
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1232,8 +1227,8 @@ AllocSetRealloc(void *pointer, Size size)
|
|||||||
/* Ensure any padding bytes are marked NOACCESS. */
|
/* Ensure any padding bytes are marked NOACCESS. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size, chksize - size);
|
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size, chksize - size);
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header . */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
@ -1305,8 +1300,8 @@ AllocSetRealloc(void *pointer, Size size)
|
|||||||
VALGRIND_MAKE_MEM_DEFINED(pointer, size);
|
VALGRIND_MAKE_MEM_DEFINED(pointer, size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
@ -1332,8 +1327,8 @@ AllocSetRealloc(void *pointer, Size size)
|
|||||||
/* leave immediately if request was not completed */
|
/* leave immediately if request was not completed */
|
||||||
if (newPointer == NULL)
|
if (newPointer == NULL)
|
||||||
{
|
{
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1374,11 +1369,17 @@ AllocSetGetChunkContext(void *pointer)
|
|||||||
AllocBlock block;
|
AllocBlock block;
|
||||||
AllocSet set;
|
AllocSet set;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
block = ExternalChunkGetBlock(chunk);
|
block = ExternalChunkGetBlock(chunk);
|
||||||
else
|
else
|
||||||
block = (AllocBlock) MemoryChunkGetBlock(chunk);
|
block = (AllocBlock) MemoryChunkGetBlock(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
Assert(AllocBlockIsValid(block));
|
Assert(AllocBlockIsValid(block));
|
||||||
set = block->aset;
|
set = block->aset;
|
||||||
|
|
||||||
@ -1396,16 +1397,27 @@ AllocSetGetChunkSpace(void *pointer)
|
|||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
int fidx;
|
int fidx;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
AllocBlock block = ExternalChunkGetBlock(chunk);
|
AllocBlock block = ExternalChunkGetBlock(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
Assert(AllocBlockIsValid(block));
|
Assert(AllocBlockIsValid(block));
|
||||||
|
|
||||||
return block->endptr - (char *) chunk;
|
return block->endptr - (char *) chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
fidx = MemoryChunkGetValue(chunk);
|
fidx = MemoryChunkGetValue(chunk);
|
||||||
Assert(FreeListIdxIsValid(fidx));
|
Assert(FreeListIdxIsValid(fidx));
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
return GetChunkSizeFromFreeListIdx(fidx) + ALLOC_CHUNKHDRSZ;
|
return GetChunkSizeFromFreeListIdx(fidx) + ALLOC_CHUNKHDRSZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1471,7 +1483,10 @@ AllocSetStats(MemoryContext context,
|
|||||||
{
|
{
|
||||||
AllocFreeListLink *link = GetFreeListLink(chunk);
|
AllocFreeListLink *link = GetFreeListLink(chunk);
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
Assert(MemoryChunkGetValue(chunk) == fidx);
|
Assert(MemoryChunkGetValue(chunk) == fidx);
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
freechunks++;
|
freechunks++;
|
||||||
freespace += chksz + ALLOC_CHUNKHDRSZ;
|
freespace += chksz + ALLOC_CHUNKHDRSZ;
|
||||||
@ -1566,8 +1581,8 @@ AllocSetCheck(MemoryContext context)
|
|||||||
Size chsize,
|
Size chsize,
|
||||||
dsize;
|
dsize;
|
||||||
|
|
||||||
/* Allow access to private part of chunk header. */
|
/* Allow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
@ -1617,12 +1632,9 @@ AllocSetCheck(MemoryContext context)
|
|||||||
elog(WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
|
elog(WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
|
||||||
name, block, chunk);
|
name, block, chunk);
|
||||||
|
|
||||||
/*
|
/* if chunk is allocated, disallow access to the chunk header */
|
||||||
* If chunk is allocated, disallow external access to private part
|
|
||||||
* of chunk header.
|
|
||||||
*/
|
|
||||||
if (dsize != InvalidAllocSize)
|
if (dsize != InvalidAllocSize)
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
||||||
|
|
||||||
blk_data += chsize;
|
blk_data += chsize;
|
||||||
nchunks++;
|
nchunks++;
|
||||||
|
@ -98,14 +98,6 @@ struct GenerationBlock
|
|||||||
char *endptr; /* end of space in this block */
|
char *endptr; /* end of space in this block */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Only the "hdrmask" field should be accessed outside this module.
|
|
||||||
* We keep the rest of an allocated chunk's header marked NOACCESS when using
|
|
||||||
* valgrind. But note that freed chunk headers are kept accessible, for
|
|
||||||
* simplicity.
|
|
||||||
*/
|
|
||||||
#define GENERATIONCHUNK_PRIVATE_LEN offsetof(MemoryChunk, hdrmask)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GenerationIsValid
|
* GenerationIsValid
|
||||||
* True iff set is valid generation set.
|
* True iff set is valid generation set.
|
||||||
@ -407,8 +399,8 @@ GenerationAlloc(MemoryContext context, Size size)
|
|||||||
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
||||||
chunk_size - size);
|
chunk_size - size);
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
return MemoryChunkGetPointer(chunk);
|
return MemoryChunkGetPointer(chunk);
|
||||||
}
|
}
|
||||||
@ -522,8 +514,8 @@ GenerationAlloc(MemoryContext context, Size size)
|
|||||||
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
||||||
chunk_size - size);
|
chunk_size - size);
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
return MemoryChunkGetPointer(chunk);
|
return MemoryChunkGetPointer(chunk);
|
||||||
}
|
}
|
||||||
@ -634,6 +626,9 @@ GenerationFree(void *pointer)
|
|||||||
Size chunksize;
|
Size chunksize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
block = ExternalChunkGetBlock(chunk);
|
block = ExternalChunkGetBlock(chunk);
|
||||||
@ -667,9 +662,6 @@ GenerationFree(void *pointer)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow access to private part of chunk header. */
|
|
||||||
VALGRIND_MAKE_MEM_DEFINED(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
|
||||||
|
|
||||||
#ifdef MEMORY_CONTEXT_CHECKING
|
#ifdef MEMORY_CONTEXT_CHECKING
|
||||||
/* Test for someone scribbling on unused space in chunk */
|
/* Test for someone scribbling on unused space in chunk */
|
||||||
Assert(chunk->requested_size < chunksize);
|
Assert(chunk->requested_size < chunksize);
|
||||||
@ -747,8 +739,8 @@ GenerationRealloc(void *pointer, Size size)
|
|||||||
GenerationPointer newPointer;
|
GenerationPointer newPointer;
|
||||||
Size oldsize;
|
Size oldsize;
|
||||||
|
|
||||||
/* Allow access to private part of chunk header. */
|
/* Allow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_DEFINED(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
@ -835,8 +827,8 @@ GenerationRealloc(void *pointer, Size size)
|
|||||||
VALGRIND_MAKE_MEM_DEFINED(pointer, size);
|
VALGRIND_MAKE_MEM_DEFINED(pointer, size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
@ -847,8 +839,8 @@ GenerationRealloc(void *pointer, Size size)
|
|||||||
/* leave immediately if request was not completed */
|
/* leave immediately if request was not completed */
|
||||||
if (newPointer == NULL)
|
if (newPointer == NULL)
|
||||||
{
|
{
|
||||||
/* Disallow external access to private part of chunk header. */
|
/* Disallow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Generation_CHUNKHDRSZ);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -886,11 +878,17 @@ GenerationGetChunkContext(void *pointer)
|
|||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
GenerationBlock *block;
|
GenerationBlock *block;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
block = ExternalChunkGetBlock(chunk);
|
block = ExternalChunkGetBlock(chunk);
|
||||||
else
|
else
|
||||||
block = (GenerationBlock *) MemoryChunkGetBlock(chunk);
|
block = (GenerationBlock *) MemoryChunkGetBlock(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
Assert(GenerationBlockIsValid(block));
|
Assert(GenerationBlockIsValid(block));
|
||||||
return &block->context->header;
|
return &block->context->header;
|
||||||
}
|
}
|
||||||
@ -906,6 +904,9 @@ GenerationGetChunkSpace(void *pointer)
|
|||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
Size chunksize;
|
Size chunksize;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
GenerationBlock *block = ExternalChunkGetBlock(chunk);
|
GenerationBlock *block = ExternalChunkGetBlock(chunk);
|
||||||
@ -916,6 +917,9 @@ GenerationGetChunkSpace(void *pointer)
|
|||||||
else
|
else
|
||||||
chunksize = MemoryChunkGetValue(chunk);
|
chunksize = MemoryChunkGetValue(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
return Generation_CHUNKHDRSZ + chunksize;
|
return Generation_CHUNKHDRSZ + chunksize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1057,8 +1061,8 @@ GenerationCheck(MemoryContext context)
|
|||||||
GenerationBlock *chunkblock;
|
GenerationBlock *chunkblock;
|
||||||
Size chunksize;
|
Size chunksize;
|
||||||
|
|
||||||
/* Allow access to private part of chunk header. */
|
/* Allow access to the chunk header. */
|
||||||
VALGRIND_MAKE_MEM_DEFINED(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Generation_CHUNKHDRSZ);
|
||||||
|
|
||||||
if (MemoryChunkIsExternal(chunk))
|
if (MemoryChunkIsExternal(chunk))
|
||||||
{
|
{
|
||||||
@ -1101,12 +1105,9 @@ GenerationCheck(MemoryContext context)
|
|||||||
else
|
else
|
||||||
nfree += 1;
|
nfree += 1;
|
||||||
|
|
||||||
/*
|
/* if chunk is allocated, disallow access to the chunk header */
|
||||||
* If chunk is allocated, disallow external access to private part
|
|
||||||
* of chunk header.
|
|
||||||
*/
|
|
||||||
if (chunk->requested_size != InvalidAllocSize)
|
if (chunk->requested_size != InvalidAllocSize)
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(chunk, GENERATIONCHUNK_PRIVATE_LEN);
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Generation_CHUNKHDRSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -190,8 +190,14 @@ GetMemoryChunkMethodID(const void *pointer)
|
|||||||
*/
|
*/
|
||||||
Assert(pointer == (const void *) MAXALIGN(pointer));
|
Assert(pointer == (const void *) MAXALIGN(pointer));
|
||||||
|
|
||||||
|
/* Allow access to the uint64 header */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
|
||||||
|
|
||||||
header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
|
header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
|
||||||
|
|
||||||
|
/* Disallow access to the uint64 header */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
|
||||||
|
|
||||||
return (MemoryContextMethodID) (header & MEMORY_CONTEXT_METHODID_MASK);
|
return (MemoryContextMethodID) (header & MEMORY_CONTEXT_METHODID_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +210,17 @@ GetMemoryChunkMethodID(const void *pointer)
|
|||||||
static inline uint64
|
static inline uint64
|
||||||
GetMemoryChunkHeader(const void *pointer)
|
GetMemoryChunkHeader(const void *pointer)
|
||||||
{
|
{
|
||||||
return *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
|
uint64 header;
|
||||||
|
|
||||||
|
/* Allow access to the uint64 header */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED((char *) pointer - sizeof(uint64), sizeof(uint64));
|
||||||
|
|
||||||
|
header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
|
||||||
|
|
||||||
|
/* Disallow access to the uint64 header */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer - sizeof(uint64), sizeof(uint64));
|
||||||
|
|
||||||
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1404,6 +1420,10 @@ MemoryContextAllocAligned(MemoryContext context,
|
|||||||
/* Mark the bytes before the redirection header as noaccess */
|
/* Mark the bytes before the redirection header as noaccess */
|
||||||
VALGRIND_MAKE_MEM_NOACCESS(unaligned,
|
VALGRIND_MAKE_MEM_NOACCESS(unaligned,
|
||||||
(char *) alignedchunk - (char *) unaligned);
|
(char *) alignedchunk - (char *) unaligned);
|
||||||
|
|
||||||
|
/* Disallow access to the redirection chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(alignedchunk, sizeof(MemoryChunk));
|
||||||
|
|
||||||
return aligned;
|
return aligned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,6 +630,9 @@ SlabAlloc(MemoryContext context, Size size)
|
|||||||
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
return MemoryChunkGetPointer(chunk);
|
return MemoryChunkGetPointer(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,11 +644,16 @@ void
|
|||||||
SlabFree(void *pointer)
|
SlabFree(void *pointer)
|
||||||
{
|
{
|
||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
SlabBlock *block = MemoryChunkGetBlock(chunk);
|
SlabBlock *block;
|
||||||
SlabContext *slab;
|
SlabContext *slab;
|
||||||
int curBlocklistIdx;
|
int curBlocklistIdx;
|
||||||
int newBlocklistIdx;
|
int newBlocklistIdx;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
|
block = MemoryChunkGetBlock(chunk);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For speed reasons we just Assert that the referenced block is good.
|
* For speed reasons we just Assert that the referenced block is good.
|
||||||
* Future field experience may show that this Assert had better become a
|
* Future field experience may show that this Assert had better become a
|
||||||
@ -761,9 +769,17 @@ void *
|
|||||||
SlabRealloc(void *pointer, Size size)
|
SlabRealloc(void *pointer, Size size)
|
||||||
{
|
{
|
||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
SlabBlock *block = MemoryChunkGetBlock(chunk);
|
SlabBlock *block;
|
||||||
SlabContext *slab;
|
SlabContext *slab;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
|
block = MemoryChunkGetBlock(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to verify that we have a sane block pointer: the block header
|
* Try to verify that we have a sane block pointer: the block header
|
||||||
* should reference a slab context. (We use a test-and-elog, not just
|
* should reference a slab context. (We use a test-and-elog, not just
|
||||||
@ -790,9 +806,18 @@ MemoryContext
|
|||||||
SlabGetChunkContext(void *pointer)
|
SlabGetChunkContext(void *pointer)
|
||||||
{
|
{
|
||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
SlabBlock *block = MemoryChunkGetBlock(chunk);
|
SlabBlock *block;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
|
block = MemoryChunkGetBlock(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
Assert(SlabBlockIsValid(block));
|
Assert(SlabBlockIsValid(block));
|
||||||
|
|
||||||
return &block->slab->header;
|
return &block->slab->header;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,9 +830,17 @@ Size
|
|||||||
SlabGetChunkSpace(void *pointer)
|
SlabGetChunkSpace(void *pointer)
|
||||||
{
|
{
|
||||||
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
||||||
SlabBlock *block = MemoryChunkGetBlock(chunk);
|
SlabBlock *block;
|
||||||
SlabContext *slab;
|
SlabContext *slab;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
|
block = MemoryChunkGetBlock(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
Assert(SlabBlockIsValid(block));
|
Assert(SlabBlockIsValid(block));
|
||||||
slab = block->slab;
|
slab = block->slab;
|
||||||
|
|
||||||
@ -1017,7 +1050,15 @@ SlabCheck(MemoryContext context)
|
|||||||
if (!slab->isChunkFree[j])
|
if (!slab->isChunkFree[j])
|
||||||
{
|
{
|
||||||
MemoryChunk *chunk = SlabBlockGetChunk(slab, block, j);
|
MemoryChunk *chunk = SlabBlockGetChunk(slab, block, j);
|
||||||
SlabBlock *chunkblock = (SlabBlock *) MemoryChunkGetBlock(chunk);
|
SlabBlock *chunkblock;
|
||||||
|
|
||||||
|
/* Allow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
|
chunkblock = (SlabBlock *) MemoryChunkGetBlock(chunk);
|
||||||
|
|
||||||
|
/* Disallow access to the chunk header. */
|
||||||
|
VALGRIND_MAKE_MEM_NOACCESS(chunk, Slab_CHUNKHDRSZ);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check the chunk's blockoffset correctly points back to
|
* check the chunk's blockoffset correctly points back to
|
||||||
|
Reference in New Issue
Block a user