diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-06-15 14:05:22 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-06-15 14:06:01 -0400 |
commit | 8520174b4e788736a41797320d9d36a4372b56df (patch) | |
tree | 2eb0b436fd3a7afa6a09d4f9e2744d15fe607b38 | |
parent | 212567ad3ee23c7ff630e41034c48814b3f18cc9 (diff) | |
download | postgresql-8520174b4e788736a41797320d9d36a4372b56df.tar.gz postgresql-8520174b4e788736a41797320d9d36a4372b56df.zip |
Fix failure to account for memory used by tuplestore_putvalues().
This oversight could result in a tuplestore using much more than the
intended amount of memory. It would only happen in a code path that loaded
a tuplestore via tuplestore_putvalues(), and many of those won't emit huge
amounts of data; but cases such as holdable cursors and plpgsql's RETURN
NEXT command could have the problem. The fix ensures that the tuplestore
will switch to write-to-disk mode when it overruns work_mem.
The potential overrun was finite, because we would still count the space
used by the tuple pointer array, so the tuplestore code would eventually
flip into write-to-disk mode anyway. When storing wide tuples we would
go far past the expected work_mem usage before that happened; but this
may account for the lack of prior reports.
Back-patch to 8.4, where tuplestore_putvalues was introduced.
Per bug #6061 from Yann Delorme.
-rw-r--r-- | src/backend/utils/sort/tuplestore.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index 4cfc38ef8b5..5d34a670be3 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -570,7 +570,8 @@ tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple) MemoryContext oldcxt = MemoryContextSwitchTo(state->context); /* - * Copy the tuple. (Must do this even in WRITEFILE case.) + * Copy the tuple. (Must do this even in WRITEFILE case. Note that + * COPYTUP includes USEMEM, so we needn't do that here.) */ tuple = COPYTUP(state, tuple); @@ -580,9 +581,8 @@ tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple) } /* - * Similar to tuplestore_puttuple(), but start from the values + nulls - * array. This avoids requiring that the caller construct a HeapTuple, - * saving a copy. + * Similar to tuplestore_puttuple(), but work from values + nulls arrays. + * This avoids an extra tuple-construction operation. */ void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, @@ -592,6 +592,7 @@ tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, MemoryContext oldcxt = MemoryContextSwitchTo(state->context); tuple = heap_form_minimal_tuple(tdesc, values, isnull); + USEMEM(state, GetMemoryChunkSpace(tuple)); tuplestore_puttuple_common(state, (void *) tuple); |