Fix unaligned memory access in xlog parsing due to replication origin patch.
authorAndres Freund
Fri, 1 May 2015 09:36:14 +0000 (11:36 +0200)
committerAndres Freund
Fri, 1 May 2015 09:36:14 +0000 (11:36 +0200)
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
src/include/access/xact.h

index 3297e1d3790eee1077a6e711fa5876eb7f78cdb6..cac1df8e07a7a98eecb351c9bd5e62b71af30e78 100644 (file)
@@ -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);
    }
index ed808fc1505efadbae1d862261c9545d74f5d4ab..668e987f488c2f3e2d2e5bc0c82345d73ef120f5 100644 (file)
@@ -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))