mirror of
https://github.com/postgres/postgres.git
synced 2025-10-22 14:32:25 +03:00
Adjust SP-GiST WAL record formats to reduce alignment padding.
The way the code was written, the padding was copied from uninitialized memory areas.. Because the structs are local variables in the code where the WAL records are constructed, making them larger and zeroing the padding bytes would not make the code very pretty, so rather than fixing this directly by zeroing out the padding bytes, it seems more clear to not try to align the tuples in the WAL records. The redo functions are taught to copy the tuple header to a local variable to avoid unaligned access. Stable-branches have the same problem, but we can't change the WAL format there, so fix in master only. Reading a few random extra bytes at the stack is harmless in practice, so it's not worth crafting a different back-patchable fix. Per reports from Kevin Grittner and Andres Freund, using clang static analyzer and Valgrind, respectively.
This commit is contained in:
@@ -422,10 +422,7 @@ typedef struct spgxlogAddLeaf
|
||||
OffsetNumber offnumParent;
|
||||
uint16 nodeI;
|
||||
|
||||
/*
|
||||
* new leaf tuple follows, on an intalign boundary (replay only needs to
|
||||
* fetch its size field, so that should be enough alignment)
|
||||
*/
|
||||
/* new leaf tuple follows (unaligned!) */
|
||||
} spgxlogAddLeaf;
|
||||
|
||||
typedef struct spgxlogMoveLeafs
|
||||
@@ -449,9 +446,7 @@ typedef struct spgxlogMoveLeafs
|
||||
* data follows:
|
||||
* array of deleted tuple numbers, length nMoves
|
||||
* array of inserted tuple numbers, length nMoves + 1 or 1
|
||||
* list of leaf tuples, length nMoves + 1 or 1 (must be maxaligned)
|
||||
* the tuple number arrays are padded to maxalign boundaries so that the
|
||||
* leaf tuples will be suitably aligned
|
||||
* list of leaf tuples, length nMoves + 1 or 1 (unaligned!)
|
||||
*
|
||||
* Note: if replaceDead is true then there is only one inserted tuple
|
||||
* number and only one leaf tuple in the data, because we are not copying
|
||||
@@ -463,8 +458,11 @@ typedef struct spgxlogMoveLeafs
|
||||
* Parent page
|
||||
*----------
|
||||
*/
|
||||
OffsetNumber offsets[1];
|
||||
} spgxlogMoveLeafs;
|
||||
|
||||
#define SizeOfSpgxlogMoveLeafs offsetof(spgxlogMoveLeafs, offsets)
|
||||
|
||||
typedef struct spgxlogAddNode
|
||||
{
|
||||
RelFileNode node;
|
||||
@@ -483,8 +481,7 @@ typedef struct spgxlogAddNode
|
||||
spgxlogState stateSrc;
|
||||
|
||||
/*
|
||||
* updated inner tuple follows, on an intalign boundary (replay only needs
|
||||
* to fetch its size field, so that should be enough alignment)
|
||||
* updated inner tuple follows (unaligned!)
|
||||
*/
|
||||
} spgxlogAddNode;
|
||||
|
||||
@@ -500,9 +497,8 @@ typedef struct spgxlogSplitTuple
|
||||
bool newPage; /* need to init that page? */
|
||||
|
||||
/*
|
||||
* new prefix inner tuple follows, then new postfix inner tuple, on
|
||||
* intalign boundaries (replay only needs to fetch size fields, so that
|
||||
* should be enough alignment)
|
||||
* new prefix inner tuple follows, then new postfix inner tuple
|
||||
* (both are unaligned!)
|
||||
*/
|
||||
} spgxlogSplitTuple;
|
||||
|
||||
@@ -531,13 +527,11 @@ typedef struct spgxlogPickSplit
|
||||
|
||||
/*----------
|
||||
* data follows:
|
||||
* new inner tuple (assumed to have a maxaligned length)
|
||||
* array of deleted tuple numbers, length nDelete
|
||||
* array of inserted tuple numbers, length nInsert
|
||||
* array of page selector bytes for inserted tuples, length nInsert
|
||||
* list of leaf tuples, length nInsert (must be maxaligned)
|
||||
* the tuple number and page selector arrays are padded to maxalign
|
||||
* boundaries so that the leaf tuples will be suitably aligned
|
||||
* new inner tuple (unaligned!)
|
||||
* list of leaf tuples, length nInsert (unaligned!)
|
||||
*
|
||||
* Buffer references in the rdata array are:
|
||||
* Src page (only if not root and not being init'd)
|
||||
@@ -546,8 +540,11 @@ typedef struct spgxlogPickSplit
|
||||
* Parent page (if any; could be same as Inner)
|
||||
*----------
|
||||
*/
|
||||
OffsetNumber offsets[1];
|
||||
} spgxlogPickSplit;
|
||||
|
||||
#define SizeOfSpgxlogPickSplit offsetof(spgxlogPickSplit, offsets)
|
||||
|
||||
typedef struct spgxlogVacuumLeaf
|
||||
{
|
||||
RelFileNode node;
|
||||
@@ -570,8 +567,11 @@ typedef struct spgxlogVacuumLeaf
|
||||
* tuple numbers to insert in nextOffset links
|
||||
*----------
|
||||
*/
|
||||
OffsetNumber offsets[1];
|
||||
} spgxlogVacuumLeaf;
|
||||
|
||||
#define SizeOfSpgxlogVacuumLeaf offsetof(spgxlogVacuumLeaf, offsets)
|
||||
|
||||
typedef struct spgxlogVacuumRoot
|
||||
{
|
||||
/* vacuum a root page when it is also a leaf */
|
||||
@@ -583,8 +583,11 @@ typedef struct spgxlogVacuumRoot
|
||||
spgxlogState stateSrc;
|
||||
|
||||
/* offsets of tuples to delete follow */
|
||||
OffsetNumber offsets[1];
|
||||
} spgxlogVacuumRoot;
|
||||
|
||||
#define SizeOfSpgxlogVacuumRoot offsetof(spgxlogVacuumRoot, offsets)
|
||||
|
||||
typedef struct spgxlogVacuumRedirect
|
||||
{
|
||||
RelFileNode node;
|
||||
@@ -595,8 +598,11 @@ typedef struct spgxlogVacuumRedirect
|
||||
TransactionId newestRedirectXid; /* newest XID of removed redirects */
|
||||
|
||||
/* offsets of redirect tuples to make placeholders follow */
|
||||
OffsetNumber offsets[1];
|
||||
} spgxlogVacuumRedirect;
|
||||
|
||||
#define SizeOfSpgxlogVacuumRedirect offsetof(spgxlogVacuumRedirect, offsets)
|
||||
|
||||
/*
|
||||
* The "flags" argument for SpGistGetBuffer should be either GBUF_LEAF to
|
||||
* get a leaf page, or GBUF_INNER_PARITY(blockNumber) to get an inner
|
||||
|
Reference in New Issue
Block a user