Disallow invalid path elements in jsonb_set
authorAndrew Dunstan <andrew@dunslane.net>
Sun, 4 Oct 2015 17:28:16 +0000 (13:28 -0400)
committerAndrew Dunstan <andrew@dunslane.net>
Sun, 4 Oct 2015 17:28:16 +0000 (13:28 -0400)
Null path elements and, where the object is an array, invalid integer
elements now cause an error.

Incorrect behaviour noted by Thom Brown, patch from Dmitry Dolgov.

Backpatch to 9.5 where jsonb_set was introduced

src/backend/utils/adt/jsonfuncs.c
src/test/regress/expected/jsonb.out
src/test/regress/expected/jsonb_1.out
src/test/regress/sql/jsonb.sql

index 154a8837e1738d578c1ea88a23e1b35cd7e57c78..01b6bb0a483a7762d940aba1b67ff8c4b89a516b 100644 (file)
@@ -3724,6 +3724,9 @@ setPath(JsonbIterator **it, Datum *path_elems,
    JsonbValue *res = NULL;
    int         r;
 
+   if (path_nulls[level])
+       elog(ERROR, "path element at the position %d is NULL", level + 1);
+
    r = JsonbIteratorNext(it, &v, false);
 
    switch (r)
@@ -3875,7 +3878,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
        lindex = strtol(c, &badp, 10);
        if (errno != 0 || badp == c || *badp != '\0' || lindex > INT_MAX ||
            lindex < INT_MIN)
-           idx = nelems;
+           elog(ERROR, "path element at the position %d is not an integer", level + 1);
        else
            idx = lindex;
    }
index 82d1b69bfaa18a4cd12bf9dd5a2818994a4b65da..6da5a151d726fd6231d6e460ac9b43a6fe546c60 100644 (file)
@@ -3127,11 +3127,7 @@ select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::j
 (1 row)
 
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '[1,2,3]');
-                              jsonb_set                              
----------------------------------------------------------------------
- {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
-(1 row)
-
+ERROR:  path element at the position 2 is NULL
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '{"1": 2}');
                                 jsonb_set                                
 -------------------------------------------------------------------------
@@ -3151,11 +3147,7 @@ select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::j
 (1 row)
 
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '{"1": 2}');
-                              jsonb_set                              
----------------------------------------------------------------------
- {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
-(1 row)
-
+ERROR:  path element at the position 2 is NULL
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '"test"');
                                 jsonb_set                                 
 --------------------------------------------------------------------------
@@ -3199,11 +3191,7 @@ select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{
 (1 row)
 
 select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{b,-1e}'; -- invalid array subscript
-                              ?column?                               
----------------------------------------------------------------------
- {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
-(1 row)
-
+ERROR:  path element at the position 2 is not an integer
 select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{d,1,0}';
                              ?column?                             
 ------------------------------------------------------------------
@@ -3331,3 +3319,9 @@ select jsonb_set('[]','{-99}','{"foo":123}');
  [{"foo": 123}]
 (1 row)
 
+select jsonb_set('{"a": [1, 2, 3]}', '{a, non_integer}', '"new_value"');
+ERROR:  path element at the position 2 is not an integer
+select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, non_integer}', '"new_value"');
+ERROR:  path element at the position 3 is not an integer
+select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, NULL}', '"new_value"');
+ERROR:  path element at the position 3 is NULL
index 2cbc0c79bba9060d98d1a164b8328cc535c68698..39e7b1ff5707b933279915f64f35e905335d46c8 100644 (file)
@@ -3127,11 +3127,7 @@ select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::j
 (1 row)
 
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '[1,2,3]');
-                              jsonb_set                              
----------------------------------------------------------------------
- {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
-(1 row)
-
+ERROR:  path element at the position 2 is NULL
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '{"1": 2}');
                                 jsonb_set                                
 -------------------------------------------------------------------------
@@ -3151,11 +3147,7 @@ select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::j
 (1 row)
 
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '{"1": 2}');
-                              jsonb_set                              
----------------------------------------------------------------------
- {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
-(1 row)
-
+ERROR:  path element at the position 2 is NULL
 select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '"test"');
                                 jsonb_set                                 
 --------------------------------------------------------------------------
@@ -3199,11 +3191,7 @@ select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{
 (1 row)
 
 select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{b,-1e}'; -- invalid array subscript
-                              ?column?                               
----------------------------------------------------------------------
- {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
-(1 row)
-
+ERROR:  path element at the position 2 is not an integer
 select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{d,1,0}';
                              ?column?                             
 ------------------------------------------------------------------
@@ -3331,3 +3319,9 @@ select jsonb_set('[]','{-99}','{"foo":123}');
  [{"foo": 123}]
 (1 row)
 
+select jsonb_set('{"a": [1, 2, 3]}', '{a, non_integer}', '"new_value"');
+ERROR:  path element at the position 2 is not an integer
+select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, non_integer}', '"new_value"');
+ERROR:  path element at the position 3 is not an integer
+select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, NULL}', '"new_value"');
+ERROR:  path element at the position 3 is NULL
index cb03ada1731d9461586bed21e1fcf47120d15ff4..b1a0764cfaaca893c6ecf0b69398a72669a88b2b 100644 (file)
@@ -816,3 +816,6 @@ select jsonb_set('{}','{x}','{"foo":123}');
 select jsonb_set('[]','{0}','{"foo":123}');
 select jsonb_set('[]','{99}','{"foo":123}');
 select jsonb_set('[]','{-99}','{"foo":123}');
+select jsonb_set('{"a": [1, 2, 3]}', '{a, non_integer}', '"new_value"');
+select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, non_integer}', '"new_value"');
+select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, NULL}', '"new_value"');