8000 Fix possible internal overflow in numeric division. · SudhirLonkar/postgres@728a2ac · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 728a2ac

Browse files
committed
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 246693e, 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
1 parent 7b21d1b commit 728a2ac

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

src/backend/utils/adt/numeric.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4872,8 +4872,14 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
48724872
/*
48734873
* maxdiv tracks the maximum possible absolute value of any div[] entry;
48744874
* when this threatens to exceed INT_MAX, we take the ti 8000 me to propagate
4875-
* carries. To avoid overflow in maxdiv itself, it actually represents
4876-
* the max possible abs. value divided by NBASE-1.
4875+
* carries. Furthermore, we need to ensure that overflow doesn't occur
4876+
* during the carry propagation passes either. The carry values may have
4877+
* an absolute value as high as INT_MAX/NBASE + 1, so really we must
4878+
* normalize when digits threaten to exceed INT_MAX - INT_MAX/NBASE - 1.
4879+
*
4880+
* To avoid overflow in maxdiv itself, it represents the max absolute
4881+
* value divided by NBASE-1, ie, at the top of the loop it is known that
4882+
* no div[] entry has an absolute value exceeding maxdiv * (NBASE-1).
48774883
*/
48784884
maxdiv = 1;
48794885

@@ -4899,7 +4905,7 @@ div_var_fast(NumericVar *var1, NumericVar *var2, NumericVar *result,
48994905
{
49004906
/* Do we need to normalize now? */
49014907
maxdiv += Abs(qdigit);
4902-
if (maxdiv > INT_MAX / (NBASE - 1))
4908+
if (maxdiv > (INT_MAX - INT_MAX / NBASE - 1) / (NBASE - 1))
49034909
{
49044910
/* Yes, do it */
49054911
carry = 0;

0 commit comments

Comments
 (0)
0