aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/numeric.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/numeric.c')
-rw-r--r--src/backend/utils/adt/numeric.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 1bfa29e1b28..1667d8093f1 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -5789,9 +5789,15 @@ mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
* to avoid normalizing carries immediately.
*
* maxdig tracks the maximum possible value of any dig[] entry; when this
- * threatens to exceed INT_MAX, we take the time to propagate carries. To
- * avoid overflow in maxdig itself, it actually represents the max
- * possible value divided by NBASE-1.
+ * threatens to exceed INT_MAX, we take the time to propagate carries.
+ * Furthermore, we need to ensure that overflow doesn't occur during the
+ * carry propagation passes either. The carry values could be as much as
+ * INT_MAX/NBASE, so really we must normalize when digits threaten to
+ * exceed INT_MAX - INT_MAX/NBASE.
+ *
+ * To avoid overflow in maxdig itself, it actually represents the max
+ * possible value divided by NBASE-1, ie, at the top of the loop it is
+ * known that no dig[] entry exceeds maxdig * (NBASE-1).
*/
dig = (int *) palloc0(res_ndigits * sizeof(int));
maxdig = 0;
@@ -5806,7 +5812,7 @@ mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
/* Time to normalize? */
maxdig += var1digit;
- if (maxdig > INT_MAX / (NBASE - 1))
+ if (maxdig > (INT_MAX - INT_MAX / NBASE) / (NBASE - 1))
{
/* Yes, do it */
carry = 0;