aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2016-10-17 12:13:16 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2016-10-17 12:13:35 +0300
commita5f0bd77a2fab60a52dc335a63efc21abc806aa7 (patch)
tree637bcc342da1bf8b564f38fd8023ce9869a02ebe /src
parentdb4b54f1550aa830890ce190e5d196de8d17db33 (diff)
downloadpostgresql-a5f0bd77a2fab60a52dc335a63efc21abc806aa7.tar.gz
postgresql-a5f0bd77a2fab60a52dc335a63efc21abc806aa7.zip
Fix use-after-free around DISTINCT transition function calls.
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.20224.39628@wrigleys.postgresql.org> Backpatch-through: 9.6
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/sort/tuplesort.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 92d41cdce2d..64ef6e5032c 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -2045,6 +2045,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,
@@ -2065,6 +2069,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;
}