Skip to content

Commit a5f0bd7

Browse files
committed
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
1 parent db4b54f commit a5f0bd7

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

src/backend/utils/sort/tuplesort.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,10 @@ tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
20452045
* determination of "non-equal tuple" based on simple binary inequality. A
20462046
* NULL value in leading attribute will set abbreviated value to zeroed
20472047
* representation, which caller may rely on in abbreviated inequality check.
2048+
*
2049+
* The slot receives a copied tuple (sometimes allocated in caller memory
2050+
* context) that will stay valid regardless of future manipulations of the
2051+
* tuplesort's state.
20482052
*/
20492053
bool
20502054
tuplesort_gettupleslot(Tuplesortstate *state, bool forward,
@@ -2065,6 +2069,11 @@ tuplesort_gettupleslot(Tuplesortstate *state, bool forward,
20652069
if (state->sortKeys->abbrev_converter && abbrev)
20662070
*abbrev = stup.datum1;
20672071

2072+
if (!should_free)
2073+
{
2074+
stup.tuple = heap_copy_minimal_tuple((MinimalTuple) stup.tuple);
2075+
should_free = true;
2076+
}
20682077
ExecStoreMinimalTuple((MinimalTuple) stup.tuple, slot, should_free);
20692078
return true;
20702079
}

0 commit comments

Comments
 (0)