@@ -211,8 +211,8 @@ struct Tuplesortstate
211211 * tuples to return? */
212212 bool boundUsed ; /* true if we made use of a bounded heap */
213213 int bound ; /* if bounded, the maximum number of tuples */
214- long availMem ; /* remaining memory available, in bytes */
215- long allowedMem ; /* total memory allowed, in bytes */
214+ Size availMem ; /* remaining memory available, in bytes */
215+ Size allowedMem ; /* total memory allowed, in bytes */
216216 int maxTapes ; /* number of tapes (Knuth's T) */
217217 int tapeRange ; /* maxTapes-1 (Knuth's P) */
218218 MemoryContext sortcontext ; /* memory context holding all sort data */
@@ -308,7 +308,7 @@ struct Tuplesortstate
308308 int * mergenext ; /* first preread tuple for each source */
309309 int * mergelast ; /* last preread tuple for each source */
310310 int * mergeavailslots ; /* slots left for prereading each tape */
311- long * mergeavailmem ; /* availMem for prereading each tape */
311+ Size * mergeavailmem ; /* availMem for prereading each tape */
312312 int mergefreelist ; /* head of freelist of recycled slots */
313313 int mergefirstfree ; /* first slot never used in this merge */
314314
@@ -961,25 +961,26 @@ tuplesort_end(Tuplesortstate *state)
961961}
962962
963963/*
964- * Grow the memtuples[] array, if possible within our memory constraint.
965- * Return TRUE if we were able to enlarge the array, FALSE if not.
964+ * Grow the memtuples[] array, if possible within our memory constraint. We
965+ * must not exceed INT_MAX tuples in memory or the caller-provided memory
966+ * limit. Return TRUE if we were able to enlarge the array, FALSE if not.
966967 *
967- * Normally, at each increment we double the size of the array. When we no
968- * longer have enough memory to do that , we attempt one last, smaller increase
969- * (and then clear the growmemtuples flag so we don't try any more). That
970- * allows us to use allowedMem as fully as possible ; sticking to the pure
971- * doubling rule could result in almost half of allowedMem going unused.
972- * Because availMem moves around with tuple addition/removal, we need some
973- * rule to prevent making repeated small increases in memtupsize, which would
974- * just be useless thrashing. The growmemtuples flag accomplishes that and
975- * also prevents useless recalculations in this function.
968+ * Normally, at each increment we double the size of the array. When doing
969+ * that would exceed a limit , we attempt one last, smaller increase (and then
970+ * clear the growmemtuples flag so we don't try any more). That allows us to
971+ * use memory as fully as permitted ; sticking to the pure doubling rule could
972+ * result in almost half going unused. Because availMem moves around with
973+ * tuple addition/removal, we need some rule to prevent making repeated small
974+ * increases in memtupsize, which would just be useless thrashing. The
975+ * growmemtuples flag accomplishes that and also prevents useless
976+ * recalculations in this function.
976977 */
977978static bool
978979grow_memtuples (Tuplesortstate * state )
979980{
980981 int newmemtupsize ;
981982 int memtupsize = state -> memtupsize ;
982- long memNowUsed = state -> allowedMem - state -> availMem ;
983+ Size memNowUsed = state -> allowedMem - state -> availMem ;
983984
984985 /* Forget it if we've already maxed out memtuples, per comment above */
985986 if (!state -> growmemtuples )
@@ -989,14 +990,16 @@ grow_memtuples(Tuplesortstate *state)
989990 if (memNowUsed <= state -> availMem )
990991 {
991992 /*
992- * It is surely safe to double memtupsize if we've used no more than
993- * half of allowedMem.
994- *
995- * Note: it might seem that we need to worry about memtupsize * 2
996- * overflowing an int, but the MaxAllocSize clamp applied below
997- * ensures the existing memtupsize can't be large enough for that.
993+ * We've used no more than half of allowedMem; double our usage,
994+ * clamping at INT_MAX.
998995 */
999- newmemtupsize = memtupsize * 2 ;
996+ if (memtupsize < INT_MAX / 2 )
997+ newmemtupsize = memtupsize * 2 ;
998+ else
999+ {
1000+ newmemtupsize = INT_MAX ;
1001+ state -> growmemtuples = false;
1002+ }
10001003 }
10011004 else
10021005 {
@@ -1012,24 +1015,27 @@ grow_memtuples(Tuplesortstate *state)
10121015 * we've already seen, and thus we can extrapolate from the space
10131016 * consumption so far to estimate an appropriate new size for the
10141017 * memtuples array. The optimal value might be higher or lower than
1015- * this estimate, but it's hard to know that in advance.
1018+ * this estimate, but it's hard to know that in advance. We again
1019+ * clamp at INT_MAX tuples.
10161020 *
10171021 * This calculation is safe against enlarging the array so much that
10181022 * LACKMEM becomes true, because the memory currently used includes
10191023 * the present array; thus, there would be enough allowedMem for the
10201024 * new array elements even if no other memory were currently used.
10211025 *
10221026 * We do the arithmetic in float8, because otherwise the product of
1023- * memtupsize and allowedMem could overflow. (A little algebra shows
1024- * that grow_ratio must be less than 2 here, so we are not risking
1025- * integer overflow this way.) Any inaccuracy in the result should be
1026- * insignificant; but even if we computed a completely insane result,
1027- * the checks below will prevent anything really bad from happening.
1027+ * memtupsize and allowedMem could overflow. Any inaccuracy in the
1028+ * result should be insignificant; but even if we computed a
1029+ * completely insane result, the checks below will prevent anything
1030+ * really bad from happening.
10281031 */
10291032 double grow_ratio ;
10301033
10311034 grow_ratio = (double ) state -> allowedMem / (double ) memNowUsed ;
1032- newmemtupsize = (int ) (memtupsize * grow_ratio );
1035+ if (memtupsize * grow_ratio < INT_MAX )
1036+ newmemtupsize = (int ) (memtupsize * grow_ratio );
1037+ else
1038+ newmemtupsize = INT_MAX ;
10331039
10341040 /* We won't make any further enlargement attempts */
10351041 state -> growmemtuples = false;
@@ -1040,12 +1046,13 @@ grow_memtuples(Tuplesortstate *state)
10401046 goto noalloc ;
10411047
10421048 /*
1043- * On a 64-bit machine, allowedMem could be more than MaxAllocSize. Clamp
1044- * to ensure our request won't be rejected by palloc.
1049+ * On a 32-bit machine, allowedMem could exceed MaxAllocHugeSize. Clamp
1050+ * to ensure our request won't be rejected. Note that we can easily
1051+ * exhaust address space before facing this outcome.
10451052 */
1046- if ((Size ) newmemtupsize >= MaxAllocSize / sizeof (SortTuple ))
1053+ if ((Size ) newmemtupsize >= MaxAllocHugeSize / sizeof (SortTuple ))
10471054 {
1048- newmemtupsize = (int ) (MaxAllocSize / sizeof (SortTuple ));
1055+ newmemtupsize = (int ) (MaxAllocHugeSize / sizeof (SortTuple ));
10491056 state -> growmemtuples = false; /* can't grow any more */
10501057 }
10511058
@@ -1060,15 +1067,15 @@ grow_memtuples(Tuplesortstate *state)
10601067 * palloc would be treating both old and new arrays as separate chunks.
10611068 * But we'll check LACKMEM explicitly below just in case.)
10621069 */
1063- if (state -> availMem < (long ) ((newmemtupsize - memtupsize ) * sizeof (SortTuple )))
1070+ if (state -> availMem < (Size ) ((newmemtupsize - memtupsize ) * sizeof (SortTuple )))
10641071 goto noalloc ;
10651072
10661073 /* OK, do it */
10671074 FREEMEM (state , GetMemoryChunkSpace (state -> memtuples ));
10681075 state -> memtupsize = newmemtupsize ;
10691076 state -> memtuples = (SortTuple * )
1070- repalloc (state -> memtuples ,
1071- state -> memtupsize * sizeof (SortTuple ));
1077+ repalloc_huge (state -> memtuples ,
1078+ state -> memtupsize * sizeof (SortTuple ));
10721079 USEMEM (state , GetMemoryChunkSpace (state -> memtuples ));
10731080 if (LACKMEM (state ))
10741081 elog (ERROR , "unexpected out-of-memory situation during sort" );
@@ -1715,7 +1722,7 @@ tuplesort_getdatum(Tuplesortstate *state, bool forward,
17151722 * This is exported for use by the planner. allowedMem is in bytes.
17161723 */
17171724int
1718- tuplesort_merge_order (long allowedMem )
1725+ tuplesort_merge_order (Size allowedMem )
17191726{
17201727 int mOrder ;
17211728
@@ -1749,7 +1756,7 @@ inittapes(Tuplesortstate *state)
17491756 int maxTapes ,
17501757 ntuples ,
17511758 j ;
1752- long tapeSpace ;
1759+ Size tapeSpace ;
17531760
17541761 /* Compute number of tapes to use: merge order plus 1 */
17551762 maxTapes = tuplesort_merge_order (state -> allowedMem ) + 1 ;
@@ -1798,7 +1805,7 @@ inittapes(Tuplesortstate *state)
17981805 state -> mergenext = (int * ) palloc0 (maxTapes * sizeof (int ));
17991806 state -> mergelast = (int * ) palloc0 (maxTapes * sizeof (int ));
18001807 state -> mergeavailslots = (int * ) palloc0 (maxTapes * sizeof (int ));
1801- state -> mergeavailmem = (long * ) palloc0 (maxTapes * sizeof (long ));
1808+ state -> mergeavailmem = (Size * ) palloc0 (maxTapes * sizeof (Size ));
18021809 state -> tp_fib = (int * ) palloc0 (maxTapes * sizeof (int ));
18031810 state -> tp_runs = (int * ) palloc0 (maxTapes * sizeof (int ));
18041811 state -> tp_dummy = (int * ) palloc0 (maxTapes * sizeof (int ));
@@ -2026,7 +2033,7 @@ mergeonerun(Tuplesortstate *state)
20262033 int srcTape ;
20272034 int tupIndex ;
20282035 SortTuple * tup ;
2029- long priorAvail ,
2036+ Size priorAvail ,
20302037 spaceFreed ;
20312038
20322039 /*
@@ -2100,7 +2107,7 @@ beginmerge(Tuplesortstate *state)
21002107 int tapenum ;
21012108 int srcTape ;
21022109 int slotsPerTape ;
2103- long spacePerTape ;
2110+ Size spacePerTape ;
21042111
21052112 /* Heap should be empty here */
21062113 Assert (state -> memtupcount == 0 );
@@ -2221,7 +2228,7 @@ mergeprereadone(Tuplesortstate *state, int srcTape)
22212228 unsigned int tuplen ;
22222229 SortTuple stup ;
22232230 int tupIndex ;
2224- long priorAvail ,
2231+ Size priorAvail ,
22252232 spaceUsed ;
22262233
22272234 if (!state -> mergeactive [srcTape ])
0 commit comments