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

Commit0325565

Browse files
committed
Adjust the integer overflow tests in the numeric code.
Formerly, the numeric code tested whether an integer value of a largertype would fit in a smaller type by casting it to the smaller type andthen testing if the reverse conversion produced the original value.That's perfectly fine, except that it caused a test failure onbuildfarm animal castoroides, most likely due to a compiler bug.Instead, do these tests by comparing against PG_INT16/32_MIN/MAX. Thatmatches existing code in other places, such as int84(), which is morewidely tested, and so is less likely to go wrong.While at it, add regression tests covering the numeric-to-int8/4/2conversions, and adjust the recently added tests to the style of434ddfb (on the v11 branch) to make failures easier to diagnose.Per buildfarm via Tom Lane, reviewed by Tom Lane.Discussion:https://postgr.es/m/2394813.1628179479%40sss.pgh.pa.us
1 parentc3a135b commit0325565

File tree

3 files changed

+85
-24
lines changed

3 files changed

+85
-24
lines changed

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4228,11 +4228,13 @@ numericvar_to_int32(const NumericVar *var, int32 *result)
42284228
if (!numericvar_to_int64(var,&val))
42294229
return false;
42304230

4231+
if (unlikely(val<PG_INT32_MIN)||unlikely(val>PG_INT32_MAX))
4232+
return false;
4233+
42314234
/* Down-convert to int4 */
42324235
*result= (int32)val;
42334236

4234-
/* Test for overflow by reverse-conversion. */
4235-
return ((int64)*result==val);
4237+
return true;
42364238
}
42374239

42384240
Datum
@@ -4312,15 +4314,14 @@ numeric_int2(PG_FUNCTION_ARGS)
43124314
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
43134315
errmsg("smallint out of range")));
43144316

4315-
/* Down-convert to int2 */
4316-
result= (int16)val;
4317-
4318-
/* Test for overflow by reverse-conversion. */
4319-
if ((int64)result!=val)
4317+
if (unlikely(val<PG_INT16_MIN)||unlikely(val>PG_INT16_MAX))
43204318
ereport(ERROR,
43214319
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
43224320
errmsg("smallint out of range")));
43234321

4322+
/* Down-convert to int2 */
4323+
result= (int16)val;
4324+
43244325
PG_RETURN_INT16(result);
43254326
}
43264327

@@ -10147,18 +10148,15 @@ power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
1014710148

1014810149
if (numericvar_to_int64(exp,&expval64))
1014910150
{
10150-
intexpval= (int)expval64;
10151-
10152-
/* Test for overflow by reverse-conversion. */
10153-
if ((int64)expval==expval64)
10151+
if (expval64 >=PG_INT32_MIN&&expval64 <=PG_INT32_MAX)
1015410152
{
1015510153
/* Okay, select rscale */
1015610154
rscale=NUMERIC_MIN_SIG_DIGITS;
1015710155
rscale=Max(rscale,base->dscale);
1015810156
rscale=Max(rscale,NUMERIC_MIN_DISPLAY_SCALE);
1015910157
rscale=Min(rscale,NUMERIC_MAX_DISPLAY_SCALE);
1016010158

10161-
power_var_int(base,expval,result,rscale);
10159+
power_var_int(base,(int)expval64,result,rscale);
1016210160
return;
1016310161
}
1016410162
}

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

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,55 @@ SELECT * FROM fract_only;
11541154
(7 rows)
11551155

11561156
DROP TABLE fract_only;
1157+
-- Check conversion to integers
1158+
SELECT (-9223372036854775808.5)::int8; -- should fail
1159+
ERROR: bigint out of range
1160+
SELECT (-9223372036854775808.4)::int8; -- ok
1161+
int8
1162+
----------------------
1163+
-9223372036854775808
1164+
(1 row)
1165+
1166+
SELECT 9223372036854775807.4::int8; -- ok
1167+
int8
1168+
---------------------
1169+
9223372036854775807
1170+
(1 row)
1171+
1172+
SELECT 9223372036854775807.5::int8; -- should fail
1173+
ERROR: bigint out of range
1174+
SELECT (-2147483648.5)::int4; -- should fail
1175+
ERROR: integer out of range
1176+
SELECT (-2147483648.4)::int4; -- ok
1177+
int4
1178+
-------------
1179+
-2147483648
1180+
(1 row)
1181+
1182+
SELECT 2147483647.4::int4; -- ok
1183+
int4
1184+
------------
1185+
2147483647
1186+
(1 row)
1187+
1188+
SELECT 2147483647.5::int4; -- should fail
1189+
ERROR: integer out of range
1190+
SELECT (-32768.5)::int2; -- should fail
1191+
ERROR: smallint out of range
1192+
SELECT (-32768.4)::int2; -- ok
1193+
int2
1194+
--------
1195+
-32768
1196+
(1 row)
1197+
1198+
SELECT 32767.4::int2; -- ok
1199+
int2
1200+
-------
1201+
32767
1202+
(1 row)
1203+
1204+
SELECT 32767.5::int2; -- should fail
1205+
ERROR: smallint out of range
11571206
-- Check inf/nan conversion behavior
11581207
SELECT 'NaN'::float8::numeric;
11591208
numeric
@@ -2365,10 +2414,10 @@ select 1.000000000123 ^ (-2147483648);
23652414
0.7678656556403084
23662415
(1 row)
23672416

