Skip to content

Commit d4f7986

Browse files
committed
Fix copy-paste error in datum_to_jsonb_internal()
Commit 3c152a2 mistakenly repeated JSONTYPE_JSON in a condition, omitting JSONTYPE_CAST. As a result, datum_to_jsonb_internal() failed to reject inputs that were casts (e.g., from an enum to json as in the example below) when used as keys in JSON constructors. This led to a crash in cases like: SELECT JSON_OBJECT('happy'::mood: '123'::jsonb); where 'happy'::mood is implicitly cast to json. The missing check meant such casted values weren’t properly rejected as invalid (non-scalar) JSON keys. Reported-by: Maciek Sakrejda <[email protected]> Reviewed-by: Tender Wang <[email protected]> Reviewed-by: Alvaro Herrera <[email protected]> Reviewed-by: Maciek Sakrejda <[email protected]> Discussion: https://postgr.es/m/CADXhmgTJtJZK9A3Na_ry+Xrq-ghjcejBRhcRMzWZvbd__QdgJA@mail.gmail.com Backpatch-through: 17
1 parent 4ecdd41 commit d4f7986

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

src/backend/utils/adt/jsonb.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
657657
tcategory == JSONTYPE_COMPOSITE ||
658658
tcategory == JSONTYPE_JSON ||
659659
tcategory == JSONTYPE_JSONB ||
660-
tcategory == JSONTYPE_JSON))
660+
tcategory == JSONTYPE_CAST))
661661
{
662662
ereport(ERROR,
663663
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),

src/test/regress/expected/sqljson.out

+12
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,18 @@ SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, 4: NULL, '5': 'a' ABSENT ON NULL WIT
573573
{"1": 1, "3": 1, "5": "a"}
574574
(1 row)
575575

576+
-- BUG: https://postgr.es/m/CADXhmgTJtJZK9A3Na_ry%2BXrq-ghjcejBRhcRMzWZvbd__QdgJA%40mail.gmail.com
577+
-- datum_to_jsonb_internal() didn't catch keys that are casts instead of a simple scalar
578+
CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral');
579+
CREATE FUNCTION mood_to_json(mood) RETURNS json AS $$
580+
SELECT to_json($1::text);
581+
$$ LANGUAGE sql IMMUTABLE;
582+
CREATE CAST (mood AS json) WITH FUNCTION mood_to_json(mood) AS IMPLICIT;
583+
SELECT JSON_OBJECT('happy'::mood: '123'::jsonb);
584+
ERROR: key value must be scalar, not array, composite, or json
585+
DROP CAST (mood AS json);
586+
DROP FUNCTION mood_to_json;
587+
DROP TYPE mood;
576588
-- JSON_ARRAY()
577589
SELECT JSON_ARRAY();
578590
json_array

src/test/regress/sql/sqljson.sql

+11
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITH UNIQUE RETURNING
152152
SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITHOUT UNIQUE RETURNING jsonb);
153153
SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, 4: NULL, '5': 'a' ABSENT ON NULL WITH UNIQUE RETURNING jsonb);
154154

155+
-- BUG: https://postgr.es/m/CADXhmgTJtJZK9A3Na_ry%2BXrq-ghjcejBRhcRMzWZvbd__QdgJA%40mail.gmail.com
156+
-- datum_to_jsonb_internal() didn't catch keys that are casts instead of a simple scalar
157+
CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral');
158+
CREATE FUNCTION mood_to_json(mood) RETURNS json AS $$
159+
SELECT to_json($1::text);
160+
$$ LANGUAGE sql IMMUTABLE;
161+
CREATE CAST (mood AS json) WITH FUNCTION mood_to_json(mood) AS IMPLICIT;
162+
SELECT JSON_OBJECT('happy'::mood: '123'::jsonb);
163+
DROP CAST (mood AS json);
164+
DROP FUNCTION mood_to_json;
165+
DROP TYPE mood;
155166

156167
-- JSON_ARRAY()
157168
SELECT JSON_ARRAY();

0 commit comments

Comments
 (0)