diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2017-07-12 13:24:17 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2017-07-12 13:24:17 -0400 |
commit | e439bbe9996f508f584cda9075d0bb3d5fbd7d97 (patch) | |
tree | 0db0df200b146123cc380c56ef530d958322b6b0 /src | |
parent | a94dd0c25d0132a48c2f95505e0f95bb273f1160 (diff) | |
download | postgresql-e439bbe9996f508f584cda9075d0bb3d5fbd7d97.tar.gz postgresql-e439bbe9996f508f584cda9075d0bb3d5fbd7d97.zip |
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 263865a48).
Discussion: https://postgr.es/m/20170629161637.1478.93109@wrigleys.postgresql.org
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/sort/tuplesort.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 18cb046f198..9b61a893ca1 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -2729,7 +2729,7 @@ tuplesort_heap_siftup(Tuplesortstate *state, bool checkIndex) { SortTuple *memtuples = state->memtuples; SortTuple *tuple; - int i, + unsigned int i, n; if (--state->memtupcount <= 0) @@ -2737,12 +2737,17 @@ tuplesort_heap_siftup(Tuplesortstate *state, bool checkIndex) 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; tuple = &memtuples[n]; /* tuple that must be reinserted */ i = 0; /* i is where the "hole" is */ for (;;) { - int j = 2 * i + 1; + unsigned int j = 2 * i + 1; if (j >= n) break; |