Commit 6c42b2b1 authored by Tom Lane's avatar Tom Lane

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.
parent a3655dd4
...@@ -622,12 +622,11 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) ...@@ -622,12 +622,11 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
{ {
XLogRecord *r = &buf->record; XLogRecord *r = &buf->record;
xl_heap_update *xlrec; xl_heap_update *xlrec;
xl_heap_header_len *xlhdr; xl_heap_header_len xlhdr;
ReorderBufferChange *change; ReorderBufferChange *change;
char *data; char *data;
xlrec = (xl_heap_update *) buf->record_data; xlrec = (xl_heap_update *) buf->record_data;
xlhdr = (xl_heap_header_len *) (buf->record_data + SizeOfHeapUpdate);
/* only interested in our database */ /* only interested in our database */
if (xlrec->target.node.dbNode != ctx->slot->data.database) if (xlrec->target.node.dbNode != ctx->slot->data.database)
...@@ -637,33 +636,41 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) ...@@ -637,33 +636,41 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
change->action = REORDER_BUFFER_CHANGE_UPDATE; change->action = REORDER_BUFFER_CHANGE_UPDATE;
memcpy(&change->data.tp.relnode, &xlrec->target.node, sizeof(RelFileNode)); memcpy(&change->data.tp.relnode, &xlrec->target.node, sizeof(RelFileNode));
data = (char *) &xlhdr->header; /* caution, remaining data in record is not aligned */
data = buf->record_data + SizeOfHeapUpdate;
if (xlrec->flags & XLOG_HEAP_CONTAINS_NEW_TUPLE) if (xlrec->flags & XLOG_HEAP_CONTAINS_NEW_TUPLE)
{ {
Assert(r->xl_len > (SizeOfHeapUpdate + SizeOfHeapHeaderLen)); Assert(r->xl_len > (SizeOfHeapUpdate + SizeOfHeapHeaderLen));
memcpy(&xlhdr, data, sizeof(xlhdr));
data += offsetof(xl_heap_header_len, header);
change->data.tp.newtuple = ReorderBufferGetTupleBuf(ctx->reorder); change->data.tp.newtuple = ReorderBufferGetTupleBuf(ctx->reorder);
DecodeXLogTuple(data, DecodeXLogTuple(data,
xlhdr->t_len + SizeOfHeapHeader, xlhdr.t_len + SizeOfHeapHeader,
change->data.tp.newtuple); change->data.tp.newtuple);
/* skip over the rest of the tuple header */ /* skip over the rest of the tuple header */
data += SizeOfHeapHeader; data += SizeOfHeapHeader;
/* skip over the tuple data */ /* skip over the tuple data */
data += xlhdr->t_len; data += xlhdr.t_len;
} }
if (xlrec->flags & XLOG_HEAP_CONTAINS_OLD) if (xlrec->flags & XLOG_HEAP_CONTAINS_OLD)
{ {
xlhdr = (xl_heap_header_len *) data; memcpy(&xlhdr, data, sizeof(xlhdr));
data += offsetof(xl_heap_header_len, header);
change->data.tp.oldtuple = ReorderBufferGetTupleBuf(ctx->reorder); change->data.tp.oldtuple = ReorderBufferGetTupleBuf(ctx->reorder);
DecodeXLogTuple((char *) &xlhdr->header,
xlhdr->t_len + SizeOfHeapHeader, DecodeXLogTuple(data,
xlhdr.t_len + SizeOfHeapHeader,
change->data.tp.oldtuple); change->data.tp.oldtuple);
data = (char *) &xlhdr->header; #ifdef NOT_USED
data += SizeOfHeapHeader; data += SizeOfHeapHeader;
data += xlhdr->t_len; data += xlhdr.t_len;
#endif
} }
ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change); ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment