Skip to content

Commit f9ac414

Browse files
committed
Fix float4/8 to handle Infinity and Nan consistently, e.g. Infinity is a
valid result from a computation if one of the input values was infinity. The previous code assumed an operation that returned infinity was an overflow. Handle underflow/overflow consistently, and add checks for aggregate overflow. Consistently prevent Inf/Nan from being cast to integer data types. Fix INT_MIN % -1 to prevent overflow. Update regression results for new error text. Per report from Roman Kononov.
1 parent 0b56be8 commit f9ac414

File tree

9 files changed

+215
-264
lines changed

9 files changed

+215
-264
lines changed

src/backend/utils/adt/float.c

Lines changed: 147 additions & 225 deletions
Large diffs are not rendered by default.

src/backend/utils/adt/int.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.75 2006/10/04 00:29:59 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.76 2007/01/02 20:00:49 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1124,6 +1124,11 @@ int4mod(PG_FUNCTION_ARGS)
11241124
ereport(ERROR,
11251125
(errcode(ERRCODE_DIVISION_BY_ZERO),
11261126
errmsg("division by zero")));
1127+
1128+
/* SELECT ((-2147483648)::int4) % (-1); causes a floating point exception */
1129+
if (arg1 == INT_MIN && arg2 == -1)
1130+
PG_RETURN_INT32(0);
1131+
11271132
/* No overflow is possible */
11281133

11291134
PG_RETURN_INT32(arg1 % arg2);

src/test/regress/expected/float4-exp-three-digits.out

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ INSERT INTO FLOAT4_TBL(f1) VALUES (' -34.84 ');
88
INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20');
99
INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20');
1010
-- test for over and under flow
11-
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e40');
12-
ERROR: type "real" value out of range: overflow
13-
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e40');
14-
ERROR: type "real" value out of range: overflow
15-
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-40');
16-
ERROR: type "real" value out of range: underflow
17-
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-40');
18-
ERROR: type "real" value out of range: underflow
11+
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
12+
ERROR: value out of range: overflow
13+
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
14+
ERROR: value out of range: overflow
15+
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
16+
ERROR: value out of range: underflow
17+
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
18+
ERROR: value out of range: underflow
1919
-- bad input
2020
INSERT INTO FLOAT4_TBL(f1) VALUES ('');
2121
ERROR: invalid input syntax for type real: ""
@@ -72,7 +72,11 @@ ERROR: invalid input syntax for type real: "NaN x"
7272
SELECT ' INFINITY x'::float4;
7373
ERROR: invalid input syntax for type real: " INFINITY x"
7474
SELECT 'Infinity'::float4 + 100.0;
75-
ERROR: type "double precision" value out of range: overflow
75+
?column?
76+
----------
77+
Infinity
78+
(1 row)
79+
7680
SELECT 'Infinity'::float4 / 'Infinity'::float4;
7781
?column?
7882
----------

src/test/regress/expected/float4.out

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ INSERT INTO FLOAT4_TBL(f1) VALUES (' -34.84 ');
88
INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20');
99
INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20');
1010
-- test for over and under flow
11-
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e40');
12-
ERROR: type "real" value out of range: overflow
13-
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e40');
14-
ERROR: type "real" value out of range: overflow
15-
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-40');
16-
ERROR: type "real" value out of range: underflow
17-
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-40');
18-
ERROR: type "real" value out of range: underflow
11+
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
12+
ERROR: value out of range: overflow
13+
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
14+
ERROR: value out of range: overflow
15+
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
16+
ERROR: value out of range: underflow
17+
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
18+
ERROR: value out of range: underflow
1919
-- bad input
2020
INSERT INTO FLOAT4_TBL(f1) VALUES ('');
2121
ERROR: invalid input syntax for type real: ""
@@ -72,7 +72,11 @@ ERROR: invalid input syntax for type real: "NaN x"
7272
SELECT ' INFINITY x'::float4;
7373
ERROR: invalid input syntax for type real: " INFINITY x"
7474
SELECT 'Infinity'::float4 + 100.0;
75-
ERROR: type "double precision" value out of range: overflow
75+
?column?
76+
----------
77+
Infinity
78+
(1 row)
79+
7680
SELECT 'Infinity'::float4 / 'Infinity'::float4;
7781
?column?
7882
----------

src/test/regress/expected/float8-exp-three-digits-win32.out

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ ERROR: invalid input syntax for type double precision: "NaN x"
7272
SELECT ' INFINITY x'::float8;
7373
ERROR: invalid input syntax for type double precision: " INFINITY x"
7474
SELECT 'Infinity'::float8 + 100.0;
75-
ERROR: type "double precision" value out of range: overflow
75+
?column?
76+
----------
77+
Infinity
78+
(1 row)
79+
7680
SELECT 'Infinity'::float8 / 'Infinity'::float8;
7781
?column?
7882
----------
@@ -342,15 +346,15 @@ UPDATE FLOAT8_TBL
342346
SET f1 = FLOAT8_TBL.f1 * '-1'
343347
WHERE FLOAT8_TBL.f1 > '0.0';
344348
SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f;
345-
ERROR: type "double precision" value out of range: overflow
349+
ERROR: value out of range: overflow
346350
SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
347-
ERROR: result is out of range
351+
ERROR: value out of range: overflow
348352
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;
349353
ERROR: cannot take logarithm of zero
350354
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
351355
ERROR: cannot take logarithm of a negative number
352356
SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
353-
ERROR: result is out of range
357+
ERROR: value out of range: underflow
354358
SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
355359
ERROR: division by zero
356360
SELECT '' AS five, * FROM FLOAT8_TBL;

