Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita89781e

Browse files
committed
Fix possible internal overflow in numeric multiplication.
mul_var() postpones propagating carries until it risks overflow in itsinternal digit array. However, the logic failed to account for thepossibility of overflow in the carry propagation step, allowing wrongresults to be generated in corner cases. We must slightly reduce thewhen-to-propagate-carries threshold to avoid that.Discovered and fixed by Dean Rasheed, with small adjustments by me.This has been wrong since commitd72f6c7,so back-patch to all supported branches.
1 parent24aed21 commita89781e

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

‎src/backend/utils/adt/numeric.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4191,9 +4191,15 @@ mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
41914191
* to avoid normalizing carries immediately.
41924192
*
41934193
* maxdig tracks the maximum possible value of any dig[] entry; when this
4194-
* threatens to exceed INT_MAX, we take the time to propagate carries. To
4195-
* avoid overflow in maxdig itself, it actually represents the max
4196-
* possible value divided by NBASE-1.
4194+
* threatens to exceed INT_MAX, we take the time to propagate carries.
4195+
* Furthermore, we need to ensure that overflow doesn't occur during the
4196+
* carry propagation passes either. The carry values could be as much as
4197+
* INT_MAX/NBASE, so really we must normalize when digits threaten to
4198+
* exceed INT_MAX - INT_MAX/NBASE.
4199+
*
4200+
* To avoid overflow in maxdig itself, it actually represents the max
4201+
* possible value divided by NBASE-1, ie, at the top of the loop it is
4202+
* known that no dig[] entry exceeds maxdig * (NBASE-1).
41974203
*/
41984204
dig= (int*)palloc0(res_ndigits*sizeof(int));
41994205
maxdig=0;
@@ -4208,7 +4214,7 @@ mul_var(NumericVar *var1, NumericVar *var2, NumericVar *result,
42084214

42094215
/* Time to normalize? */
42104216
maxdig+=var1digit;
4211-
if (maxdig>INT_MAX / (NBASE-1))
4217+
if (maxdig>(INT_MAX-INT_MAX /NBASE) / (NBASE-1))
42124218
{
42134219
/* Yes, do it */
42144220
carry=0;

‎src/test/regress/expected/numeric.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,33 @@ SELECT * FROM num_input_test;
13091309
NaN
13101310
(7 rows)
13111311

1312+
--
1313+
-- Test some corner cases for multiplication
1314+
--
1315+
select 4790999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
1316+
?column?
1317+
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1318+
47909999999999999999999999999999999999999999999999999999999999999999999999999999999999985209000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1319+
(1 row)
1320+
1321+
select 4789999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
1322+
?column?
1323+
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1324+
47899999999999999999999999999999999999999999999999999999999999999999999999999999999999985210000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1325+
(1 row)
1326+
1327+
select 4770999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
1328+
?column?
1329+
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1330+
47709999999999999999999999999999999999999999999999999999999999999999999999999999999999985229000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1331+
(1 row)
1332+
1333+
select 4769999999999999999999999999999999999999999999999999999999999999999999999999999999999999 * 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
1334+
?column?
1335+
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1336+
47699999999999999999999999999999999999999999999999999999999999999999999999999999999999985230000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1337+
(1 row)
1338+
13121339
--
13131340
-- Test some corner cases for division
13141341
--

‎src/test/regress/sql/numeric.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,18 @@ INSERT INTO num_input_test(n1) VALUES (' N aN ');
811811

812812
SELECT*FROM num_input_test;
813813

814+
--
815+
-- Test some corner cases for multiplication
816+
--
817+
818+
select4790999999999999999999999999999999999999999999999999999999999999999999999999999999999999*9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
819+
820+
select4789999999999999999999999999999999999999999999999999999999999999999999999999999999999999*9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
821+
822+
select4770999999999999999999999999999999999999999999999999999999999999999999999999999999999999*9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
823+
824+
select4769999999999999999999999999999999999999999999999999999999999999999999999999999999999999*9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999;
825+
814826
--
815827
-- Test some corner cases for division
816828
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp