From e2f289e5b9b82acaf1523fda827e71b8fc8bd549 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 24 Mar 2026 12:01:05 +0100 Subject: [PATCH] Make many cast functions error safe This adjusts many C functions underlying casts to support soft errors. This is in preparation for a future feature where conversion errors in casts can be caught. This patch covers cast functions that can be adjusted easily by changing ereport to ereturn or making other light changes. The underlying helper functions were already changed to support soft errors some time ago as part of soft error support in type input functions. Other casts and types will require some more work and are being kept as separate patches. Author: jian he Reviewed-by: Amul Sul Reviewed-by: Corey Huinker Discussion: https://www.postgresql.org/message-id/flat/CADkLM%3Dfv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ%40mail.gmail.com --- src/backend/executor/execExprInterp.c | 2 +- src/backend/utils/adt/bytea.c | 8 ++-- src/backend/utils/adt/char.c | 2 +- src/backend/utils/adt/date.c | 35 ++++++++------- src/backend/utils/adt/float.c | 8 ++-- src/backend/utils/adt/int.c | 2 +- src/backend/utils/adt/int8.c | 10 ++--- src/backend/utils/adt/mac8.c | 2 +- src/backend/utils/adt/network.c | 2 +- src/backend/utils/adt/numeric.c | 64 ++++++++++++++++++++------- src/backend/utils/adt/timestamp.c | 23 +++++++--- src/backend/utils/adt/varbit.c | 8 ++-- src/backend/utils/adt/varchar.c | 4 +- src/backend/utils/adt/xml.c | 12 +++-- src/include/utils/xml.h | 2 +- 15 files changed, 116 insertions(+), 68 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 53ae0205702..43116431edf 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -4548,7 +4548,7 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op) *op->resvalue = PointerGetDatum(xmlparse(data, xexpr->xmloption, - preserve_whitespace)); + preserve_whitespace, NULL)); *op->resnull = false; } break; diff --git a/src/backend/utils/adt/bytea.c b/src/backend/utils/adt/bytea.c index 39ed04ddae8..f6e3266ac32 100644 --- a/src/backend/utils/adt/bytea.c +++ b/src/backend/utils/adt/bytea.c @@ -1256,7 +1256,7 @@ bytea_int2(PG_FUNCTION_ARGS) /* Check that the byte array is not too long */ if (len > sizeof(result)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range")); @@ -1281,7 +1281,7 @@ bytea_int4(PG_FUNCTION_ARGS) /* Check that the byte array is not too long */ if (len > sizeof(result)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range")); @@ -1306,7 +1306,7 @@ bytea_int8(PG_FUNCTION_ARGS) /* Check that the byte array is not too long */ if (len > sizeof(result)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range")); @@ -1351,7 +1351,7 @@ bytea_uuid(PG_FUNCTION_ARGS) pg_uuid_t *uuid; if (len != UUID_LEN) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid input length for type %s", "uuid"), errdetail("Expected %d bytes, got %d.", UUID_LEN, len))); diff --git a/src/backend/utils/adt/char.c b/src/backend/utils/adt/char.c index 3e4def68fe4..698863924ee 100644 --- a/src/backend/utils/adt/char.c +++ b/src/backend/utils/adt/char.c @@ -192,7 +192,7 @@ i4tochar(PG_FUNCTION_ARGS) int32 arg1 = PG_GETARG_INT32(0); if (arg1 < SCHAR_MIN || arg1 > SCHAR_MAX) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("\"char\" out of range"))); diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index 87c063fa0cd..71ea048d251 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -722,15 +722,6 @@ date2timestamptz_safe(DateADT dateVal, Node *escontext) return result; } -/* - * Promote date to timestamptz, throwing error for overflow. - */ -static TimestampTz -date2timestamptz(DateADT dateVal) -{ - return date2timestamptz_safe(dateVal, NULL); -} - /* * date2timestamp_no_overflow * @@ -1315,7 +1306,9 @@ date_timestamp(PG_FUNCTION_ARGS) DateADT dateVal = PG_GETARG_DATEADT(0); Timestamp result; - result = date2timestamp(dateVal); + result = date2timestamp_safe(dateVal, fcinfo->context); + if (SOFT_ERROR_OCCURRED(fcinfo->context)) + PG_RETURN_NULL(); PG_RETURN_TIMESTAMP(result); } @@ -1329,7 +1322,10 @@ timestamp_date(PG_FUNCTION_ARGS) Timestamp timestamp = PG_GETARG_TIMESTAMP(0); DateADT result; - result = timestamp2date_safe(timestamp, NULL); + result = timestamp2date_safe(timestamp, fcinfo->context); + if (SOFT_ERROR_OCCURRED(fcinfo->context)) + PG_RETURN_NULL(); + PG_RETURN_DATEADT(result); } @@ -1388,7 +1384,9 @@ date_timestamptz(PG_FUNCTION_ARGS) DateADT dateVal = PG_GETARG_DATEADT(0); TimestampTz result; - result = date2timestamptz(dateVal); + result = date2timestamptz_safe(dateVal, fcinfo->context); + if (SOFT_ERROR_OCCURRED(fcinfo->context)) + PG_RETURN_NULL(); PG_RETURN_TIMESTAMP(result); } @@ -1403,7 +1401,10 @@ timestamptz_date(PG_FUNCTION_ARGS) TimestampTz timestamp = PG_GETARG_TIMESTAMP(0); DateADT result; - result = timestamptz2date_safe(timestamp, NULL); + result = timestamptz2date_safe(timestamp, fcinfo->context); + if (SOFT_ERROR_OCCURRED(fcinfo->args)) + PG_RETURN_NULL(); + PG_RETURN_DATEADT(result); } @@ -2002,7 +2003,7 @@ timestamp_time(PG_FUNCTION_ARGS) PG_RETURN_NULL(); if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); @@ -2033,7 +2034,7 @@ timestamptz_time(PG_FUNCTION_ARGS) PG_RETURN_NULL(); if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); @@ -2103,7 +2104,7 @@ interval_time(PG_FUNCTION_ARGS) TimeADT result; if (INTERVAL_NOT_FINITE(span)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("cannot convert infinite interval to time"))); @@ -2952,7 +2953,7 @@ timestamptz_timetz(PG_FUNCTION_ARGS) PG_RETURN_NULL(); if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index f77f73820d7..a06fef42901 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -1241,7 +1241,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"))); @@ -1266,7 +1266,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"))); @@ -1315,7 +1315,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"))); @@ -1340,7 +1340,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/int.c b/src/backend/utils/adt/int.c index ff54d50ea9d..4c894a49d5d 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -379,7 +379,7 @@ i4toi2(PG_FUNCTION_ARGS) int32 arg1 = PG_GETARG_INT32(0); if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX)) - 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 6c8fb7b7275..19bb30f2d0f 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -1251,7 +1251,7 @@ int84(PG_FUNCTION_ARGS) int64 arg = PG_GETARG_INT64(0); if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); @@ -1272,7 +1272,7 @@ int82(PG_FUNCTION_ARGS) int64 arg = PG_GETARG_INT64(0); if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); @@ -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"))); @@ -1355,7 +1355,7 @@ i8tooid(PG_FUNCTION_ARGS) int64 arg = PG_GETARG_INT64(0); if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("OID out of range"))); diff --git a/src/backend/utils/adt/mac8.c b/src/backend/utils/adt/mac8.c index c1bf9fd5783..0425ea473a5 100644 --- a/src/backend/utils/adt/mac8.c +++ b/src/backend/utils/adt/mac8.c @@ -550,7 +550,7 @@ macaddr8tomacaddr(PG_FUNCTION_ARGS) result = palloc0_object(macaddr); if ((addr->d != 0xFF) || (addr->e != 0xFE)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("macaddr8 data out of range to convert to macaddr"), errhint("Only addresses that have FF and FE as values in the " diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index 3a2002097dd..c7e0828764e 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -1137,7 +1137,7 @@ network_show(PG_FUNCTION_ARGS) if (pg_inet_net_ntop(ip_family(ip), ip_addr(ip), ip_maxbits(ip), tmp, sizeof(tmp)) == NULL) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("could not format inet value: %m"))); diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index d25b8ad505d..cb23dfe9b95 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -1244,7 +1244,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)); } @@ -1295,8 +1296,9 @@ numeric (PG_FUNCTION_ARGS) init_var(&var); set_var_from_num(num, &var); - (void) apply_typmod(&var, typmod, NULL); - new = make_result(&var); + if (!apply_typmod(&var, typmod, fcinfo->context)) + PG_RETURN_NULL(); + new = make_result_safe(&var, fcinfo->context); free_var(&var); @@ -3018,7 +3020,10 @@ numeric_mul(PG_FUNCTION_ARGS) Numeric num2 = PG_GETARG_NUMERIC(1); Numeric res; - res = numeric_mul_safe(num1, num2, NULL); + res = numeric_mul_safe(num1, num2, fcinfo->context); + + if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context))) + PG_RETURN_NULL(); PG_RETURN_NUMERIC(res); } @@ -4393,8 +4398,14 @@ Datum numeric_int4(PG_FUNCTION_ARGS) { Numeric num = PG_GETARG_NUMERIC(0); + int32 result; - PG_RETURN_INT32(numeric_int4_safe(num, NULL)); + result = numeric_int4_safe(num, fcinfo->context); + + if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context))) + PG_RETURN_NULL(); + + PG_RETURN_INT32(result); } /* @@ -4463,8 +4474,14 @@ Datum numeric_int8(PG_FUNCTION_ARGS) { Numeric num = PG_GETARG_NUMERIC(0); + int64 result; - PG_RETURN_INT64(numeric_int8_safe(num, NULL)); + result = numeric_int8_safe(num, fcinfo->context); + + if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context))) + PG_RETURN_NULL(); + + PG_RETURN_INT64(result); } @@ -4488,11 +4505,11 @@ numeric_int2(PG_FUNCTION_ARGS) if (NUMERIC_IS_SPECIAL(num)) { if (NUMERIC_IS_NAN(num)) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot convert NaN to %s", "smallint"))); else - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot convert infinity to %s", "smallint"))); } @@ -4501,12 +4518,12 @@ numeric_int2(PG_FUNCTION_ARGS) init_var_from_num(num, &x); if (!numericvar_to_int64(&x, &val)) - ereport(ERROR, + ereturn(fcinfo->context, (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(fcinfo->context, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); @@ -4542,7 +4559,8 @@ float8_numeric(PG_FUNCTION_ARGS) init_var(&result); /* Assume we need not worry about leading/trailing spaces */ - (void) set_var_from_str(buf, buf, &result, &endptr, NULL); + if (!set_var_from_str(buf, buf, &result, &endptr, fcinfo->context)) + PG_RETURN_NULL(); res = make_result(&result); @@ -4571,10 +4589,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); } @@ -4636,7 +4658,8 @@ float4_numeric(PG_FUNCTION_ARGS) init_var(&result); /* Assume we need not worry about leading/trailing spaces */ - (void) set_var_from_str(buf, buf, &result, &endptr, NULL); + if (!set_var_from_str(buf, buf, &result, &endptr, fcinfo->context)) + PG_RETURN_NULL(); res = make_result(&result); @@ -4666,7 +4689,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); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 50a73fd24ec..288d696be77 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -343,7 +343,8 @@ timestamp_scale(PG_FUNCTION_ARGS) result = timestamp; - AdjustTimestampForTypmod(&result, typmod, NULL); + if (!AdjustTimestampForTypmod(&result, typmod, fcinfo->context)) + PG_RETURN_NULL(); PG_RETURN_TIMESTAMP(result); } @@ -866,7 +867,8 @@ timestamptz_scale(PG_FUNCTION_ARGS) result = timestamp; - AdjustTimestampForTypmod(&result, typmod, NULL); + if (!AdjustTimestampForTypmod(&result, typmod, fcinfo->context)) + PG_RETURN_NULL(); PG_RETURN_TIMESTAMPTZ(result); } @@ -1325,7 +1327,8 @@ interval_scale(PG_FUNCTION_ARGS) result = palloc_object(Interval); *result = *interval; - AdjustIntervalForTypmod(result, typmod, NULL); + if (!AdjustIntervalForTypmod(result, typmod, fcinfo->context)) + PG_RETURN_NULL(); PG_RETURN_INTERVAL_P(result); } @@ -6421,8 +6424,13 @@ Datum timestamp_timestamptz(PG_FUNCTION_ARGS) { Timestamp timestamp = PG_GETARG_TIMESTAMP(0); + TimestampTz result; - PG_RETURN_TIMESTAMPTZ(timestamp2timestamptz(timestamp)); + result = timestamp2timestamptz_safe(timestamp, fcinfo->context); + if (SOFT_ERROR_OCCURRED(fcinfo->context)) + PG_RETURN_NULL(); + + PG_RETURN_TIMESTAMPTZ(result); } /* @@ -6484,8 +6492,13 @@ Datum timestamptz_timestamp(PG_FUNCTION_ARGS) { TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0); + Timestamp result; - PG_RETURN_TIMESTAMP(timestamptz2timestamp(timestamp)); + result = timestamptz2timestamp_safe(timestamp, fcinfo->context); + if (unlikely(SOFT_ERROR_OCCURRED(fcinfo->context))) + PG_RETURN_NULL(); + + PG_RETURN_TIMESTAMP(result); } /* diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c index 65ad1bfe18f..c46b5bae70d 100644 --- a/src/backend/utils/adt/varbit.c +++ b/src/backend/utils/adt/varbit.c @@ -401,7 +401,7 @@ bit(PG_FUNCTION_ARGS) PG_RETURN_VARBIT_P(arg); if (!isExplicit) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH), errmsg("bit string length %d does not match type bit(%d)", VARBITLEN(arg), len))); @@ -752,7 +752,7 @@ varbit(PG_FUNCTION_ARGS) PG_RETURN_VARBIT_P(arg); if (!isExplicit) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), errmsg("bit string too long for type bit varying(%d)", len))); @@ -1591,7 +1591,7 @@ bittoint4(PG_FUNCTION_ARGS) /* Check that the bit string is not too long */ if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE) - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); @@ -1671,7 +1671,7 @@ bittoint8(PG_FUNCTION_ARGS) /* Check that the bit string is not too long */ if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE) - 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/varchar.c b/src/backend/utils/adt/varchar.c index df305098130..a62e55eec19 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -307,7 +307,7 @@ bpchar(PG_FUNCTION_ARGS) { for (i = maxmblen; i < len; i++) if (s[i] != ' ') - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), errmsg("value too long for type character(%d)", maxlen))); @@ -634,7 +634,7 @@ varchar(PG_FUNCTION_ARGS) { for (i = maxmblen; i < len; i++) if (s_data[i] != ' ') - ereport(ERROR, + ereturn(fcinfo->context, (Datum) 0, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), errmsg("value too long for type character varying(%d)", maxlen))); diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 79f6cf7b4fa..2c7f778cfdb 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -660,7 +660,7 @@ texttoxml(PG_FUNCTION_ARGS) { text *data = PG_GETARG_TEXT_PP(0); - PG_RETURN_XML_P(xmlparse(data, xmloption, true)); + PG_RETURN_XML_P(xmlparse(data, xmloption, true, fcinfo->context)); } @@ -1029,14 +1029,18 @@ xmlelement(XmlExpr *xexpr, xmltype * -xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace) +xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, Node *escontext) { #ifdef USE_LIBXML xmlDocPtr doc; doc = xml_parse(data, xmloption_arg, preserve_whitespace, - GetDatabaseEncoding(), NULL, NULL, NULL); - xmlFreeDoc(doc); + GetDatabaseEncoding(), NULL, NULL, escontext); + if (doc) + xmlFreeDoc(doc); + + if (SOFT_ERROR_OCCURRED(escontext)) + return NULL; return (xmltype *) data; #else diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h index 023fdeb4531..ca266f448d6 100644 --- a/src/include/utils/xml.h +++ b/src/include/utils/xml.h @@ -73,7 +73,7 @@ extern xmltype *xmlconcat(List *args); extern xmltype *xmlelement(XmlExpr *xexpr, const Datum *named_argvalue, const bool *named_argnull, const Datum *argvalue, const bool *argnull); -extern xmltype *xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace); +extern xmltype *xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, Node *escontext); extern xmltype *xmlpi(const char *target, text *arg, bool arg_is_null, bool *result_is_null); extern xmltype *xmlroot(xmltype *data, text *version, int standalone); extern bool xml_is_document(xmltype *arg);