Fix handling of sortKeys field in Tuplesortstate.

Commit 5cefbf5a6c4466ac6b1cc2a4316b4eba9108c802 introduced an
assumption that this field would always be non-NULL when doing a merge
pass, but that's not true.  Without this fix, you can crash the server
by building a hash index that is sufficiently large relative to
maintenance_work_mem, or by triggering a large datum sort.

Commit 5ea86e6e65dd2da3e9a3464484985d48328e7fe3 changed the comments
for that field to say that it would be set in all cases except for the
hash index case, but that wasn't (and still isn't) true.

The datum-sort failure was spotted by Tomas Vondra; initial analysis
of that failure was by Peter Geoghegan.  The remaining issues were
spotted by me during review of the surrounding code, and the patch is
all my fault.
This commit is contained in:
Robert Haas 2015-03-09 10:35:41 -04:00
parent f1fd515b39
commit 2720e96a9b

View File

@ -336,9 +336,9 @@ struct Tuplesortstate
bool markpos_eof; /* saved "eof_reached" */ bool markpos_eof; /* saved "eof_reached" */
/* /*
* The sortKeys variable is used by every case other than the hash index * The sortKeys variable is used by every case other than the datum and
* case; it is set by tuplesort_begin_xxx. tupDesc is only used by the * hash index cases; it is set by tuplesort_begin_xxx. tupDesc is only
* MinimalTuple and CLUSTER routines, though. * used by the MinimalTuple and CLUSTER routines, though.
*/ */
TupleDesc tupDesc; TupleDesc tupDesc;
SortSupport sortKeys; /* array of length nKeys */ SortSupport sortKeys; /* array of length nKeys */
@ -1246,7 +1246,7 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
RelationGetDescr(state->indexRel), RelationGetDescr(state->indexRel),
&stup.isnull1); &stup.isnull1);
if (!state->sortKeys->abbrev_converter || stup.isnull1) if (!state->sortKeys || !state->sortKeys->abbrev_converter || stup.isnull1)
{ {
/* /*
* Store ordinary Datum representation, or NULL value. If there is a * Store ordinary Datum representation, or NULL value. If there is a
@ -2172,7 +2172,7 @@ mergeruns(Tuplesortstate *state)
return; return;
} }
if (state->sortKeys->abbrev_converter) if (state->sortKeys != NULL && state->sortKeys->abbrev_converter != NULL)
{ {
/* /*
* If there are multiple runs to be merged, when we go to read back * If there are multiple runs to be merged, when we go to read back