2368-
select 0.9999999999 ^ 23300000000000 = 0 as rounds_to_zero;
2417+
selectcoalesce(nullif(0.9999999999 ^ 23300000000000, 0), 0) as rounds_to_zero;
23692418
rounds_to_zero
23702419
----------------
2371-
t
2420+
0
23722421
(1 row)
23732422

23742423
-- cases that used to error out
@@ -2384,10 +2433,10 @@ select 0.5678 ^ (-85);
23842433
782333637740774446257.7719390061997396
23852434
(1 row)
23862435

2387-
select 0.9999999999 ^ 70000000000000 = 0 as underflows;
2436+
selectcoalesce(nullif(0.9999999999 ^ 70000000000000, 0), 0) as underflows;
23882437
underflows
23892438
------------
2390-
t
2439+
0
23912440
(1 row)
23922441

23932442
-- negative base to integer powers
@@ -2557,16 +2606,16 @@ select exp('-inf'::numeric);
25572606
0
25582607
(1 row)
25592608

2560-
select exp(-5000::numeric) = 0 as rounds_to_zero;
2609+
selectcoalesce(nullif(exp(-5000::numeric), 0), 0) as rounds_to_zero;
25612610
rounds_to_zero
25622611
----------------
2563-
t
2612+
0
25642613
(1 row)
25652614

2566-
select exp(-10000::numeric) = 0 as underflows;
2615+
selectcoalesce(nullif(exp(-10000::numeric), 0), 0) as underflows;
25672616
underflows
25682617
------------
2569-
t
2618+
0
25702619
(1 row)
25712620

25722621
-- cases that used to generate inaccurate results

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,20 @@ INSERT INTO fract_only VALUES (11, '-Inf');-- should fail
773773
SELECT*FROM fract_only;
774774
DROPTABLE fract_only;
775775

776+
-- Check conversion to integers
777+
SELECT (-9223372036854775808.5)::int8;-- should fail
778+
SELECT (-9223372036854775808.4)::int8;-- ok
779+
SELECT9223372036854775807.4::int8;-- ok
780+
SELECT9223372036854775807.5::int8;-- should fail
781+
SELECT (-2147483648.5)::int4;-- should fail
782+
SELECT (-2147483648.4)::int4;-- ok
783+
SELECT2147483647.4::int4;-- ok
784+
SELECT2147483647.5::int4;-- should fail
785+
SELECT (-32768.5)::int2;-- should fail
786+
SELECT (-32768.4)::int2;-- ok
787+
SELECT32767.4::int2;-- ok
788+
SELECT32767.5::int2;-- should fail
789+
776790
-- Check inf/nan conversion behavior
777791
SELECT'NaN'::float8::numeric;
778792
SELECT'Infinity'::float8::numeric;
@@ -1099,12 +1113,12 @@ select 3.789 ^ 35;
10991113
select1.2 ^345;
11001114
select0.12 ^ (-20);
11011115
select1.000000000123 ^ (-2147483648);
1102-
select0.9999999999 ^23300000000000=0as rounds_to_zero;
1116+
selectcoalesce(nullif(0.9999999999 ^23300000000000,0),0)as rounds_to_zero;
11031117

11041118
-- cases that used to error out
11051119
select0.12 ^ (-25);
11061120
select0.5678 ^ (-85);
1107-
select0.9999999999 ^70000000000000=0as underflows;
1121+
selectcoalesce(nullif(0.9999999999 ^70000000000000,0),0)as underflows;
11081122

11091123
-- negative base to integer powers
11101124
select (-1.0) ^2147483646;
@@ -1154,8 +1168,8 @@ select exp(1.0::numeric(71,70));
11541168
select exp('nan'::numeric);
11551169
select exp('inf'::numeric);
11561170
select exp('-inf'::numeric);
1157-
select exp(-5000::numeric)=0as rounds_to_zero;
1158-
select exp(-10000::numeric)=0as underflows;
1171+
selectcoalesce(nullif(exp(-5000::numeric),0),0)as rounds_to_zero;
1172+
selectcoalesce(nullif(exp(-10000::numeric),0),0)as underflows;
11591173

11601174
-- cases that used to generate inaccurate results
11611175
select exp(32.999);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp