mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Handle unaligned SerializeSnapshot() buffer.
Likewise in RestoreSnapshot(). Do so by copying between the user buffer and a stack buffer of known alignment. Back-patch to 9.6, where this last applies cleanly. In master, the select_parallel test dies with SIGBUS on "Oracle Solaris 10 1/13 s10s_u11wos_24a SPARC", building 32-bit with gcc 4.9.2. In 9.6 and 9.5, the buffers in question happen to be sufficiently-aligned, and this change is mere insurance against future 9.6 changes or extension code compromising that.
This commit is contained in:
@ -2015,34 +2015,37 @@ EstimateSnapshotSpace(Snapshot snap)
|
|||||||
void
|
void
|
||||||
SerializeSnapshot(Snapshot snapshot, char *start_address)
|
SerializeSnapshot(Snapshot snapshot, char *start_address)
|
||||||
{
|
{
|
||||||
SerializedSnapshotData *serialized_snapshot;
|
SerializedSnapshotData serialized_snapshot;
|
||||||
|
|
||||||
Assert(snapshot->subxcnt >= 0);
|
Assert(snapshot->subxcnt >= 0);
|
||||||
|
|
||||||
serialized_snapshot = (SerializedSnapshotData *) start_address;
|
|
||||||
|
|
||||||
/* Copy all required fields */
|
/* Copy all required fields */
|
||||||
serialized_snapshot->xmin = snapshot->xmin;
|
serialized_snapshot.xmin = snapshot->xmin;
|
||||||
serialized_snapshot->xmax = snapshot->xmax;
|
serialized_snapshot.xmax = snapshot->xmax;
|
||||||
serialized_snapshot->xcnt = snapshot->xcnt;
|
serialized_snapshot.xcnt = snapshot->xcnt;
|
||||||
serialized_snapshot->subxcnt = snapshot->subxcnt;
|
serialized_snapshot.subxcnt = snapshot->subxcnt;
|
||||||
serialized_snapshot->suboverflowed = snapshot->suboverflowed;
|
serialized_snapshot.suboverflowed = snapshot->suboverflowed;
|
||||||
serialized_snapshot->takenDuringRecovery = snapshot->takenDuringRecovery;
|
serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
|
||||||
serialized_snapshot->curcid = snapshot->curcid;
|
serialized_snapshot.curcid = snapshot->curcid;
|
||||||
serialized_snapshot->whenTaken = snapshot->whenTaken;
|
serialized_snapshot.whenTaken = snapshot->whenTaken;
|
||||||
serialized_snapshot->lsn = snapshot->lsn;
|
serialized_snapshot.lsn = snapshot->lsn;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore the SubXID array if it has overflowed, unless the snapshot was
|
* Ignore the SubXID array if it has overflowed, unless the snapshot was
|
||||||
* taken during recovey - in that case, top-level XIDs are in subxip as
|
* taken during recovey - in that case, top-level XIDs are in subxip as
|
||||||
* well, and we mustn't lose them.
|
* well, and we mustn't lose them.
|
||||||
*/
|
*/
|
||||||
if (serialized_snapshot->suboverflowed && !snapshot->takenDuringRecovery)
|
if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
|
||||||
serialized_snapshot->subxcnt = 0;
|
serialized_snapshot.subxcnt = 0;
|
||||||
|
|
||||||
|
/* Copy struct to possibly-unaligned buffer */
|
||||||
|
memcpy(start_address,
|
||||||
|
&serialized_snapshot, sizeof(SerializedSnapshotData));
|
||||||
|
|
||||||
/* Copy XID array */
|
/* Copy XID array */
|
||||||
if (snapshot->xcnt > 0)
|
if (snapshot->xcnt > 0)
|
||||||
memcpy((TransactionId *) (serialized_snapshot + 1),
|
memcpy((TransactionId *) (start_address +
|
||||||
|
sizeof(SerializedSnapshotData)),
|
||||||
snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
|
snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2051,12 +2054,12 @@ SerializeSnapshot(Snapshot snapshot, char *start_address)
|
|||||||
* snapshot taken during recovery; all the top-level XIDs are in subxip as
|
* snapshot taken during recovery; all the top-level XIDs are in subxip as
|
||||||
* well in that case, so we mustn't lose them.
|
* well in that case, so we mustn't lose them.
|
||||||
*/
|
*/
|
||||||
if (serialized_snapshot->subxcnt > 0)
|
if (serialized_snapshot.subxcnt > 0)
|
||||||
{
|
{
|
||||||
Size subxipoff = sizeof(SerializedSnapshotData) +
|
Size subxipoff = sizeof(SerializedSnapshotData) +
|
||||||
snapshot->xcnt * sizeof(TransactionId);
|
snapshot->xcnt * sizeof(TransactionId);
|
||||||
|
|
||||||
memcpy((TransactionId *) ((char *) serialized_snapshot + subxipoff),
|
memcpy((TransactionId *) (start_address + subxipoff),
|
||||||
snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
|
snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2071,50 +2074,51 @@ SerializeSnapshot(Snapshot snapshot, char *start_address)
|
|||||||
Snapshot
|
Snapshot
|
||||||
RestoreSnapshot(char *start_address)
|
RestoreSnapshot(char *start_address)
|
||||||
{
|
{
|
||||||
SerializedSnapshotData *serialized_snapshot;
|
SerializedSnapshotData serialized_snapshot;
|
||||||
Size size;
|
Size size;
|
||||||
Snapshot snapshot;
|
Snapshot snapshot;
|
||||||
TransactionId *serialized_xids;
|
TransactionId *serialized_xids;
|
||||||
|
|
||||||
serialized_snapshot = (SerializedSnapshotData *) start_address;
|
memcpy(&serialized_snapshot, start_address,
|
||||||
|
sizeof(SerializedSnapshotData));
|
||||||
serialized_xids = (TransactionId *)
|
serialized_xids = (TransactionId *)
|
||||||
(start_address + sizeof(SerializedSnapshotData));
|
(start_address + sizeof(SerializedSnapshotData));
|
||||||
|
|
||||||
/* We allocate any XID arrays needed in the same palloc block. */
|
/* We allocate any XID arrays needed in the same palloc block. */
|
||||||
size = sizeof(SnapshotData)
|
size = sizeof(SnapshotData)
|
||||||
+ serialized_snapshot->xcnt * sizeof(TransactionId)
|
+ serialized_snapshot.xcnt * sizeof(TransactionId)
|
||||||
+ serialized_snapshot->subxcnt * sizeof(TransactionId);
|
+ serialized_snapshot.subxcnt * sizeof(TransactionId);
|
||||||
|
|
||||||
/* Copy all required fields */
|
/* Copy all required fields */
|
||||||
snapshot = (Snapshot) MemoryContextAlloc(TopTransactionContext, size);
|
snapshot = (Snapshot) MemoryContextAlloc(TopTransactionContext, size);
|
||||||
snapshot->satisfies = HeapTupleSatisfiesMVCC;
|
snapshot->satisfies = HeapTupleSatisfiesMVCC;
|
||||||
snapshot->xmin = serialized_snapshot->xmin;
|
snapshot->xmin = serialized_snapshot.xmin;
|
||||||
snapshot->xmax = serialized_snapshot->xmax;
|
snapshot->xmax = serialized_snapshot.xmax;
|
||||||
snapshot->xip = NULL;
|
snapshot->xip = NULL;
|
||||||
snapshot->xcnt = serialized_snapshot->xcnt;
|
snapshot->xcnt = serialized_snapshot.xcnt;
|
||||||
snapshot->subxip = NULL;
|
snapshot->subxip = NULL;
|
||||||
snapshot->subxcnt = serialized_snapshot->subxcnt;
|
snapshot->subxcnt = serialized_snapshot.subxcnt;
|
||||||
snapshot->suboverflowed = serialized_snapshot->suboverflowed;
|
snapshot->suboverflowed = serialized_snapshot.suboverflowed;
|
||||||
snapshot->takenDuringRecovery = serialized_snapshot->takenDuringRecovery;
|
snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
|
||||||
snapshot->curcid = serialized_snapshot->curcid;
|
snapshot->curcid = serialized_snapshot.curcid;
|
||||||
snapshot->whenTaken = serialized_snapshot->whenTaken;
|
snapshot->whenTaken = serialized_snapshot.whenTaken;
|
||||||
snapshot->lsn = serialized_snapshot->lsn;
|
snapshot->lsn = serialized_snapshot.lsn;
|
||||||
|
|
||||||
/* Copy XIDs, if present. */
|
/* Copy XIDs, if present. */
|
||||||
if (serialized_snapshot->xcnt > 0)
|
if (serialized_snapshot.xcnt > 0)
|
||||||
{
|
{
|
||||||
snapshot->xip = (TransactionId *) (snapshot + 1);
|
snapshot->xip = (TransactionId *) (snapshot + 1);
|
||||||
memcpy(snapshot->xip, serialized_xids,
|
memcpy(snapshot->xip, serialized_xids,
|
||||||
serialized_snapshot->xcnt * sizeof(TransactionId));
|
serialized_snapshot.xcnt * sizeof(TransactionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy SubXIDs, if present. */
|
/* Copy SubXIDs, if present. */
|
||||||
if (serialized_snapshot->subxcnt > 0)
|
if (serialized_snapshot.subxcnt > 0)
|
||||||
{
|
{
|
||||||
snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
|
snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
|
||||||
serialized_snapshot->xcnt;
|
serialized_snapshot.xcnt;
|
||||||
memcpy(snapshot->subxip, serialized_xids + serialized_snapshot->xcnt,
|
memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
|
||||||
serialized_snapshot->subxcnt * sizeof(TransactionId));
|
serialized_snapshot.subxcnt * sizeof(TransactionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the copied flag so that the caller will set refcounts correctly. */
|
/* Set the copied flag so that the caller will set refcounts correctly. */
|
||||||
|
Reference in New Issue
Block a user