From 512f67c8d02cc558f9c269cc848b0f0f788c4fe1 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 12 Jul 2017 13:24:16 -0400 Subject: [PATCH] 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 --- src/backend/utils/sort/tuplesort.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index a8a115c6b0..c152e43e68 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -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; -- 2.40.0