aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-05-17 15:53:21 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2014-05-17 15:53:21 -0400
commit6c42b2b10af3f717030966b9f05867f3e065becc (patch)
treecebcf67afee0f6844f98de08d16cf547f1549c7d /src
parenta3655dd4a5cee3917a7d1766e07e36013e7e8835 (diff)
downloadpostgresql-6c42b2b10af3f717030966b9f05867f3e065becc.tar.gz
postgresql-6c42b2b10af3f717030966b9f05867f3e065becc.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/replication/logical/decode.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index cc736521c2a..00b5b838d7c 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -622,12 +622,11 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
{
XLogRecord *r = &buf->record;
xl_heap_update *xlrec;
- xl_heap_header_len *xlhdr;
+ xl_heap_header_len xlhdr;
ReorderBufferChange *change;
char *data;
xlrec = (xl_heap_update *) buf->record_data;
- xlhdr = (xl_heap_header_len *) (buf->record_data + SizeOfHeapUpdate);
/* only interested in our database */
if (xlrec->target.node.dbNode != ctx->slot->data.database)
@@ -637,33 +636,41 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
change->action = REORDER_BUFFER_CHANGE_UPDATE;
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)
{
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);
DecodeXLogTuple(data,
- xlhdr->t_len + SizeOfHeapHeader,
+ xlhdr.t_len + SizeOfHeapHeader,
change->data.tp.newtuple);
/* skip over the rest of the tuple header */
data += SizeOfHeapHeader;
/* skip over the tuple data */
- data += xlhdr->t_len;
+ data += xlhdr.t_len;
}
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);
- DecodeXLogTuple((char *) &xlhdr->header,
- xlhdr->t_len + SizeOfHeapHeader,
+
+ DecodeXLogTuple(data,
+ xlhdr.t_len + SizeOfHeapHeader,
change->data.tp.oldtuple);
- data = (char *) &xlhdr->header;
+#ifdef NOT_USED
data += SizeOfHeapHeader;
- data += xlhdr->t_len;
+ data += xlhdr.t_len;
+#endif
}
ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change);