From f75ae350b7a1b3398cffda315d00943890c92292 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Tue, 12 May 2026 09:54:35 +0800
Subject: [PATCH v1] Fix jsonpath .split_part() to honor silent mode

The jsonpath .split_part() method passed its field-position argument
through numeric_int4() and then called split_part() directly.  As a
result, int4 overflow and zero field-position errors were thrown outside
jsonpath's RETURN_ERROR() path, so they were not suppressed when
jsonpath functions were called with silent => true.

Fix this by converting the numeric argument with numeric_int4_safe() and
checking for a zero field position in jsonpath_exec.c, reporting both
errors through RETURN_ERROR().

Add regression tests for zero and out-of-range field positions, including
silent mode.

Author: Chao Li <lic@highgo.com>
Reviewed-by:
Discussion: https://postgr.es/m/
---
 src/backend/utils/adt/jsonpath_exec.c        | 19 ++++++++++++++++---
 src/test/regress/expected/jsonb_jsonpath.out | 14 ++++++++++++++
 src/test/regress/sql/jsonb_jsonpath.sql      |  4 ++++
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 0ec9b4df2ef..6cc2acb4254 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -3017,7 +3017,8 @@ executeStringInternalMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 		case jpiStrSplitPart:
 			{
 				char	   *from_str;
-				Numeric		n;
+				int32		n;
+				ErrorSaveContext escontext = {T_ErrorSaveContext};
 
 				jspGetLeftArg(jsp, &elem);
 				if (elem.type != jpiString)
@@ -3029,13 +3030,25 @@ executeStringInternalMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
 				if (elem.type != jpiNumeric)
 					elog(ERROR, "invalid jsonpath item type for .split_part()");
 
-				n = jspGetNumeric(&elem);
+				n = numeric_int4_safe(jspGetNumeric(&elem),
+									  (Node *) &escontext);
+				if (escontext.error_occurred)
+					RETURN_ERROR(ereport(ERROR,
+										 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+										 errmsg("field position of jsonpath item method .%s() is out of range for type integer",
+												jspOperationName(jsp->type))));
+
+				if (n == 0)
+					RETURN_ERROR(ereport(ERROR,
+										 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+										 errmsg("field position of jsonpath item method .%s() must not be zero",
+												jspOperationName(jsp->type))));
 
 				resStr = TextDatumGetCString(DirectFunctionCall3Coll(split_part,
 																	 DEFAULT_COLLATION_OID,
 																	 str,
 																	 CStringGetTextDatum(from_str),
-																	 DirectFunctionCall1(numeric_int4, NumericGetDatum(n))));
+																	 Int32GetDatum(n)));
 				break;
 			}
 		default:
diff --git a/src/test/regress/expected/jsonb_jsonpath.out b/src/test/regress/expected/jsonb_jsonpath.out
index afa6c4cb529..81efebc3d0f 100644
--- a/src/test/regress/expected/jsonb_jsonpath.out
+++ b/src/test/regress/expected/jsonb_jsonpath.out
@@ -3073,6 +3073,20 @@ select jsonb_path_query('"abc,def,ghi,jkl"', '$.split_part(",", -2)');
  "ghi"
 (1 row)
 
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)');
+ERROR:  field position of jsonpath item method .split_part() must not be zero
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)');
+ERROR:  field position of jsonpath item method .split_part() is out of range for type integer
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)', silent => true);
+ jsonb_path_query 
+------------------
+(0 rows)
+
 -- Test string methods play nicely together
 select jsonb_path_query('"hello world"', '$.replace("hello","bye").upper()');
  jsonb_path_query 
diff --git a/src/test/regress/sql/jsonb_jsonpath.sql b/src/test/regress/sql/jsonb_jsonpath.sql
index d3a38c57791..c1f4ab5422e 100644
--- a/src/test/regress/sql/jsonb_jsonpath.sql
+++ b/src/test/regress/sql/jsonb_jsonpath.sql
@@ -721,6 +721,10 @@ select jsonb_path_query('"hello world"', '$.replace("hello","bye") starts with "
 -- Test .split_part()
 select jsonb_path_query('"abc~@~def~@~ghi"', '$.split_part("~@~", 2)');
 select jsonb_path_query('"abc,def,ghi,jkl"', '$.split_part(",", -2)');
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)');
+select jsonb_path_query('"a,b"', '$.split_part(",", 0)', silent => true);
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)');
+select jsonb_path_query('"a,b"', '$.split_part(",", 2147483648)', silent => true);
 
 -- Test string methods play nicely together
 select jsonb_path_query('"hello world"', '$.replace("hello","bye").upper()');
-- 
2.50.1 (Apple Git-155)

