@@ -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 = set ;
509
510
block -> freeptr = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
510
511
block -> endptr = ((char * ) block ) + blksize ;
512
+ block -> prev = NULL ;
511
513
block -> next = set -> blocks ;
514
+ if (block -> next )
515
+ block -> next -> prev = block ;
512
516
set -> blocks = block ;
513
517
/* Mark block as not to be released at reset time */
514
518
set -> 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
@@ -696,16 +701,20 @@ AllocSetAlloc(MemoryContext context, Size size)
696
701
#endif
697
702
698
703
/*
699
- * Stick the new block underneath the active allocation block, so that
700
- * we don't lose the use of the space remaining therein.
704
+ * Stick the new block underneath the active allocation block, if any,
705
+ * so that we don't lose the use of the space remaining therein.
701
706
*/
702
707
if (set -> blocks != NULL )
703
708
{
709
+ block -> prev = set -> blocks ;
704
710
block -> next = set -> blocks -> next ;
711
+ if (block -> next )
712
+ block -> next -> prev = block ;
705
713
set -> blocks -> next = block ;
706
714
}
707
715
else
708
716
{
717
+ block -> prev = NULL ;
709
718
block -> next = NULL ;
710
719
set -> blocks = block ;
711
720
}
@@ -886,7 +895,10 @@ AllocSetAlloc(MemoryContext context, Size size)
886
895
VALGRIND_MAKE_MEM_NOACCESS (block -> freeptr ,
887
896
blksize - ALLOC_BLOCKHDRSZ );
888
897
898
+ block -> prev = NULL ;
889
899
block -> next = set -> blocks ;
900
+ if (block -> next )
901
+ block -> next -> prev = block ;
890
902
set -> blocks = block ;
891
903
}
892
904
@@ -946,29 +958,28 @@ AllocSetFree(MemoryContext context, void *pointer)
946
958
{
947
959
/*
948
960
* Big chunks are certain to have been allocated as single-chunk
949
- * blocks. Find the containing block and return it to malloc().
961
+ * blocks. Just unlink that block and return it to malloc().
950
962
*/
951
- AllocBlock block = set -> blocks ;
952
- AllocBlock prevblock = NULL ;
963
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
953
964
954
- while (block != NULL )
955
- {
956
- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
957
- break ;
958
- prevblock = block ;
959
- block = block -> next ;
960
- }
961
- if (block == NULL )
965
+ /*
966
+ * Try to verify that we have a sane block pointer: it should
967
+ * reference the correct aset, and freeptr and endptr should point
968
+ * just past the chunk.
969
+ */
970
+ if (block -> aset != set ||
971
+ block -> freeptr != block -> endptr ||
972
+ block -> freeptr != ((char * ) block ) +
973
+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
962
974
elog (ERROR , "could not find block containing chunk %p" , chunk );
963
- /* let's just make sure chunk is the only one in the block */
964
- Assert (block -> freeptr == ((char * ) block ) +
965
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
966
975
967
976
/* OK, remove block from aset's list and free it */
968
- if (prevblock == NULL )
969
- set -> blocks = block -> next ;
977
+ if (block -> prev )
978
+ block -> prev -> next = block -> next ;
970
979
else
971
- prevblock -> next = block -> next ;
980
+ set -> blocks = block -> next ;
981
+ if (block -> next )
982
+ block -> next -> prev = block -> prev ;
972
983
#ifdef CLOBBER_FREED_MEMORY
973
984
wipe_mem (block , block -> freeptr - ((char * ) block ));
974
985
#endif
@@ -1074,27 +1085,24 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1074
1085
if (oldsize > set -> allocChunkLimit )
1075
1086
{
1076
1087
/*
1077
- * The chunk must have been allocated as a single-chunk block. Find
1078
- * the containing block and use realloc() to make it bigger with
1079
- * minimum space wastage.
1088
+ * The chunk must have been allocated as a single-chunk block. Use
1089
+ * realloc() to make the containing block bigger with minimum space
1090
+ * wastage.
1080
1091
*/
1081
- AllocBlock block = set -> blocks ;
1082
- AllocBlock prevblock = NULL ;
1092
+ AllocBlock block = (AllocBlock ) (((char * ) chunk ) - ALLOC_BLOCKHDRSZ );
1083
1093
Size chksize ;
1084
1094
Size blksize ;
1085
1095
1086
- while (block != NULL )
1087
- {
1088
- if (chunk == (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ ))
1089
- break ;
1090
- prevblock = block ;
1091
- block = block -> next ;
1092
- }
1093
- if (block == NULL )
1096
+ /*
1097
+ * Try to verify that we have a sane block pointer: it should
1098
+ * reference the correct aset, and freeptr and endptr should point
1099
+ * just past the chunk.
1100
+ */
1101
+ if (block -> aset != set ||
1102
+ block -> freeptr != block -> endptr ||
1103
+ block -> freeptr != ((char * ) block ) +
1104
+ (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ))
1094
1105
elog (ERROR , "could not find block containing chunk %p" , chunk );
1095
- /* let's just make sure chunk is the only one in the block */
1096
- Assert (block -> freeptr == ((char * ) block ) +
1097
- (chunk -> size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ ));
1098
1106
1099
1107
/* Do the realloc */
1100
1108
chksize = MAXALIGN (size );
@@ -1107,10 +1115,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1107
1115
/* Update pointers since block has likely been moved */
1108
1116
chunk = (AllocChunk ) (((char * ) block ) + ALLOC_BLOCKHDRSZ );
1109
1117
pointer = AllocChunkGetPointer (chunk );
1110
- if (prevblock == NULL )
1111
- set -> blocks = block ;
1118
+ if (block -> prev )
1119
+ block -> prev -> next = block ;
1112
1120
else
1113
- prevblock -> next = block ;
1121
+ set -> blocks = block ;
1122
+ if (block -> next )
1123
+ block -> next -> prev = block ;
1114
1124
chunk -> size = chksize ;
1115
1125
1116
1126
#ifdef MEMORY_CONTEXT_CHECKING
@@ -1134,7 +1144,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1134
1144
1135
1145
/* set mark to catch clobber of "unused" space */
1136
1146
if (size < chunk -> size )
1137
- set_sentinel (AllocChunkGetPointer ( chunk ) , size );
1147
+ set_sentinel (pointer , size );
1138
1148
#else /* !MEMORY_CONTEXT_CHECKING */
1139
1149
1140
1150
/*
@@ -1147,7 +1157,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
1147
1157
1148
1158
/* Make any trailing alignment padding NOACCESS. */
1149
1159
VALGRIND_MAKE_MEM_NOACCESS ((char * ) pointer + size , chksize - size );
1150
- return AllocChunkGetPointer (chunk );
1160
+
1161
+ return pointer ;
1151
1162
}
1152
1163
else
1153
1164
{
@@ -1284,9 +1295,12 @@ AllocSetCheck(MemoryContext context)
1284
1295
{
1285
1296
AllocSet set = (AllocSet ) context ;
1286
1297
char * name = set -> header .name ;
1298
+ AllocBlock prevblock ;
1287
1299
AllocBlock block ;
1288
1300
1289
- for (block = set -> blocks ; block != NULL ; block = block -> next )
1301
+ for (prevblock = NULL , block = set -> blocks ;
1302
+ block != NULL ;
1303
+ prevblock = block , block = block -> next )
1290
1304
{
1291
1305
char * bpoz = ((char * ) block ) + ALLOC_BLOCKHDRSZ ;
1292
1306
long blk_used = block -> freeptr - bpoz ;
@@ -1303,6 +1317,16 @@ AllocSetCheck(MemoryContext context)
1303
1317
name , block );
1304
1318
}
1305
1319
1320
+ /*
1321
+ * Check block header fields
1322
+ */
1323
+ if (block -> aset != set ||
1324
+ block -> prev != prevblock ||
1325
+ block -> freeptr < bpoz ||
1326
+ block -> freeptr > block -> endptr )
1327
+ elog (WARNING , "problem in alloc set %s: corrupt header in block %p" ,
1328
+ name , block );
1329
+
1306
1330
/*
1307
1331
* Chunk walker
1308
1332
*/
0 commit comments