summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/numeric.c
diff options
context:
space:
mode:
authorDean Rasheed <dean.a.rasheed@gmail.com>2021-08-06 21:34:04 +0100
committerDean Rasheed <dean.a.rasheed@gmail.com>2021-08-06 21:34:04 +0100
commit5b7b92ad74f2eeb4ac166bb45be31df95e574b3b (patch)
treef10e82b92da92155befa7caa0e8df12a5037bf3e /src/backend/utils/adt/numeric.c
parentbf224e0a420397d9fdf8ead99a936fd44350f6bf (diff)
downloadpostgresql-5b7b92ad74f2eeb4ac166bb45be31df95e574b3b.tar.gz
Adjust the integer overflow tests in the numeric code.
Formerly, the numeric code tested whether an integer value of a larger type would fit in a smaller type by casting it to the smaller type and then testing if the reverse conversion produced the original value. That's perfectly fine, except that it caused a test failure on buildfarm animal castoroides, most likely due to a compiler bug. Instead, do these tests by comparing against PG_INT16/32_MIN/MAX. That matches existing code in other places, such as int84(), which is more widely tested, and so is less likely to go wrong. While at it, add regression tests covering the numeric-to-int8/4/2 conversions, and adjust the recently added tests to the style of 434ddfb79a (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
Diffstat (limited to 'src/backend/utils/adt/numeric.c')
-rw-r--r--src/backend/utils/adt/numeric.c26
1 files changed, 9 insertions, 17 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 98574669a2..b485415975 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -2889,7 +2889,6 @@ numeric_int4(PG_FUNCTION_ARGS)
static int32
numericvar_to_int32(NumericVar *var)
{
- int32 result;
int64 val;
if (!numericvar_to_int64(var, &val))
@@ -2897,16 +2896,13 @@ numericvar_to_int32(NumericVar *var)
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
- /* Down-convert to int4 */
- result = (int32) val;
-
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != val)
+ if (val < PG_INT32_MIN || val > PG_INT32_MAX)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
- return result;
+ /* Down-convert to int4 */
+ return (int32) val;
}
Datum
@@ -2994,15 +2990,14 @@ numeric_int2(PG_FUNCTION_ARGS)
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
- /* Down-convert to int2 */
- result = (int16) val;
-
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != val)
+ if (val < PG_INT16_MIN || val > PG_INT16_MAX)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
+ /* Down-convert to int2 */
+ result = (int16) val;
+
PG_RETURN_INT16(result);
}
@@ -7976,10 +7971,7 @@ power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
if (numericvar_to_int64(exp, &expval64))
{
- int expval = (int) expval64;
-
- /* Test for overflow by reverse-conversion. */
- if ((int64) expval == expval64)
+ if (expval64 >= PG_INT32_MIN && expval64 <= PG_INT32_MAX)
{
/* Okay, select rscale */
rscale = NUMERIC_MIN_SIG_DIGITS;
@@ -7987,7 +7979,7 @@ power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
rscale = Max(rscale, NUMERIC_MIN_DISPLAY_SCALE);
rscale = Min(rscale, NUMERIC_MAX_DISPLAY_SCALE);
- power_var_int(base, expval, result, rscale);
+ power_var_int(base, (int) expval64, result, rscale);
return;
}
}