Regression with large XML data input
Michael Paquier <michael@paquier.xyz>
From: Michael Paquier <michael@paquier.xyz>
To: Postgres hackers <pgsql-hackers@lists.postgresql.org>
Cc: Tom Lane <tgl@sss.pgh.pa.us>, Erik Wienhold <ewie@ewie.name>
Date: 2025-07-24T03:12:28Z
Lists: pgsql-hackers
Attachments
- 0001-Fix-xml2-regression.patch (text/x-diff) patch 0001
Hi all,
(Adding in CC Tom and Eric, as committer and author.)
A customer has reported a regression with the parsing of rather large
XML data, introduced by the set of backpatches done with f68d6aabb7e2
& friends.
The problem is introduced by the change from
xmlParseBalancedChunkMemory() to xmlNewNode() +
xmlParseInNodeContext() in xml_parse(), to avoid an issue in
xmlParseBalancedChunkMemory() in the range of libxml2 2.13.0-2.13.2
for a bug that has already been fixed upstream, where we use a
temporary root node for the case where parse_as_document is false.
If the input XML data is large enough, one gets a failure at the top
of the latest branches, and it worked properly before. Here is a
short test case (courtesy of a colleague, case that I've modified
slightly):
CREATE TABLE xmldata (id BIGINT PRIMARY KEY, message XML );
DO $$ DECLARE size_40mb TEXT := repeat('X', 40000000);
BEGIN
BEGIN
INSERT INTO xmldata (id, message) VALUES
( 1, (('<Root><Item><Name>Test40MB</Name><Content>' || size_40mb || '</Content></Item></Root>')::xml) );
RAISE NOTICE 'insert 40MB successful';
EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'Error insert 40MB: %', SQLERRM;
END;
END $$;
Switching back to the previous code, where we rely on
xmlParseBalancedChunkMemory() fixes the issue. A quick POC is
attached. It fails one case in check-world with SERIALIZE because I
am not sure it is possible to pass down some options through
xmlParseBalancedChunkMemory(), still the regression is gone, and I am
wondering if there is not a better solution to be able to dodge the
original problem and still accept this case. One good thing is that
xmlParseBalancedChunkMemory() is able to return a list of nodes, that
we need for this code path of xml_parse(). So perhaps one solution
would be the addition of a code path with
xmlParseBalancedChunkMemory() depending on the options we want to
process, keeping the code path with the fake "content-root" for the
XML SERIALIZE case.
The patch in question has been applied first to 6082b3d5d3d1 on HEAD
impacting v18~, then it has been backpatched down to all stable
branches, like f68d6aabb7e2, introducing the regression in all the
stable branches since the minor releases done in August 2024, as of:
12.20, 13.16, 14.13, 15.8, 16.4.
Thoughts or comments?
--
Michael
Commits
-
Remove unnecessary complication around xmlParseBalancedChunkMemory.
- 902f92221889 19 (unreleased) landed
- cdcdabce5b70 14.19 landed
- 0ae824704070 13.22 landed
- 0928e18eb85a 15.14 landed
- d5f014d897c8 18.0 landed
- 762c6d8d26e0 16.10 landed
- 7571e0f6e924 17.6 landed
-
Avoid regression in the size of XML input that we will accept.
- 6d5e493b4a15 16.10 landed
- 589d6e6408b4 13.22 landed
- 0ffbd345e43d 15.14 landed
- 0395464aff02 14.19 landed
- fd4ad33fe223 17.6 landed
- 71c0921b649d 19 (unreleased) landed
- 637ead2e1aa1 18.0 landed
-
Use xmlParseInNodeContext not xmlParseBalancedChunkMemory.
- 6082b3d5d3d1 18.0 cited
-
Revert "Add support for parsing of large XML data (>= 10MB)"
- f2743a7d70e7 17.0 cited