@@ -201,7 +201,8 @@ typedef AllocSetContext *AllocSet;
201
201
typedef struct AllocBlockData
202
202
{
203
203
AllocSet aset ; /* aset that owns this block */
204
- AllocBlock next ; /* next block in aset's blocks list */
204
+ AllocBlock prev ; /* prev block in aset's blocks list, if any */
205
+ AllocBlock next ; /* next block in aset's blocks list, if any */
205
206
char * freeptr ; /* start of free space in this block */
206
207
char * endptr ; /* end of space in this block */
207
208
} AllocBlockData ;
@@ -513,7 +514,10 @@ AllocSetContextCreate(MemoryContext parent,
513
514
block -> aset = set ;
514
515
block -> freeptr = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
515
516
block -> endptr = ((char * ) block ) + blksize ;
517
+ block -> prev = NULL ;
516
518
block -> next = set -> blocks ;
519
+ if (block -> next )
520
+ block -> next -> prev = block ;
517
521
set -> blocks = block ;
518
522
/* Mark block as not to be released at reset time */
519
523
set -> keeper = block ;
@@ -595,6 +599,7 @@ AllocSetReset(MemoryContext context)
595
599
VALGRIND_MAKE_MEM_NOACCESS (datastart , block -> freeptr - datastart );
596
600
#endif
597
601
block -> freeptr = datastart ;
602
+ block -> prev = NULL ;
598
603
block -> next = NULL ;
599
604
}
600
605
else
@@ -701,16 +706,20 @@ AllocSetAlloc(MemoryContext context, Size size)
701
706
#endif
702
707
703
708
/*
704
- * Stick the new block underneath the active allocation block, so that
705
- * we don't lose the use of the space remaining therein.
709
+ * Stick the new block underneath the active allocation block, if any,
710
+ * so that we don't lose the use of the space remaining therein.
706
711
*/
707
712
if (set -> blocks != NULL )
708
713
{
714
+ block -> prev = set -> blocks ;
709
715
block -> next = set -> blocks -> next ;
716
+ if (block -> next )
717
+ block -> next -> prev = block ;
710
718
set -> blocks -> next = block ;
711
719
}
712
720
else
713
721
{
722
+ block -> prev = NULL ;
714
723
block -> next = NULL ;
715
724
set -> blocks = block ;
716
725
}
@@ -891,7 +900,10 @@ AllocSetAlloc(MemoryContext context, Size size)
891
900
VALGRIND_MAKE_MEM_NOACCESS (block -> freeptr ,
892
901
blksize - ALLOC_BLOCKHDRSZ );
893
902
903
+ block -> prev = NULL ;
894
904
block -> next = set -> blocks ;
905
+ if (block -> next )
906
+ block -> next -> prev = block ;
895
907
set -> blocks = block ;
896
908
}
897
909
@@ -951,29 +963,28 @@ AllocSetFree(MemoryContext context, void *pointer)
951
963
{
952
964
/*
953
965
* Big chunks are certain to have been allocated as single-chunk
954
- * blocks. Find the containing block and return it to malloc().
966
+ * blocks. Just unlink that block and return it to malloc().
955
967
*/
956
- AllocBlock block = set -> blocks ;
957
- AllocBlock prevblock = NULL ;
968
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
958
969
959
- while (block != NULL )
960
- {
961
- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
962
- break ;
963
- prevblock = block ;
964
- block = block -> next ;
965
- }
966
- if (block == NULL )
970
+ /*
971
+ * Try to verify that we have a sane block pointer: it should
972
+ * reference the correct aset, and freeptr and endptr should point
973
+ * just past the chunk.
974
+ */
975
+ if (block -> aset != set ||
976
+ block -> freeptr != block -> endptr ||
977
+ block -> freeptr != ((char * ) block ) +
978
+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
967
979
elog (ERROR , "could not find block containing chunk %p" , chunk );
968
- /* let's just make sure chunk is the only one in the block */
969
- Assert (block -> freeptr == ((char * ) block ) +
970
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
971
980
972
981
/* OK, remove block from aset's list and free it */
973
- if (prevblock == NULL )
974
- set -> blocks = block -> next ;
982
+ if (block -> prev )
983
+ block -> prev -> next = block -> next ;
975
984
else
976
- prevblock -> next = block -> next ;
985
+ set -> blocks = block -> next ;
986
+ if (block -> next )
987
+ block -> next -> prev = block -> prev ;
977
988
#ifdef CLOBBER_FREED_MEMORY
978
989
wipe_mem (block , block -> freeptr - ((char * ) block ));
979
990
#endif
@@ -1079,27 +1090,24 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1079
1090
if (oldsize > set -> allocChunkLimit )
1080
1091
{
1081
1092
/*
1082
- * The chunk must have been allocated as a single-chunk block. Find
1083
- * the containing block and use realloc() to make it bigger with
1084
- * minimum space wastage.
1093
+ * The chunk must have been allocated as a single-chunk block. Use
1094
+ * realloc() to make the containing block bigger with minimum space
1095
+ * wastage.
1085
1096
*/
1086
- AllocBlock block = set -> blocks ;
1087
- AllocBlock prevblock = NULL ;
1097
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
1088
1098
Size chksize ;
1089
1099
Size blksize ;
1090
1100
1091
- while (block != NULL )
1092
- {
1093
- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
1094
- break ;
1095
- prevblock = block ;
1096
- block = block -> next ;
1097
- }
1098
- if (block == NULL )
1101
+ /*
1102
+ * Try to verify that we have a sane block pointer: it should
1103
+ * reference the correct aset, and freeptr and endptr should point
1104
+ * just past the chunk.
1105
+ */
1106
+ if (block -> aset != set ||
1107
+ block -> freeptr != block -> endptr ||
1108
+ block -> freeptr != ((char * ) block ) +
1109
+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1099
1110
elog (ERROR , "could not find block containing chunk %p" , chunk );
1100
- /* let's just make sure chunk is the only one in the block */
1101
- Assert (block -> freeptr == ((char * ) block ) +
1102
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
1103
1111
1104
1112
/* Do the realloc */
1105
1113
chksize = MAXALIGN (size );
@@ -1112,10 +1120,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1112
1120
/* Update pointers since block has likely been moved */
1113
1121
chunk = (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ );
1114
1122
pointer = AllocChunkGetPointer (chunk );
1115
- if (prevblock == NULL )
1116
- set -> blocks = block ;
1123
+ if (block -> prev )
1124
+ block -> prev -> next = block ;
1117
1125
else
1118
- prevblock -> next = block ;
1126
+ set -> blocks = block ;
1127
+ if (block -> next )
1128
+ block -> next -> prev = block ;
1119
1129
chunk -> size = chksize ;
1120
1130
1121
1131
#ifdef MEMORY_CONTEXT_CHECKING
@@ -1139,7 +1149,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1139
1149
1140
1150
/* set mark to catch clobber of "unused" space */
1141
1151
if (size < chunk -> size )
1142
- set_sentinel (AllocChunkGetPointer ( chunk ) , size );
1152
+ set_sentinel (pointer , size );
1143
1153
#else /* !MEMORY_CONTEXT_CHECKING */
1144
1154
1145
1155
/*
@@ -1152,7 +1162,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1152
1162
1153
1163
/* Make any trailing alignment padding NOACCESS. */
1154
1164
VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size , chksize - size );
1155
- return AllocChunkGetPointer (chunk );
1165
+
1166
+ return pointer ;
1156
1167
}
1157
1168
else
1158
1169
{
@@ -1306,9 +1317,12 @@ AllocSetCheck(MemoryContext context)
1306
1317
{
1307
1318
AllocSet set = (AllocSet ) context ;
1308
1319
char * name = set -> header .name ;
1320
+ AllocBlock prevblock ;
1309
1321
AllocBlock block ;
1310
1322
1311
- for (block = set -> blocks ; block != NULL ; block = block -> next )
1323
+ for (prevblock = NULL , block = set -> blocks ;
1324
+ block != NULL ;
1325
+ prevblock = block , block = block -> next )
1312
1326
{
1313
1327
char * bpoz = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
1314
1328
long blk_used = block -> freeptr - bpoz ;
@@ -1325,6 +1339,16 @@ AllocSetCheck(MemoryContext context)
1325
1339
name , block );
1326
1340
}
1327
1341
1342
+ /*
1343
+ * Check block header fields
1344
+ */
1345
+ if (block -> aset != set ||
1346
+ block -> prev != prevblock ||
1347
+ block -> freeptr < bpoz ||
1348
+ block -> freeptr > block -> endptr )
1349
+ elog (WARNING , "problem in alloc set %s: corrupt header in block %p" ,
1350
+ name , block );
1351
+
1328
1352
/*
1329
1353
* Chunk walker
1330
1354
*/
0 commit comments