@@ -148,7 +148,8 @@ typedef AllocSetContext *AllocSet;
148
148
typedef struct AllocBlockData
149
149
{
150
150
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 */
152
153
char * freeptr ; /* start of free space in this block */
153
154
char * endptr ; /* end of space in this block */
154
155
} AllocBlockData ;
@@ -407,7 +408,10 @@ AllocSetContextCreate(MemoryContext parent,
407
408
block -> aset = set ;
408
409
block -> freeptr = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
409
410
block -> endptr = ((char * ) block ) + blksize ;
411
+ block -> prev = NULL ;
410
412
block -> next = set -> blocks ;
413
+ if (block -> next )
414
+ block -> next -> prev = block ;
411
415
set -> blocks = block ;
412
416
/* Mark block as not to be released at reset time */
413
417
set -> keeper = block ;
@@ -489,6 +493,7 @@ AllocSetReset(MemoryContext context)
489
493
VALGRIND_MAKE_MEM_NOACCESS (datastart , block -> freeptr - datastart );
490
494
#endif
491
495
block -> freeptr = datastart ;
496
+ block -> prev = NULL ;
492
497
block -> next = NULL ;
493
498
}
494
499
else
@@ -595,16 +600,20 @@ AllocSetAlloc(MemoryContext context, Size size)
595
600
#endif
596
601
597
602
/*
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.
600
605
*/
601
606
if (set -> blocks != NULL )
602
607
{
608
+ block -> prev = set -> blocks ;
603
609
block -> next = set -> blocks -> next ;
610
+ if (block -> next )
611
+ block -> next -> prev = block ;
604
612
set -> blocks -> next = block ;
605
613
}
606
614
else
607
615
{
616
+ block -> prev = NULL ;
608
617
block -> next = NULL ;
609
618
set -> blocks = block ;
610
619
}
@@ -785,7 +794,10 @@ AllocSetAlloc(MemoryContext context, Size size)
785
794
VALGRIND_MAKE_MEM_NOACCESS (block -> freeptr ,
786
795
blksize - ALLOC_BLOCKHDRSZ );
787
796
797
+ block -> prev = NULL ;
788
798
block -> next = set -> blocks ;
799
+ if (block -> next )
800
+ block -> next -> prev = block ;
789
801
set -> blocks = block ;
790
802
}
791
803
@@ -845,29 +857,28 @@ AllocSetFree(MemoryContext context, void *pointer)
845
857
{
846
858
/*
847
859
* 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().
849
861
*/
850
- AllocBlock block = set -> blocks ;
851
- AllocBlock prevblock = NULL ;
862
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
852
863
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 ))
861
873
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 ));
865
874
866
875
/* 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 ;
869
878
else
870
- prevblock -> next = block -> next ;
879
+ set -> blocks = block -> next ;
880
+ if (block -> next )
881
+ block -> next -> prev = block -> prev ;
871
882
#ifdef CLOBBER_FREED_MEMORY
872
883
wipe_mem (block , block -> freeptr - ((char * ) block ));
873
884
#endif
@@ -973,27 +984,24 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
973
984
if (oldsize > set -> allocChunkLimit )
974
985
{
975
986
/*
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.
979
990
*/
980
- AllocBlock block = set -> blocks ;
981
- AllocBlock prevblock = NULL ;
991
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
982
992
Size chksize ;
983
993
Size blksize ;
984
994
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 ))
993
1004
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 ));
997
1005
998
1006
/* Do the realloc */
999
1007
chksize = MAXALIGN (size );
@@ -1006,10 +1014,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1006
1014
/* Update pointers since block has likely been moved */
1007
1015
chunk = (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ );
1008
1016
pointer = AllocChunkGetPointer (chunk );
1009
- if (prevblock == NULL )
1010
- set -> blocks = block ;
1017
+ if (block -> prev )
1018
+ block -> prev -> next = block ;
1011
1019
else
1012
- prevblock -> next = block ;
1020
+ set -> blocks = block ;
1021
+ if (block -> next )
1022
+ block -> next -> prev = block ;
1013
1023
chunk -> size = chksize ;
1014
1024
1015
1025
#ifdef MEMORY_CONTEXT_CHECKING
@@ -1033,7 +1043,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1033
1043
1034
1044
/* set mark to catch clobber of "unused" space */
1035
1045
if (size < chunk -> size )
1036
- set_sentinel (AllocChunkGetPointer ( chunk ) , size );
1046
+ set_sentinel (pointer , size );
1037
1047
#else /* !MEMORY_CONTEXT_CHECKING */
1038
1048
1039
1049
/*
@@ -1046,7 +1056,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1046
1056
1047
1057
/* Make any trailing alignment padding NOACCESS. */
1048
1058
VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size , chksize - size );
1049
- return AllocChunkGetPointer (chunk );
1059
+
1060
+ return pointer ;
1050
1061
}
1051
1062
else
1052
1063
{
@@ -1200,9 +1211,12 @@ AllocSetCheck(MemoryContext context)
1200
1211
{
1201
1212
AllocSet set = (AllocSet ) context ;
1202
1213
char * name = set -> header .name ;
1214
+ AllocBlock prevblock ;
1203
1215
AllocBlock block ;
1204
1216
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 )
1206
1220
{
1207
1221
char * bpoz = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
1208
1222
long blk_used = block -> freeptr - bpoz ;
@@ -1219,6 +1233,16 @@ AllocSetCheck(MemoryContext context)
1219
1233
name , block );
1220
1234
}
1221
1235
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
+
1222
1246
/*
1223
1247
* Chunk walker
1224
1248
*/
0 commit comments