entries = ginExtractEntries(ginstate, attnum, value, isNull,
&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);
}