Commit 5f10b7a6 authored by Tom Lane's avatar Tom Lane

Fix possible internal overflow in numeric division.

div_var_fast() postpones propagating carries in the same way as mul_var(),
so it has the same corner-case overflow risk we fixed in 246693e5,
namely that the size of the carries has to be accounted for when setting
the threshold for executing a carry propagation step.  We've not devised
a test case illustrating the brokenness, but the required fix seems clear
enough.  Like the previous fix, back-patch to all active branches.

Dean Rasheed
parent c5ec4064
...@@ -6266,8 +6266,14 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result, ...@@ -6266,8 +6266,14 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
/* /*
* maxdiv tracks the maximum possible absolute value of any div[] entry; * maxdiv tracks the maximum possible absolute value of any div[] entry;
* when this threatens to exceed INT_MAX, we take the time to propagate * when this threatens to exceed INT_MAX, we take the time to propagate
* carries. To avoid overflow in maxdiv itself, it actually represents * carries. Furthermore, we need to ensure that overflow doesn't occur
* the max possible abs. value divided by NBASE-1. * during the carry propagation passes either. The carry values may have
* an absolute value as high as INT_MAX/NBASE + 1, so really we must
* normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
*
* To avoid overflow in maxdiv itself, it represents the max absolute
* value divided by NBASE-1, ie, at the top of the loop it is known that
* no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
*/ */
maxdiv = 1; maxdiv = 1;
...@@ -6293,7 +6299,7 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result, ...@@ -6293,7 +6299,7 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
{ {
/* Do we need to normalize now? */ /* Do we need to normalize now? */
maxdiv += Abs(qdigit); maxdiv += Abs(qdigit);
if (maxdiv > INT_MAX / (NBASE - 1)) if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
{ {
/* Yes, do it */ /* Yes, do it */
carry = 0; carry = 0;
......
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