v4-0001-make-some-numeric-cast-function-error-safe.patch
text/x-patch
Filename: v4-0001-make-some-numeric-cast-function-error-safe.patch
Type: text/x-patch
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v4-0001
Subject: make some numeric cast function error safe
| File | + | − |
|---|---|---|
| src/backend/utils/adt/float.c | 10 | 6 |
| src/backend/utils/adt/int8.c | 2 | 2 |
| src/backend/utils/adt/numeric.c | 55 | 12 |
From e3854ee1d362646ea97a8baa4e262cc3a9e95913 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Fri, 1 Aug 2025 13:22:59 +0800
Subject: [PATCH v4 1/3] make some numeric cast function error safe
The following function are changed to make it error safe.
numeric_int2
numeric_int4
numeric_int8
numeric_float4
numeric_float8
dtoi8
dtoi4
dtoi2
ftoi8
ftoi4
ftoi2
ftod
dtof
float4_numeric
float8_numeric
numeric (oid 1703)
This is need for evaulation CAST(... DEFAULT... ON CONVERSION ERROR).
discussion: https://postgr.es/m/CADkLM=fv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ@mail.gmail.com
---
src/backend/utils/adt/float.c | 16 +++++---
src/backend/utils/adt/int8.c | 4 +-
src/backend/utils/adt/numeric.c | 67 +++++++++++++++++++++++++++------
3 files changed, 67 insertions(+), 20 deletions(-)
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 7b97d2be6c..6461e9c94b 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -1199,9 +1199,13 @@ dtof(PG_FUNCTION_ARGS)
result = (float4) num;
if (unlikely(isinf(result)) && !isinf(num))
- float_overflow_error();
+ ereturn(fcinfo->context, (Datum) 0,
+ errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value out of range: overflow"));
if (unlikely(result == 0.0f) && num != 0.0)
- float_underflow_error();
+ ereturn(fcinfo->context, (Datum) 0,
+ errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value out of range: underflow"));
PG_RETURN_FLOAT4(result);
}
@@ -1224,7 +1228,7 @@ dtoi4(PG_FUNCTION_ARGS)
/* Range check */
if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT32(num)))
- ereport(ERROR,
+ ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
@@ -1249,7 +1253,7 @@ dtoi2(PG_FUNCTION_ARGS)
/* Range check */
if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT16(num)))
- ereport(ERROR,
+ ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
@@ -1298,7 +1302,7 @@ ftoi4(PG_FUNCTION_ARGS)
/* Range check */
if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT32(num)))
- ereport(ERROR,
+ ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
@@ -1323,7 +1327,7 @@ ftoi2(PG_FUNCTION_ARGS)
/* Range check */
if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT16(num)))
- ereport(ERROR,
+ ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 9dd5889f34..4b9a762067 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -1307,7 +1307,7 @@ dtoi8(PG_FUNCTION_ARGS)
/* Range check */
if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
- ereport(ERROR,
+ ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -1342,7 +1342,7 @@ ftoi8(PG_FUNCTION_ARGS)
/* Range check */
if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
- ereport(ERROR,
+ ereturn(fcinfo->context, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index c9233565d5..cf498627a9 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -1261,7 +1261,8 @@ numeric (PG_FUNCTION_ARGS)
*/
if (NUMERIC_IS_SPECIAL(num))
{
- (void) apply_typmod_special(num, typmod, NULL);
+ if (!apply_typmod_special(num, typmod, fcinfo->context))
+ PG_RETURN_NULL();
PG_RETURN_NUMERIC(duplicate_numeric(num));
}
@@ -4564,7 +4565,22 @@ numeric_int4(PG_FUNCTION_ARGS)
{
Numeric num = PG_GETARG_NUMERIC(0);
- PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
+ if (likely(fcinfo->context == NULL))
+ PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
+ else
+ {
+ bool has_error;
+ int32 result;
+ Node *escontext = fcinfo->context;
+
+ result = numeric_int4_opt_error(num, &has_error);
+ if (has_error)
+ ereturn(escontext, (Datum) 0,
+ errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range"));
+
+ PG_RETURN_INT32(result);
+ }
}
/*
@@ -4652,7 +4668,22 @@ numeric_int8(PG_FUNCTION_ARGS)
{
Numeric num = PG_GETARG_NUMERIC(0);
- PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
+ if (likely(fcinfo->context == NULL))
+ PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
+ else
+ {
+ bool has_error;
+ int64 result;
+ Node *escontext = fcinfo->context;
+
+ result = numeric_int8_opt_error(num, &has_error);
+ if (has_error)
+ ereturn(escontext, (Datum) 0,
+ errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range"));
+
+ PG_RETURN_INT64(result);
+ }
}
@@ -4669,6 +4700,7 @@ Datum
numeric_int2(PG_FUNCTION_ARGS)
{
Numeric num = PG_GETARG_NUMERIC(0);
+ Node *escontext = fcinfo->context;
NumericVar x;
int64 val;
int16 result;
@@ -4676,11 +4708,11 @@ numeric_int2(PG_FUNCTION_ARGS)
if (NUMERIC_IS_SPECIAL(num))
{
if (NUMERIC_IS_NAN(num))
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot convert NaN to %s", "smallint")));
else
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot convert infinity to %s", "smallint")));
}
@@ -4689,12 +4721,12 @@ numeric_int2(PG_FUNCTION_ARGS)
init_var_from_num(num, &x);
if (!numericvar_to_int64(&x, &val))
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
if (unlikely(val < PG_INT16_MIN) || unlikely(val > PG_INT16_MAX))
- ereport(ERROR,
+ ereturn(escontext, (Datum) 0,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
@@ -4759,10 +4791,14 @@ numeric_float8(PG_FUNCTION_ARGS)
tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(num)));
-
- result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
-
- pfree(tmp);
+ if (!DirectInputFunctionCallSafe(float8in, tmp,
+ InvalidOid, -1,
+ (Node *) fcinfo->context,
+ &result))
+ {
+ pfree(tmp);
+ PG_RETURN_NULL();
+ }
PG_RETURN_DATUM(result);
}
@@ -4854,7 +4890,14 @@ numeric_float4(PG_FUNCTION_ARGS)
tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
NumericGetDatum(num)));
- result = DirectFunctionCall1(float4in, CStringGetDatum(tmp));
+ if (!DirectInputFunctionCallSafe(float4in, tmp,
+ InvalidOid, -1,
+ (Node *) fcinfo->context,
+ &result))
+ {
+ pfree(tmp);
+ PG_RETURN_NULL();
+ }
pfree(tmp);
--
2.34.1