aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-12-19 11:41:36 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2018-12-19 11:41:36 -0500
commitc6e394c1a2ae641724d285ce0b043b753406dbbd (patch)
treeb959667903bb74ff52db853c5482a27b0d83e243 /src
parent639924249c8a5e1929a0c74ab4ae15d18683e7fa (diff)
downloadpostgresql-c6e394c1a2ae641724d285ce0b043b753406dbbd.tar.gz
postgresql-c6e394c1a2ae641724d285ce0b043b753406dbbd.zip
Small improvements for allocation logic in ginHeapTupleFastCollect().
Avoid repetitive calls to repalloc() when the required size of the collector array grows more than 2x in one call. Also ensure that the array size is a power of 2 (since palloc will probably consume a power of 2 anyway) and doesn't start out very small (which'd likely just lead to extra repallocs). David Rowley, tweaked a bit by me Discussion: https://postgr.es/m/CAKJS1f8vn-iSBE8PKeVHrnhvyjRNYCxguPFFY08QLYmjWG9hPQ@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gin/ginfast.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
index ca2a32bd257..a800659b923 100644
--- a/src/backend/access/gin/ginfast.c
+++ b/src/backend/access/gin/ginfast.c
@@ -487,17 +487,40 @@ ginHeapTupleFastCollect(GinState *ginstate,
&nentries, &categories);
/*
+ * Protect against integer overflow in allocation calculations
+ */
+ if (nentries < 0 ||
+ collector->ntuples + nentries > MaxAllocSize / sizeof(IndexTuple))
+ elog(ERROR, "too many entries for GIN index");
+
+ /*
* Allocate/reallocate memory for storing collected tuples
*/
if (collector->tuples == NULL)
{
- collector->lentuples = nentries * ginstate->origTupdesc->natts;
+ /*
+ * Determine the number of elements to allocate in the tuples array
+ * initially. Make it a power of 2 to avoid wasting memory when
+ * resizing (since palloc likes powers of 2).
+ */
+ collector->lentuples = 16;
+ while (collector->lentuples < nentries)
+ collector->lentuples *= 2;
+
collector->tuples = (IndexTuple *) palloc(sizeof(IndexTuple) * collector->lentuples);
}
-
- while (collector->ntuples + nentries > collector->lentuples)
+ else if (collector->lentuples < collector->ntuples + nentries)
{
- collector->lentuples *= 2;
+ /*
+ * Advance lentuples to the next suitable power of 2. This won't
+ * overflow, though we could get to a value that exceeds
+ * MaxAllocSize/sizeof(IndexTuple), causing an error in repalloc.
+ */
+ do
+ {
+ collector->lentuples *= 2;
+ } while (collector->lentuples < collector->ntuples + nentries);
+
collector->tuples = (IndexTuple *) repalloc(collector->tuples,
sizeof(IndexTuple) * collector->lentuples);
}