@@ -148,7 +148,8 @@ typedef AllocSetContext *AllocSet;
148148typedef struct AllocBlockData
149149{
150150 AllocSet aset ; /* aset that owns this block */
151- AllocBlock next ; /* next block in aset's blocks list */
151+ AllocBlock prev ; /* prev block in aset's blocks list, if any */
152+ AllocBlock next ; /* next block in aset's blocks list, if any */
152153 char * freeptr ; /* start of free space in this block */
153154 char * endptr ; /* end of space in this block */
154155} AllocBlockData ;
@@ -407,7 +408,10 @@ AllocSetContextCreate(MemoryContext parent,
407408 block -> aset = set ;
408409 block -> freeptr = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
409410 block -> endptr = ((char * ) block ) + blksize ;
411+ block -> prev = NULL ;
410412 block -> next = set -> blocks ;
413+ if (block -> next )
414+ block -> next -> prev = block ;
411415 set -> blocks = block ;
412416 /* Mark block as not to be released at reset time */
413417 set -> keeper = block ;
@@ -489,6 +493,7 @@ AllocSetReset(MemoryContext context)
489493 VALGRIND_MAKE_MEM_NOACCESS (datastart , block -> freeptr - datastart );
490494#endif
491495 block -> freeptr = datastart ;
496+ block -> prev = NULL ;
492497 block -> next = NULL ;
493498 }
494499 else
@@ -595,16 +600,20 @@ AllocSetAlloc(MemoryContext context, Size size)
595600#endif
596601
597602 /*
598- * Stick the new block underneath the active allocation block, so that
599- * we don't lose the use of the space remaining therein.
603+ * Stick the new block underneath the active allocation block, if any,
604+ * so that we don't lose the use of the space remaining therein.
600605 */
601606 if (set -> blocks != NULL )
602607 {
608+ block -> prev = set -> blocks ;
603609 block -> next = set -> blocks -> next ;
610+ if (block -> next )
611+ block -> next -> prev = block ;
604612 set -> blocks -> next = block ;
605613 }
606614 else
607615 {
616+ block -> prev = NULL ;
608617 block -> next = NULL ;
609618 set -> blocks = block ;
610619 }
@@ -785,7 +794,10 @@ AllocSetAlloc(MemoryContext context, Size size)
785794 VALGRIND_MAKE_MEM_NOACCESS (block -> freeptr ,
786795 blksize - ALLOC_BLOCKHDRSZ );
787796
797+ block -> prev = NULL ;
788798 block -> next = set -> blocks ;
799+ if (block -> next )
800+ block -> next -> prev = block ;
789801 set -> blocks = block ;
790802 }
791803
@@ -845,29 +857,28 @@ AllocSetFree(MemoryContext context, void *pointer)
845857 {
846858 /*
847859 * Big chunks are certain to have been allocated as single-chunk
848- * blocks. Find the containing block and return it to malloc().
860+ * blocks. Just unlink that block and return it to malloc().
849861 */
850- AllocBlock block = set -> blocks ;
851- AllocBlock prevblock = NULL ;
862+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
852863
853- while (block != NULL )
854- {
855- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
856- break ;
857- prevblock = block ;
858- block = block -> next ;
859- }
860- if (block == NULL )
864+ /*
865+ * Try to verify that we have a sane block pointer: it should
866+ * reference the correct aset, and freeptr and endptr should point
867+ * just past the chunk.
868+ */
869+ if (block -> aset != set ||
870+ block -> freeptr != block -> endptr ||
871+ block -> freeptr != ((char * ) block ) +
872+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
861873 elog (ERROR , "could not find block containing chunk %p" , chunk );
862- /* let's just make sure chunk is the only one in the block */
863- Assert (block -> freeptr == ((char * ) block ) +
864- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
865874
866875 /* OK, remove block from aset's list and free it */
867- if (prevblock == NULL )
868- set -> blocks = block -> next ;
876+ if (block -> prev )
877+ block -> prev -> next = block -> next ;
869878 else
870- prevblock -> next = block -> next ;
879+ set -> blocks = block -> next ;
880+ if (block -> next )
881+ block -> next -> prev = block -> prev ;
871882#ifdef CLOBBER_FREED_MEMORY
872883 wipe_mem (block , block -> freeptr - ((char * ) block ));
873884#endif
@@ -973,27 +984,24 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
973984 if (oldsize > set -> allocChunkLimit )
974985 {
975986 /*
976- * The chunk must have been allocated as a single-chunk block. Find
977- * the containing block and use realloc() to make it bigger with
978- * minimum space wastage.
987+ * The chunk must have been allocated as a single-chunk block. Use
988+ * realloc() to make the containing block bigger with minimum space
989+ * wastage.
979990 */
980- AllocBlock block = set -> blocks ;
981- AllocBlock prevblock = NULL ;
991+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
982992 Size chksize ;
983993 Size blksize ;
984994
985- while (block != NULL )
986- {
987- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
988- break ;
989- prevblock = block ;
990- block = block -> next ;
991- }
992- if (block == NULL )
995+ /*
996+ * Try to verify that we have a sane block pointer: it should
997+ * reference the correct aset, and freeptr and endptr should point
998+ * just past the chunk.
999+ */
1000+ if (block -> aset != set ||
1001+ block -> freeptr != block -> endptr ||
1002+ block -> freeptr != ((char * ) block ) +
1003+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
9931004 elog (ERROR , "could not find block containing chunk %p" , chunk );
994- /* let's just make sure chunk is the only one in the block */
995- Assert (block -> freeptr == ((char * ) block ) +
996- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
9971005
9981006 /* Do the realloc */
9991007 chksize = MAXALIGN (size );
@@ -1006,10 +1014,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
10061014 /* Update pointers since block has likely been moved */
10071015 chunk = (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ );
10081016 pointer = AllocChunkGetPointer (chunk );
1009- if (prevblock == NULL )
1010- set -> blocks = block ;
1017+ if (block -> prev )
1018+ block -> prev -> next = block ;
10111019 else
1012- prevblock -> next = block ;
1020+ set -> blocks = block ;
1021+ if (block -> next )
1022+ block -> next -> prev = block ;
10131023 chunk -> size = chksize ;
10141024
10151025#ifdef MEMORY_CONTEXT_CHECKING
@@ -1033,7 +1043,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
10331043
10341044 /* set mark to catch clobber of "unused" space */
10351045 if (size < chunk -> size )
1036- set_sentinel (AllocChunkGetPointer ( chunk ) , size );
1046+ set_sentinel (pointer , size );
10371047#else /* !MEMORY_CONTEXT_CHECKING */
10381048
10391049 /*
@@ -1046,7 +1056,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
10461056
10471057 /* Make any trailing alignment padding NOACCESS. */
10481058 VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size , chksize - size );
1049- return AllocChunkGetPointer (chunk );
1059+
1060+ return pointer ;
10501061 }
10511062 else
10521063 {
@@ -1200,9 +1211,12 @@ AllocSetCheck(MemoryContext context)
12001211{
12011212 AllocSet set = (AllocSet ) context ;
12021213 char * name = set -> header .name ;
1214+ AllocBlock prevblock ;
12031215 AllocBlock block ;
12041216
1205- for (block = set -> blocks ; block != NULL ; block = block -> next )
1217+ for (prevblock = NULL , block = set -> blocks ;
1218+ block != NULL ;
1219+ prevblock = block , block = block -> next )
12061220 {
12071221 char * bpoz = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
12081222 long blk_used = block -> freeptr - bpoz ;
@@ -1219,6 +1233,16 @@ AllocSetCheck(MemoryContext context)
12191233 name , block );
12201234 }
12211235
1236+ /*
1237+ * Check block header fields
1238+ */
1239+ if (block -> aset != set ||
1240+ block -> prev != prevblock ||
1241+ block -> freeptr < bpoz ||
1242+ block -> freeptr > block -> endptr )
1243+ elog (WARNING , "problem in alloc set %s: corrupt header in block %p" ,
1244+ name , block );
1245+
12221246 /*
12231247 * Chunk walker
12241248 */
0 commit comments