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

Commit2642df9

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 parentba4eb86 commit2642df9

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
@@ -4289,11 +4289,13 @@ numericvar_to_int32(const NumericVar *var, int32 *result)
42894289
if (!numericvar_to_int64(var,&val))
42904290
return false;
42914291

4292+
if (unlikely(val<PG_INT32_MIN)||unlikely(val>PG_INT32_MAX))
4293+
return false;
4294+
42924295
/* Down-convert to int4 */
42934296
*result= (int32)val;
42944297

4295-
/* Test for overflow by reverse-conversion. */
4296-
return ((int64)*result==val);
4298+
return true;
42974299
}
42984300

42994301
Datum
@@ -4373,15 +4375,14 @@ numeric_int2(PG_FUNCTION_ARGS)
43734375
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
43744376
errmsg("smallint out of range")));
43754377

4376-
/* Down-convert to int2 */
4377-
result= (int16)val;
4378-
4379-
/* Test for overflow by reverse-conversion. */
4380-
if ((int64)result!=val)
4378+
if (unlikely(val<PG_INT16_MIN)||unlikely(val>PG_INT16_MAX))
43814379
ereport(ERROR,
43824380
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
43834381
errmsg("smallint out of range")));
43844382

4383+
/* Down-convert to int2 */
4384+
result= (int16)val;
4385+
43854386
PG_RETURN_INT16(result);
43864387
}
43874388

@@ -10186,18 +10187,15 @@ power_var(const NumericVar *base, const NumericVar *exp, NumericVar *result)
1018610187

1018710188
if (numericvar_to_int64(exp,&expval64))
1018810189
{
10189-
intexpval= (int)expval64;
10190-
10191-
/* Test for overflow by reverse-conversion. */
10192-
if ((int64)expval==expval64)
10190+
if (expval64 >=PG_INT32_MIN&&expval64 <=PG_INT32_MAX)
1019310191
{
1019410192
/* Okay, select rscale */
1019510193
rscale=NUMERIC_MIN_SIG_DIGITS;
1019610194
rscale=Max(rscale,base->dscale);
1019710195
rscale=Max(rscale,NUMERIC_MIN_DISPLAY_SCALE);
1019810196
rscale=Min(rscale,NUMERIC_MAX_DISPLAY_SCALE);
1019910197

10200-
power_var_int(base,expval,result,rscale);
10198+
power_var_int(base,(int)expval64,result,rscale);
1020110199
return;
1020210200
}
1020310201
}

‎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
@@ -2428,10 +2477,10 @@ select 1.000000000123 ^ (-2147483648);
24282477
0.7678656556403084
24292478
(1 row)
24302479

2431-
select 0.9999999999 ^ 23300000000000 = 0 as rounds_to_zero;
2480+
selectcoalesce(nullif(0.9999999999 ^ 23300000000000, 0), 0) as rounds_to_zero;
24322481
rounds_to_zero
24332482
----------------
2434-
t
2483+
0
24352484
(1 row)
24362485

24372486
-- cases that used to error out
@@ -2447,10 +2496,10 @@ select 0.5678 ^ (-85);
24472496
782333637740774446257.7719390061997396
24482497
(1 row)
24492498

2450-
select 0.9999999999 ^ 70000000000000 = 0 as underflows;
2499+
selectcoalesce(nullif(0.9999999999 ^ 70000000000000, 0), 0) as underflows;
24512500
underflows
24522501
------------
2453-
t
2502+
0
24542503
(1 row)
24552504

24562505
-- negative base to integer powers
@@ -2620,16 +2669,16 @@ select exp('-inf'::numeric);
26202669
0
26212670
(1 row)
26222671

2623-
select exp(-5000::numeric) = 0 as rounds_to_zero;
2672+
selectcoalesce(nullif(exp(-5000::numeric), 0), 0) as rounds_to_zero;
26242673
rounds_to_zero
26252674
----------------
2626-
t
2675+
0
26272676
(1 row)
26282677

2629-
select exp(-10000::numeric) = 0 as underflows;
2678+
selectcoalesce(nullif(exp(-10000::numeric), 0), 0) as underflows;
26302679
underflows
26312680
------------
2632-
t
2681+
0
26332682
(1 row)
26342683

26352684
-- 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;
@@ -1133,12 +1147,12 @@ select 3.789 ^ 35;
11331147
select1.2 ^345;
11341148
select0.12 ^ (-20);
11351149
select1.000000000123 ^ (-2147483648);
1136-
select0.9999999999 ^23300000000000=0as rounds_to_zero;
1150+
selectcoalesce(nullif(0.9999999999 ^23300000000000,0),0)as rounds_to_zero;
11371151

11381152
-- cases that used to error out
11391153
select0.12 ^ (-25);
11401154
select0.5678 ^ (-85);
1141-
select0.9999999999 ^70000000000000=0as underflows;
1155+
selectcoalesce(nullif(0.9999999999 ^70000000000000,0),0)as underflows;
11421156

11431157
-- negative base to integer powers
11441158
select (-1.0) ^2147483646;
@@ -1188,8 +1202,8 @@ select exp(1.0::numeric(71,70));
11881202
select exp('nan'::numeric);
11891203
select exp('inf'::numeric);
11901204
select exp('-inf'::numeric);
1191-
select exp(-5000::numeric)=0as rounds_to_zero;
1192-
select exp(-10000::numeric)=0as underflows;
1205+
selectcoalesce(nullif(exp(-5000::numeric),0),0)as rounds_to_zero;
1206+
selectcoalesce(nullif(exp(-10000::numeric),0),0)as underflows;
11931207

11941208
-- cases that used to generate inaccurate results
11951209
select exp(32.999);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp