Fix use-after-free around DISTINCT transition function calls.
authorHeikki Linnakangas <[email protected]>
Mon, 17 Oct 2016 09:13:16 +0000 (12:13 +0300)
committerHeikki Linnakangas <[email protected]>
Mon, 17 Oct 2016 09:13:16 +0000 (12:13 +0300)
Have tuplesort_gettupleslot() copy the contents of its current table slot
as needed. This is based on an approach taken by tuplestore_gettupleslot().
In the future, tuplesort_gettupleslot() may also be taught to avoid copying
the tuple where caller can determine that that is safe (the
tuplestore_gettupleslot() interface already offers this option to callers).

Patch by Peter Geoghegan. Fixes bug #14344, reported by Regina Obe.

Report: <20160929035538[email protected]>

Backpatch-through: 9.6

src/backend/utils/sort/tuplesort.c

index f6eb30c2ce203af7ded381b489014e8c4280756a..46512cfca1a4aca2bda4160f6322c8c92d4c8708 100644 (file)
@@ -2084,6 +2084,10 @@ tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
  * determination of "non-equal tuple" based on simple binary inequality.  A
  * NULL value in leading attribute will set abbreviated value to zeroed
  * representation, which caller may rely on in abbreviated inequality check.
+ *
+ * The slot receives a copied tuple (sometimes allocated in caller memory
+ * context) that will stay valid regardless of future manipulations of the
+ * tuplesort's state.
  */
 bool
 tuplesort_gettupleslot(Tuplesortstate *state, bool forward,
@@ -2104,6 +2108,11 @@ tuplesort_gettupleslot(Tuplesortstate *state, bool forward,
        if (state->sortKeys->abbrev_converter && abbrev)
            *abbrev = stup.datum1;
 
+       if (!should_free)
+       {
+           stup.tuple = heap_copy_minimal_tuple((MinimalTuple) stup.tuple);
+           should_free = true;
+       }
        ExecStoreMinimalTuple((MinimalTuple) stup.tuple, slot, should_free);
        return true;
    }