From 1db12da85bee7a01abfbbf2798904347e4d9515a Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 1 May 2015 11:36:14 +0200 Subject: Fix unaligned memory access in xlog parsing due to replication origin patch. ParseCommitRecord() accessed xl_xact_origin directly. But the chunks in the commit record's data only have 4 byte alignment, whereas xl_xact_origin's members require 8 byte alignment on some platforms. Update comments to make not of that and copy the record to stack local storage before reading. With help from Stefan Kaltenbrunner in pinning down the buildfarm and verifying the fix. --- src/backend/access/rmgrdesc/xactdesc.c | 9 ++++++--- src/include/access/xact.h | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c index 3297e1d3790..cac1df8e07a 100644 --- a/src/backend/access/rmgrdesc/xactdesc.c +++ b/src/backend/access/rmgrdesc/xactdesc.c @@ -104,10 +104,13 @@ ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *pars if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN) { - xl_xact_origin *xl_origin = (xl_xact_origin *) data; + xl_xact_origin xl_origin; - parsed->origin_lsn = xl_origin->origin_lsn; - parsed->origin_timestamp = xl_origin->origin_timestamp; + /* we're only guaranteed 4 byte alignment, so copy onto stack */ + memcpy(&xl_origin, data, sizeof(xl_origin)); + + parsed->origin_lsn = xl_origin.origin_lsn; + parsed->origin_timestamp = xl_origin.origin_timestamp; data += sizeof(xl_xact_origin); } diff --git a/src/include/access/xact.h b/src/include/access/xact.h index ed808fc1505..668e987f488 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -173,7 +173,8 @@ typedef struct xl_xact_assignment * by a set XLOG_XACT_HAS_INFO bit in the xl_info field. * * NB: All the individual data chunks should be sized to multiples of - * sizeof(int) and only require int32 alignment. + * sizeof(int) and only require int32 alignment. If they require bigger + * alignment, they need to be copied upon reading. */ /* sub-records for commit/abort */ @@ -237,7 +238,7 @@ typedef struct xl_xact_commit /* xl_xact_relfilenodes follows if XINFO_HAS_RELFILENODES */ /* xl_xact_invals follows if XINFO_HAS_INVALS */ /* xl_xact_twophase follows if XINFO_HAS_TWOPHASE */ - /* xl_xact_origin follows if XINFO_HAS_ORIGIN */ + /* xl_xact_origin follows if XINFO_HAS_ORIGIN, stored unaligned! */ } xl_xact_commit; #define MinSizeOfXactCommit (offsetof(xl_xact_commit, xact_time) + sizeof(TimestampTz)) -- cgit v1.2.3