Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)