diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2016-10-17 12:13:16 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2016-10-17 12:13:16 +0300 |
commit | d8589946ddd5c43e1ebd01c5e92d0e177cbfc198 (patch) | |
tree | 8d55a3ea631630089a5fd29051303006ad3b19c3 | |
parent | 9e083fd4683294f41544e6d0d72f6e258ff3a77c (diff) | |
download | postgresql-d8589946ddd5c43e1ebd01c5e92d0e177cbfc198.tar.gz postgresql-d8589946ddd5c43e1ebd01c5e92d0e177cbfc198.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
-rw-r--r-- | src/backend/utils/sort/tuplesort.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index f6eb30c2ce2..46512cfca1a 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -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; } |