]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix jsonpath .split_part() to honor silent mode
authorMichael Paquier <michael@paquier.xyz>
Thu, 14 May 2026 07:02:07 +0000 (16:02 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 14 May 2026 07:02:07 +0000 (16:02 +0900)
The jsonpath .split_part() method passed its field-position argument
through numeric_int4(), that can fail hard if called directly.

This commit switches the code to use numeric_int4_safe() with an error
context for soft reporting, so as the overflow and zero field-position
cases can be handled in silent mode.

Oversight in bd4f879a9cdd.

Author:  Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/FCF996D0-580B-431C-8DE1-A540C58E444C@gmail.com

src/backend/utils/adt/jsonpath_exec.c
src/test/regress/expected/jsonb_jsonpath.out
src/test/regress/sql/jsonb_jsonpath.sql

index 0ec9b4df2efe470f1b5e6401ce2f5a5b34bb6973..6cc2acb4254234e4c32cdef527fca555c14153e0 100644 (file)
@@ -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:
index afa6c4cb5294b7a7de9c9158c6470ae9056b753f..81efebc3d0fd48258d5860fe49a427a733b3da6c 100644 (file)
@@ -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 
index d3a38c577918b20c12fcb32e41011af486543328..c1f4ab5422e0d614fbadf520e9af2373733f7684 100644 (file)
@@ -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()');