From fed4f75d0a2a77c99eebcd6351ff099d385587bf Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Thu, 9 Oct 2025 19:09:53 +0800
Subject: [PATCH v7 02/20] error safe for casting bit/varbit to other types per
 pg_cast

select castsource::regtype, casttarget::regtype, castfunc,
       castcontext,castmethod, pp.prosrc, pp.proname
from pg_cast pc join pg_proc pp on pp.oid = pc.castfunc
where pc.castfunc > 0 and (castsource::regtype ='bit'::regtype or
castsource::regtype ='varbit'::regtype)
order by castsource::regtype;

 castsource  | casttarget  | castfunc | castcontext | castmethod |  prosrc   | proname
-------------+-------------+----------+-------------+------------+-----------+---------
 bit         | bigint      |     2076 | e           | f          | bittoint8 | int8
 bit         | integer     |     1684 | e           | f          | bittoint4 | int4
 bit         | bit         |     1685 | i           | f          | bit       | bit
 bit varying | bit varying |     1687 | i           | f          | varbit    | varbit
(4 rows)

discussion: https://postgr.es/m/CADkLM=fv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ@mail.gmail.com
---
 src/backend/utils/adt/varbit.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index 205a67dafc5..bfcea18f4b2 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -401,11 +401,15 @@ bit(PG_FUNCTION_ARGS)
 		PG_RETURN_VARBIT_P(arg);
 
 	if (!isExplicit)
-		ereport(ERROR,
+	{
+		errsave(fcinfo->context,
 				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
 				 errmsg("bit string length %d does not match type bit(%d)",
 						VARBITLEN(arg), len)));
 
+		PG_RETURN_NULL();
+	}
+
 	rlen = VARBITTOTALLEN(len);
 	/* set to 0 so that string is zero-padded */
 	result = (VarBit *) palloc0(rlen);
@@ -752,11 +756,15 @@ varbit(PG_FUNCTION_ARGS)
 		PG_RETURN_VARBIT_P(arg);
 
 	if (!isExplicit)
-		ereport(ERROR,
+	{
+		errsave(fcinfo->context,
 				(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
 				 errmsg("bit string too long for type bit varying(%d)",
 						len)));
 
+		PG_RETURN_NULL();
+	}
+
 	rlen = VARBITTOTALLEN(len);
 	result = (VarBit *) palloc(rlen);
 	SET_VARSIZE(result, rlen);
@@ -1591,10 +1599,14 @@ bittoint4(PG_FUNCTION_ARGS)
 
 	/* Check that the bit string is not too long */
 	if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
-		ereport(ERROR,
+	{
+		errsave(fcinfo->context,
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("integer out of range")));
 
+		PG_RETURN_NULL();
+	}
+
 	result = 0;
 	for (r = VARBITS(arg); r < VARBITEND(arg); r++)
 	{
@@ -1671,10 +1683,14 @@ bittoint8(PG_FUNCTION_ARGS)
 
 	/* Check that the bit string is not too long */
 	if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
-		ereport(ERROR,
+	{
+		errsave(fcinfo->context,
 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 				 errmsg("bigint out of range")));
 
+		PG_RETURN_NULL();
+	}
+
 	result = 0;
 	for (r = VARBITS(arg); r < VARBITEND(arg); r++)
 	{
-- 
2.34.1

