Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 258b041

Browse files
committed
Fix some possibly latent bugs in slab.c
Primarily, this fixes an incorrect calculation in SlabCheck which was looking in the wrong byte for the sentinel check. The reason that we've never noticed this before in the form of a failing sentinel check is because the pre-check to this always fails because all current core users of slab contexts have a chunk size which is already MAXALIGNed, therefore there's never any space for the sentinel byte. It is possible that an extension needs to use a slab context and if they do with a chunk size that's not MAXALIGNed, then they'll likely get errors about overwritten sentinel bytes. Additionally, this patch changes various calculations which are being done based on the sizeof(SlabBlock). Currently, sizeof(SlabBlock) is a multiple of 8, therefore sizeof(SlabBlock) is the same as MAXALIGN(sizeof(SlabBlock)), however, if we were to ever have to add any fields to that struct as part of a bug fix, then SlabAlloc could end up returning a non-MAXALIGNed pointer. To be safe, let's ensure we always MAXALIGN sizeof(SlabBlock) before using it in any calculations. This patch has already been applied to master in d5ee4db. Diagnosed-by: Tomas Vondra, Tom Lane Author: Tomas Vondra, David Rowley Discussion: https://postgr.es/m/CAA4eK1%2B1JyW5TiL%3DyV-3Uq1CrfnTyn0Xrk5uArt31Z%3D8rgPhXQ%40mail.gmail.com Backpatch-through: 10
1 parent f988e94 commit 258b041

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

src/backend/utils/mmgr/slab.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#include "lib/ilist.h"
5858

5959

60+
#define Slab_BLOCKHDRSZ MAXALIGN(sizeof(SlabBlock))
61+
6062
/*
6163
* SlabContext is a specialized implementation of MemoryContext.
6264
*/
@@ -110,10 +112,10 @@ typedef struct SlabChunk
110112
#define SlabChunkGetPointer(chk) \
111113
((void *)(((char *)(chk)) + sizeof(SlabChunk)))
112114
#define SlabBlockGetChunk(slab, block, idx) \
113-
((SlabChunk *) ((char *) (block) + sizeof(SlabBlock) \
115+
((SlabChunk *) ((char *) (block) + Slab_BLOCKHDRSZ \
114116
+ (idx * slab->fullChunkSize)))
115117
#define SlabBlockStart(block) \
116-
((char *) block + sizeof(SlabBlock))
118+
((char *) block + Slab_BLOCKHDRSZ)
117119
#define SlabChunkIndex(slab, block, chunk) \
118120
(((char *) chunk - SlabBlockStart(block)) / slab->fullChunkSize)
119121

@@ -179,7 +181,7 @@ static MemoryContextMethods SlabMethods = {
179181
* chunkSize: allocation chunk size
180182
*
181183
* The chunkSize may not exceed:
182-
* MAXALIGN_DOWN(SIZE_MAX) - MAXALIGN(sizeof(SlabBlock)) - SLAB_CHUNKHDRSZ
184+
* MAXALIGN_DOWN(SIZE_MAX) - MAXALIGN(Slab_BLOCKHDRSZ) - sizeof(SlabChunk)
183185
*
184186
*/
185187
MemoryContext
@@ -206,12 +208,12 @@ SlabContextCreate(MemoryContext parent,
206208
fullChunkSize = MAXALIGN(sizeof(SlabChunk) + MAXALIGN(chunkSize));
207209

208210
/* Make sure the block can store at least one chunk. */
209-
if (blockSize - sizeof(SlabBlock) < fullChunkSize)
211+
if (blockSize - Slab_BLOCKHDRSZ < fullChunkSize)
210212
elog(ERROR, "block size %zu for slab is too small for %zu chunks",
211213
blockSize, chunkSize);
212214

213215
/* Compute maximum number of chunks per block */
214-
chunksPerBlock = (blockSize - sizeof(SlabBlock)) / fullChunkSize;
216+
chunksPerBlock = (blockSize - Slab_BLOCKHDRSZ) / fullChunkSize;
215217

216218
/* The freelist starts with 0, ends with chunksPerBlock. */
217219
freelistSize = sizeof(dlist_head) * (chunksPerBlock + 1);
@@ -220,7 +222,7 @@ SlabContextCreate(MemoryContext parent,
220222
Assert(chunksPerBlock > 0);
221223

222224
/* make sure the chunks actually fit on the block */
223-
Assert((fullChunkSize * chunksPerBlock) + sizeof(SlabBlock) <= blockSize);
225+
Assert((fullChunkSize * chunksPerBlock) + Slab_BLOCKHDRSZ <= blockSize);
224226

225227
/* Size of the memory context header */
226228
headerSize = offsetof(SlabContext, freelist) + freelistSize;
@@ -765,7 +767,7 @@ SlabCheck(MemoryContext context)
765767

766768
/* there might be sentinel (thanks to alignment) */
767769
if (slab->chunkSize < (slab->fullChunkSize - sizeof(SlabChunk)))
768-
if (!sentinel_ok(chunk, slab->chunkSize))
770+
if (!sentinel_ok(chunk, sizeof(SlabChunk) + slab->chunkSize))
769771
elog(WARNING, "problem in slab %s: detected write past chunk end in block %p, chunk %p",
770772
name, block, chunk);
771773
}

0 commit comments

Comments
 (0)