mirror of
https://github.com/postgres/postgres.git
synced 2025-12-19 17:02:53 +03:00
Fix jsonb_object_agg crash after eliminating null-valued pairs.
In commit b61aa76e4 I added an assumption in jsonb_object_agg_finalfn
that it'd be okay to apply uniqueifyJsonbObject repeatedly to a
JsonbValue. I should have studied that code more closely first,
because in skip_nulls mode it removed leading nulls by changing the
"pairs" array start pointer. This broke the data structure's
invariants in two ways: pairs no longer references a repalloc-able
chunk, and the distance from pairs to the end of its array is less
than parseState->size. So any subsequent addition of more pairs is
at high risk of clobbering memory and/or causing repalloc to crash.
Unfortunately, adding more pairs is exactly what will happen when the
aggregate is being used as a window function.
Fix by rewriting uniqueifyJsonbObject to not do that. The prior
coding had little to recommend it anyway.
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/ec5e96fb-ee49-4e5f-8a09-3f72b4780538@gmail.com
This commit is contained in:
@@ -1582,6 +1582,38 @@ SELECT jsonb_object_agg(1, NULL::jsonb);
|
||||
|
||||
SELECT jsonb_object_agg(NULL, '{"a":1}');
|
||||
ERROR: field name must not be null
|
||||
SELECT jsonb_object_agg_unique(i, null) OVER (ORDER BY i)
|
||||
FROM generate_series(1, 10) g(i);
|
||||
jsonb_object_agg_unique
|
||||
-----------------------------------------------------------------------------------------------------------------
|
||||
{"1": null}
|
||||
{"1": null, "2": null}
|
||||
{"1": null, "2": null, "3": null}
|
||||
{"1": null, "2": null, "3": null, "4": null}
|
||||
{"1": null, "2": null, "3": null, "4": null, "5": null}
|
||||
{"1": null, "2": null, "3": null, "4": null, "5": null, "6": null}
|
||||
{"1": null, "2": null, "3": null, "4": null, "5": null, "6": null, "7": null}
|
||||
{"1": null, "2": null, "3": null, "4": null, "5": null, "6": null, "7": null, "8": null}
|
||||
{"1": null, "2": null, "3": null, "4": null, "5": null, "6": null, "7": null, "8": null, "9": null}
|
||||
{"1": null, "2": null, "3": null, "4": null, "5": null, "6": null, "7": null, "8": null, "9": null, "10": null}
|
||||
(10 rows)
|
||||
|
||||
SELECT jsonb_object_agg_unique_strict(i, null) OVER (ORDER BY i)
|
||||
FROM generate_series(1, 10) g(i);
|
||||
jsonb_object_agg_unique_strict
|
||||
--------------------------------
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
(10 rows)
|
||||
|
||||
CREATE TEMP TABLE foo (serial_num int, name text, type text);
|
||||
INSERT INTO foo VALUES (847001,'t15','GE1043');
|
||||
INSERT INTO foo VALUES (847002,'t16','GE1043');
|
||||
|
||||
@@ -402,6 +402,12 @@ SELECT jsonb_build_object('{1,2,3}'::int[], 3);
|
||||
SELECT jsonb_object_agg(1, NULL::jsonb);
|
||||
SELECT jsonb_object_agg(NULL, '{"a":1}');
|
||||
|
||||
SELECT jsonb_object_agg_unique(i, null) OVER (ORDER BY i)
|
||||
FROM generate_series(1, 10) g(i);
|
||||
|
||||
SELECT jsonb_object_agg_unique_strict(i, null) OVER (ORDER BY i)
|
||||
FROM generate_series(1, 10) g(i);
|
||||
|
||||
CREATE TEMP TABLE foo (serial_num int, name text, type text);
|
||||
INSERT INTO foo VALUES (847001,'t15','GE1043');
|
||||
INSERT INTO foo VALUES (847002,'t16','GE1043');
|
||||
|
||||
Reference in New Issue
Block a user