src/test/regress/expected/float8-small-is-zero.out

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ ERROR: invalid input syntax for type double precision: "NaN x"
8080
SELECT ' INFINITY x'::float8;
8181
ERROR: invalid input syntax for type double precision: " INFINITY x"
8282
SELECT 'Infinity'::float8 + 100.0;
83-
ERROR: type "double precision" value out of range: overflow
83+
?column?
84+
----------
85+
Infinity
86+
(1 row)
87+
8488
SELECT 'Infinity'::float8 / 'Infinity'::float8;
8589
?column?
8690
----------
@@ -350,15 +354,15 @@ UPDATE FLOAT8_TBL
350354
SET f1 = FLOAT8_TBL.f1 * '-1'
351355
WHERE FLOAT8_TBL.f1 > '0.0';
352356
SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f;
353-
ERROR: type "double precision" value out of range: overflow
357+
ERROR: value out of range: overflow
354358
SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
355-
ERROR: result is out of range
359+
ERROR: value out of range: overflow
356360
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;
357361
ERROR: cannot take logarithm of zero
358362
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
359363
ERROR: cannot take logarithm of a negative number
360364
SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
361-
ERROR: result is out of range
365+
ERROR: value out of range: underflow
362366
SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
363367
ERROR: division by zero
364368
SELECT '' AS five, * FROM FLOAT8_TBL;

src/test/regress/expected/float8-small-is-zero_1.out

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ ERROR: invalid input syntax for type double precision: "NaN x"
8080
SELECT ' INFINITY x'::float8;
8181
ERROR: invalid input syntax for type double precision: " INFINITY x"
8282
SELECT 'Infinity'::float8 + 100.0;
83-
ERROR: type "double precision" value out of range: overflow
83+
?column?
84+
----------
85+
Infinity
86+
(1 row)
87+
8488
SELECT 'Infinity'::float8 / 'Infinity'::float8;
8589
?column?
8690
----------
@@ -350,15 +354,15 @@ UPDATE FLOAT8_TBL
350354
SET f1 = FLOAT8_TBL.f1 * '-1'
351355
WHERE FLOAT8_TBL.f1 > '0.0';
352356
SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f;
353-
ERROR: type "double precision" value out of range: overflow
357+
ERROR: value out of range: overflow
354358
SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
355-
ERROR: result is out of range
359+
ERROR: value out of range: overflow
356360
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;
357361
ERROR: cannot take logarithm of zero
358362
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
359363
ERROR: cannot take logarithm of a negative number
360364
SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
361-
ERROR: result is out of range
365+
ERROR: value out of range: underflow
362366
SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
363367
ERROR: division by zero
364368
SELECT '' AS five, * FROM FLOAT8_TBL;

src/test/regress/expected/float8.out

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,11 @@ ERROR: invalid input syntax for type double precision: "NaN x"
7272
SELECT ' INFINITY x'::float8;
7373
ERROR: invalid input syntax for type double precision: " INFINITY x"
7474
SELECT 'Infinity'::float8 + 100.0;
75-
ERROR: type "double precision" value out of range: overflow
75+
?column?
76+
----------
77+
Infinity
78+
(1 row)
79+
7680
SELECT 'Infinity'::float8 / 'Infinity'::float8;
7781
?column?
7882
----------
@@ -342,15 +346,15 @@ UPDATE FLOAT8_TBL
342346
SET f1 = FLOAT8_TBL.f1 * '-1'
343347
WHERE FLOAT8_TBL.f1 > '0.0';
344348
SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f;
345-
ERROR: type "double precision" value out of range: overflow
349+
ERROR: value out of range: overflow
346350
SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
347-
ERROR: result is out of range
351+
ERROR: value out of range: overflow
348352
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;
349353
ERROR: cannot take logarithm of zero
350354
SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
351355
ERROR: cannot take logarithm of a negative number
352356
SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
353-
ERROR: result is out of range
357+
ERROR: value out of range: underflow
354358
SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
355359
ERROR: division by zero
356360
SELECT '' AS five, * FROM FLOAT8_TBL;

src/test/regress/sql/float4.sql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e+20');
1111
INSERT INTO FLOAT4_TBL(f1) VALUES ('1.2345678901234e-20');
1212

1313
-- test for over and under flow
14-
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e40');
15-
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e40');
16-
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-40');
17-
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-40');
14+
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e70');
15+
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e70');
16+
INSERT INTO FLOAT4_TBL(f1) VALUES ('10e-70');
17+
INSERT INTO FLOAT4_TBL(f1) VALUES ('-10e-70');
1818

1919
-- bad input
2020
INSERT INTO FLOAT4_TBL(f1) VALUES ('');

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy