Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3587cbc

Browse files
committed
Fix NULL handling in datum_to_jsonb().
The function failed to adhere to its specification that the "tcategory" argument should not be examined when the input value is NULL. This resulted in a crash in some cases. Per bug #13680 from Boyko Yordanov. In passing, re-pgindent some recent changes in jsonb.c, and fix a rather ungrammatical comment. Diagnosis and patch by Michael Paquier, cosmetic changes by me
1 parent 08fbad0 commit 3587cbc

File tree

3 files changed

+28
-12
lines changed

3 files changed

+28
-12
lines changed

src/backend/utils/adt/jsonb.c

+15-12
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ typedef enum /* type categories for datum_to_jsonb */
6161

6262
typedef struct JsonbAggState
6363
{
64-
JsonbInState *res;
65-
JsonbTypeCategory key_category;
66-
Oid key_output_func;
67-
JsonbTypeCategory val_category;
68-
Oid val_output_func;
64+
JsonbInState *res;
65+
JsonbTypeCategory key_category;
66+
Oid key_output_func;
67+
JsonbTypeCategory val_category;
68+
Oid val_output_func;
6969
} JsonbAggState;
7070

7171
static inline Datum jsonb_from_cstring(char *json, int len);
@@ -714,6 +714,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
714714

715715
check_stack_depth();
716716

717+
/* Convert val to a JsonbValue in jb (in most cases) */
717718
if (is_null)
718719
{
719720
Assert(!key_scalar);
@@ -936,8 +937,10 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
936937
break;
937938
}
938939
}
939-
if (tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST &&
940-
!scalar_jsonb)
940+
941+
/* Now insert jb into result, unless we did it recursively */
942+
if (!is_null && !scalar_jsonb &&
943+
tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
941944
{
942945
/* work has been done recursively */
943946
return;
@@ -1607,8 +1610,7 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
16071610

16081611
if (PG_ARGISNULL(0))
16091612
{
1610-
1611-
Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1613+
Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
16121614

16131615
if (arg_type == InvalidOid)
16141616
ereport(ERROR,
@@ -1762,7 +1764,7 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
17621764

17631765
if (PG_ARGISNULL(0))
17641766
{
1765-
Oid arg_type;
1767+
Oid arg_type;
17661768

17671769
oldcontext = MemoryContextSwitchTo(aggcontext);
17681770
state = palloc(sizeof(JsonbAggState));
@@ -1950,8 +1952,9 @@ jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
19501952
/*
19511953
* We need to do a shallow clone of the argument's res field in case the
19521954
* final function is called more than once, so we avoid changing the
1953-
* it. A shallow clone is sufficient as we aren't going to change any of
1954-
* the values, just add the final object end marker.
1955+
* aggregate state value. A shallow clone is sufficient as we aren't
1956+
* going to change any of the values, just add the final object end
1957+
* marker.
19551958
*/
19561959

19571960
result.parseState = clone_parse_state(arg->res->parseState);

src/test/regress/expected/jsonb.out

+9
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,15 @@ SELECT jsonb_build_object(json '{"a":1,"b":2}', 3);
13621362
ERROR: key value must be scalar, not array, composite or json
13631363
SELECT jsonb_build_object('{1,2,3}'::int[], 3);
13641364
ERROR: key value must be scalar, not array, composite or json
1365+
-- handling of NULL values
1366+
SELECT jsonb_object_agg(1, NULL::jsonb);
1367+
jsonb_object_agg
1368+
------------------
1369+
{"1": null}
1370+
(1 row)
1371+
1372+
SELECT jsonb_object_agg(NULL, '{"a":1}');
1373+
ERROR: field name must not be null
13651374
CREATE TEMP TABLE foo (serial_num int, name text, type text);
13661375
INSERT INTO foo VALUES (847001,'t15','GE1043');
13671376
INSERT INTO foo VALUES (847002,'t16','GE1043');

src/test/regress/sql/jsonb.sql

+4
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,10 @@ SELECT jsonb_build_object(json '{"a":1,"b":2}', 3);
330330

331331
SELECT jsonb_build_object('{1,2,3}'::int[], 3);
332332

333+
-- handling of NULL values
334+
SELECT jsonb_object_agg(1, NULL::jsonb);
335+
SELECT jsonb_object_agg(NULL, '{"a":1}');
336+
333337
CREATE TEMP TABLE foo (serial_num int, name text, type text);
334338
INSERT INTO foo VALUES (847001,'t15','GE1043');
335339
INSERT INTO foo VALUES (847002,'t16','GE1043');

0 commit comments

Comments
 (0)