Commit 512f67c8 authored by Tom Lane's avatar Tom Lane

Avoid integer overflow while sifting-up a heap in tuplesort.c.

If the number of tuples in the heap exceeds approximately INT_MAX/2,
this loop's calculation "2*i+1" could overflow, resulting in a crash.
Fix it by using unsigned int rather than int for the relevant local
variables; that shouldn't cost anything extra on any popular hardware.
Per bug #14722 from Sergey Koposov.

Original patch by Sergey Koposov, modified by me per a suggestion
from Heikki Linnakangas to use unsigned int not int64.

Back-patch to 9.4, where tuplesort.c grew the ability to sort as many
as INT_MAX tuples in-memory (commit 263865a4).

Discussion: https://postgr.es/m/20170629161637.1478.93109@wrigleys.postgresql.org
parent ca906f68
......@@ -3490,7 +3490,7 @@ tuplesort_heap_replace_top(Tuplesortstate *state, SortTuple *tuple,
bool checkIndex)
{
SortTuple *memtuples = state->memtuples;
int i,
unsigned int i,
n;
Assert(!checkIndex || state->currentRun == RUN_FIRST);
......@@ -3498,11 +3498,16 @@ tuplesort_heap_replace_top(Tuplesortstate *state, SortTuple *tuple,
CHECK_FOR_INTERRUPTS();
/*
* state->memtupcount is "int", but we use "unsigned int" for i, j, n.
* This prevents overflow in the "2 * i + 1" calculation, since at the top
* of the loop we must have i < n <= INT_MAX <= UINT_MAX/2.
*/
n = state->memtupcount;
i = 0; /* i is where the "hole" is */
for (;;)
{
int j = 2 * i + 1;
unsigned int j = 2 * i + 1;
if (j >= n)
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment