diff options
-rw-r--r-- | src/backend/access/gin/ginfast.c | 31 |
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); } |