Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6c42b2b

Browse files
committed
Fix unaligned accesses in DecodeUpdate().
The xl_heap_header_len structures in an XLOG_HEAP_UPDATE record aren't necessarily aligned adequately. The regular replay function for these records is aware of that, but decode.c didn't get the memo. I'm not sure why the buildfarm failed to catch this; the test_decoding test certainly blows up real good on my old HPPA box. Also, I'm pretty sure that the address arithmetic was wrong for the case of XLOG_HEAP_CONTAINS_OLD and not XLOG_HEAP_CONTAINS_NEW_TUPLE, though this apparently can't happen when logical decoding is active.
1 parent a3655dd commit 6c42b2b

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

src/backend/replication/logical/decode.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -622,12 +622,11 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
622622
{
623623
XLogRecord *r = &buf->record;
624624
xl_heap_update *xlrec;
625-
xl_heap_header_len *xlhdr;
625+
xl_heap_header_len xlhdr;
626626
ReorderBufferChange *change;
627627
char *data;
628628

629629
xlrec = (xl_heap_update *) buf->record_data;
630-
xlhdr = (xl_heap_header_len *) (buf->record_data + SizeOfHeapUpdate);
631630

632631
/* only interested in our database */
633632
if (xlrec->target.node.dbNode != ctx->slot->data.database)
@@ -637,33 +636,41 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
637636
change->action = REORDER_BUFFER_CHANGE_UPDATE;
638637
memcpy(&change->data.tp.relnode, &xlrec->target.node, sizeof(RelFileNode));
639638

640-
data = (char *) &xlhdr->header;
639+
/* caution, remaining data in record is not aligned */
640+
data = buf->record_data + SizeOfHeapUpdate;
641641

642642
if (xlrec->flags & XLOG_HEAP_CONTAINS_NEW_TUPLE)
643643
{
644644
Assert(r->xl_len > (SizeOfHeapUpdate + SizeOfHeapHeaderLen));
645645

646+
memcpy(&xlhdr, data, sizeof(xlhdr));
647+
data += offsetof(xl_heap_header_len, header);
648+
646649
change->data.tp.newtuple = ReorderBufferGetTupleBuf(ctx->reorder);
647650

648651
DecodeXLogTuple(data,
649-
xlhdr->t_len + SizeOfHeapHeader,
652+
xlhdr.t_len + SizeOfHeapHeader,
650653
change->data.tp.newtuple);
651654
/* skip over the rest of the tuple header */
652655
data += SizeOfHeapHeader;
653656
/* skip over the tuple data */
654-
data += xlhdr->t_len;
657+
data += xlhdr.t_len;
655658
}
656659

657660
if (xlrec->flags & XLOG_HEAP_CONTAINS_OLD)
658661
{
659-
xlhdr = (xl_heap_header_len *) data;
662+
memcpy(&xlhdr, data, sizeof(xlhdr));
663+
data += offsetof(xl_heap_header_len, header);
664+
660665
change->data.tp.oldtuple = ReorderBufferGetTupleBuf(ctx->reorder);
661-
DecodeXLogTuple((char *) &xlhdr->header,
662-
xlhdr->t_len + SizeOfHeapHeader,
666+
667+
DecodeXLogTuple(data,
668+
xlhdr.t_len + SizeOfHeapHeader,
663669
change->data.tp.oldtuple);
664-
data = (char *) &xlhdr->header;
670+
#ifdef NOT_USED
665671
data += SizeOfHeapHeader;
666-
data += xlhdr->t_len;
672+
data += xlhdr.t_len;
673+
#endif
667674
}
668675

669676
ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change);

0 commit comments

Comments
 (0)