Skip to content

Commit 112fdb3

Browse files
committed
Fix finalization for json_objectagg and friends
Commit f4fb45d misguidedly tried to free some state during aggregate finalization for json_objectagg. This resulted in attempts to access freed memory, especially when the function is used as a window function. Commit 4eb9798 attempted to ameliorate that, but in fact it should just be ripped out, which is done here. Also add some regression tests for json_objectagg in various flavors as a window function. Original report from Jaime Casanova, diagnosis by Andres Freund. Discussion: https://postgr.es/m/YkfeMNYRCGhySKyg@ahch-to
1 parent a038679 commit 112fdb3

File tree

3 files changed

+53
-12
lines changed

3 files changed

+53
-12
lines changed

src/backend/utils/adt/json.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,13 +1002,6 @@ json_unique_builder_init(JsonUniqueBuilderState *cxt)
10021002
cxt->skipped_keys.data = NULL;
10031003
}
10041004

1005-
static void
1006-
json_unique_builder_clean(JsonUniqueBuilderState *cxt)
1007-
{
1008-
if (cxt->skipped_keys.data)
1009-
resetStringInfo(&cxt->skipped_keys);
1010-
}
1011-
10121005
/* On-demand initialization of skipped_keys StringInfo structure */
10131006
static StringInfo
10141007
json_unique_builder_get_skipped_keys(JsonUniqueBuilderState *cxt)
@@ -1216,8 +1209,6 @@ json_object_agg_finalfn(PG_FUNCTION_ARGS)
12161209
if (state == NULL)
12171210
PG_RETURN_NULL();
12181211

1219-
json_unique_builder_clean(&state->unique_check);
1220-
12211212
/* Else return state with appropriate object terminator added */
12221213
PG_RETURN_TEXT_P(catenate_stringinfo_string(state->str, " }"));
12231214
}
@@ -1324,9 +1315,6 @@ json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
13241315

13251316
appendStringInfoChar(result, '}');
13261317

1327-
if (unique_keys)
1328-
json_unique_builder_clean(&unique_check);
1329-
13301318
return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
13311319
}
13321320

src/test/regress/expected/sqljson.out

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,41 @@ SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json);
959959
CREATE OR REPLACE VIEW public.json_object_view AS
960960
SELECT JSON_OBJECT('foo' : '1'::text FORMAT JSON, 'bar' : 'baz'::text RETURNING json) AS "json_object"
961961
DROP VIEW json_object_view;
962+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
963+
FROM (VALUES (1,1), (2,2)) a(k,v);
964+
a | json_objectagg
965+
---------------+----------------------
966+
{"k":1,"v":1} | { "1" : 1 }
967+
{"k":2,"v":2} | { "1" : 1, "2" : 2 }
968+
(2 rows)
969+
970+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
971+
FROM (VALUES (1,1), (1,2), (2,2)) a(k,v);
972+
ERROR: duplicate JSON key "1"
973+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL WITH UNIQUE KEYS)
974+
OVER (ORDER BY k)
975+
FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
976+
ERROR: duplicate JSON key "1"
977+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
978+
OVER (ORDER BY k)
979+
FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
980+
a | json_objectagg
981+
------------------+----------------------
982+
{"k":1,"v":1} | { "1" : 1 }
983+
{"k":1,"v":null} | { "1" : 1 }
984+
{"k":2,"v":2} | { "1" : 1, "2" : 2 }
985+
(3 rows)
986+
987+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
988+
OVER (ORDER BY k RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
989+
FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
990+
a | json_objectagg
991+
------------------+----------------------
992+
{"k":1,"v":1} | { "1" : 1, "2" : 2 }
993+
{"k":1,"v":null} | { "1" : 1, "2" : 2 }
994+
{"k":2,"v":2} | { "1" : 1, "2" : 2 }
995+
(3 rows)
996+
962997
-- Test JSON_ARRAY deparsing
963998
EXPLAIN (VERBOSE, COSTS OFF)
964999
SELECT JSON_ARRAY('1' FORMAT JSON, 2 RETURNING json);

src/test/regress/sql/sqljson.sql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,24 @@ SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json);
292292

293293
DROP VIEW json_object_view;
294294

295+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
296+
FROM (VALUES (1,1), (2,2)) a(k,v);
297+
298+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
299+
FROM (VALUES (1,1), (1,2), (2,2)) a(k,v);
300+
301+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL WITH UNIQUE KEYS)
302+
OVER (ORDER BY k)
303+
FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
304+
305+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
306+
OVER (ORDER BY k)
307+
FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
308+
309+
SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
310+
OVER (ORDER BY k RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
311+
FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
312+
295313
-- Test JSON_ARRAY deparsing
296314
EXPLAIN (VERBOSE, COSTS OFF)
297315
SELECT JSON_ARRAY('1' FORMAT JSON, 2 RETURNING json);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy