summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Dunstan <andrew@dunslane.net>2015-10-04 13:28:16 -0400
committerAndrew Dunstan <andrew@dunslane.net>2015-10-04 13:28:16 -0400
commit1edd4ec831458e10b524d1473a7de5791aa8753e (patch)
tree1b2f229c94932b0b92421e1b258b44f4f802cddf /src
parent6390c8c654d07c08686adbbc595a13d76b573653 (diff)
downloadpostgresql-1edd4ec831458e10b524d1473a7de5791aa8753e.tar.gz
Disallow invalid path elements in jsonb_set
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/jsonfuncs.c5
-rw-r--r--src/test/regress/expected/jsonb.out24
-rw-r--r--src/test/regress/expected/jsonb_1.out24
-rw-r--r--src/test/regress/sql/jsonb.sql3
4 files changed, 25 insertions, 31 deletions
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index 154a8837e1..01b6bb0a48 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -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;
}
diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out
index 82d1b69bfa..6da5a151d7 100644
--- a/src/test/regress/expected/jsonb.out
+++ b/src/test/regress/expected/jsonb.out
@@ -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
diff --git a/src/test/regress/expected/jsonb_1.out b/src/test/regress/expected/jsonb_1.out
index 2cbc0c79bb..39e7b1ff57 100644
--- a/src/test/regress/expected/jsonb_1.out
+++ b/src/test/regress/expected/jsonb_1.out
@@ -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
diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql
index cb03ada173..b1a0764cfa 100644
--- a/src/test/regress/sql/jsonb.sql
+++ b/src/test/regress/sql/jsonb.sql
@@ -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"');