@@ -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 ;
@@ -508,7 +509,10 @@ AllocSetContextCreate(MemoryContext parent,
508
509
block -> aset = context ;
509
510
block -> freeptr = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
510
511
block -> endptr = ((char * ) block ) + blksize ;
512
+ block -> prev = NULL ;
511
513
block -> next = context -> blocks ;
514
+ if (block -> next )
515
+ block -> next -> prev = block ;
512
516
context -> blocks = block ;
513
517
/* Mark block as not to be released at reset time */
514
518
context -> keeper = block ;
@@ -590,6 +594,7 @@ AllocSetReset(MemoryContext context)
590
594
VALGRIND_MAKE_MEM_NOACCESS (datastart , block -> freeptr - datastart );
591
595
#endif
592
596
block -> freeptr = datastart ;
597
+ block -> prev = NULL ;
593
598
block -> next = NULL ;
594
599
}
595
600
else
@@ -702,16 +707,20 @@ AllocSetAlloc(MemoryContext context, Size size)
702
707
#endif
703
708
704
709
/*
705
- * Stick the new block underneath the active allocation block, so that
706
- * we don't lose the use of the space remaining therein.
710
+ * Stick the new block underneath the active allocation block, if any,
711
+ * so that we don't lose the use of the space remaining therein.
707
712
*/
708
713
if (set -> blocks != NULL )
709
714
{
715
+ block -> prev = set -> blocks ;
710
716
block -> next = set -> blocks -> next ;
717
+ if (block -> next )
718
+ block -> next -> prev = block ;
711
719
set -> blocks -> next = block ;
712
720
}
713
721
else
714
722
{
723
+ block -> prev = NULL ;
715
724
block -> next = NULL ;
716
725
set -> blocks = block ;
717
726
}
@@ -898,7 +907,10 @@ AllocSetAlloc(MemoryContext context, Size size)
898
907
VALGRIND_MAKE_MEM_NOACCESS (block -> freeptr ,
899
908
blksize - ALLOC_BLOCKHDRSZ );
900
909
910
+ block -> prev = NULL ;
901
911
block -> next = set -> blocks ;
912
+ if (block -> next )
913
+ block -> next -> prev = block ;
902
914
set -> blocks = block ;
903
915
}
904
916
@@ -958,29 +970,28 @@ AllocSetFree(MemoryContext context, void *pointer)
958
970
{
959
971
/*
960
972
* Big chunks are certain to have been allocated as single-chunk
961
- * blocks. Find the containing block and return it to malloc().
973
+ * blocks. Just unlink that block and return it to malloc().
962
974
*/
963
- AllocBlock block = set -> blocks ;
964
- AllocBlock prevblock = NULL ;
975
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
965
976
966
- while (block != NULL )
967
- {
968
- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
969
- break ;
970
- prevblock = block ;
971
- block = block -> next ;
972
- }
973
- if (block == NULL )
977
+ /*
978
+ * Try to verify that we have a sane block pointer: it should
979
+ * reference the correct aset, and freeptr and endptr should point
980
+ * just past the chunk.
981
+ */
982
+ if (block -> aset != set ||
983
+ block -> freeptr != block -> endptr ||
984
+ block -> freeptr != ((char * ) block ) +
985
+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
974
986
elog (ERROR , "could not find block containing chunk %p" , chunk );
975
- /* let's just make sure chunk is the only one in the block */
976
- Assert (block -> freeptr == ((char * ) block ) +
977
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
978
987
979
988
/* OK, remove block from aset's list and free it */
980
- if (prevblock == NULL )
981
- set -> blocks = block -> next ;
989
+ if (block -> prev )
990
+ block -> prev -> next = block -> next ;
982
991
else
983
- prevblock -> next = block -> next ;
992
+ set -> blocks = block -> next ;
993
+ if (block -> next )
994
+ block -> next -> prev = block -> prev ;
984
995
#ifdef CLOBBER_FREED_MEMORY
985
996
wipe_mem (block , block -> freeptr - ((char * ) block ));
986
997
#endif
@@ -1085,27 +1096,24 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1085
1096
if (oldsize > set -> allocChunkLimit )
1086
1097
{
1087
1098
/*
1088
- * The chunk must have been allocated as a single-chunk block. Find
1089
- * the containing block and use realloc() to make it bigger with
1090
- * minimum space wastage.
1099
+ * The chunk must have been allocated as a single-chunk block. Use
1100
+ * realloc() to make the containing block bigger with minimum space
1101
+ * wastage.
1091
1102
*/
1092
- AllocBlock block = set -> blocks ;
1093
- AllocBlock prevblock = NULL ;
1103
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
1094
1104
Size chksize ;
1095
1105
Size blksize ;
1096
1106
1097
- while (block != NULL )
1098
- {
1099
- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
1100
- break ;
1101
- prevblock = block ;
1102
- block = block -> next ;
1103
- }
1104
- if (block == NULL )
1107
+ /*
1108
+ * Try to verify that we have a sane block pointer: it should
1109
+ * reference the correct aset, and freeptr and endptr should point
1110
+ * just past the chunk.
1111
+ */
1112
+ if (block -> aset != set ||
1113
+ block -> freeptr != block -> endptr ||
1114
+ block -> freeptr != ((char * ) block ) +
1115
+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1105
1116
elog (ERROR , "could not find block containing chunk %p" , chunk );
1106
- /* let's just make sure chunk is the only one in the block */
1107
- Assert (block -> freeptr == ((char * ) block ) +
1108
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
1109
1117
1110
1118
/* Do the realloc */
1111
1119
chksize = MAXALIGN (size );
@@ -1124,10 +1132,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1124
1132
/* Update pointers since block has likely been moved */
1125
1133
chunk = (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ );
1126
1134
pointer = AllocChunkGetPointer (chunk );
1127
- if (prevblock == NULL )
1128
- set -> blocks = block ;
1135
+ if (block -> prev )
1136
+ block -> prev -> next = block ;
1129
1137
else
1130
- prevblock -> next = block ;
1138
+ set -> blocks = block ;
1139
+ if (block -> next )
1140
+ block -> next -> prev = block ;
1131
1141
chunk -> size = chksize ;
1132
1142
1133
1143
#ifdef MEMORY_CONTEXT_CHECKING
@@ -1151,7 +1161,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1151
1161
1152
1162
/* set mark to catch clobber of "unused" space */
1153
1163
if (size < chunk -> size )
1154
- set_sentinel (AllocChunkGetPointer ( chunk ) , size );
1164
+ set_sentinel (pointer , size );
1155
1165
#else /* !MEMORY_CONTEXT_CHECKING */
1156
1166
1157
1167
/*
@@ -1164,7 +1174,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1164
1174
1165
1175
/* Make any trailing alignment padding NOACCESS. */
1166
1176
VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size , chksize - size );
1167
- return AllocChunkGetPointer (chunk );
1177
+
1178
+ return pointer ;
1168
1179
}
1169
1180
else
1170
1181
{
@@ -1297,9 +1308,12 @@ AllocSetCheck(MemoryContext context)
1297
1308
{
1298
1309
AllocSet set = (AllocSet ) context ;
1299
1310
char * name = set -> header .name ;
1311
+ AllocBlock prevblock ;
1300
1312
AllocBlock block ;
1301
1313
1302
- for (block = set -> blocks ; block != NULL ; block = block -> next )
1314
+ for (prevblock = NULL , block = set -> blocks ;
1315
+ block != NULL ;
1316
+ prevblock = block , block = block -> next )
1303
1317
{
1304
1318
char * bpoz = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
1305
1319
long blk_used = block -> freeptr - bpoz ;
@@ -1316,6 +1330,16 @@ AllocSetCheck(MemoryContext context)
1316
1330
name , block );
1317
1331
}
1318
1332
1333
+ /*
1334
+ * Check block header fields
1335
+ */
1336
+ if (block -> aset != set ||
1337
+ block -> prev != prevblock ||
1338
+ block -> freeptr < bpoz ||
1339
+ block -> freeptr > block -> endptr )
1340
+ elog (WARNING , "problem in alloc set %s: corrupt header in block %p" ,
1341
+ name , block );
1342
+
1319
1343
/*
1320
1344
* Chunk walker
1321
1345
*/
0 commit comments