From f75ae350b7a1b3398cffda315d00943890c92292 Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" 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 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)