Skip to content

Commit 20bae06

Browse files
committed
Fix memory leak in XMLSERIALIZE(... INDENT).
xmltotext_with_options sometimes tries to replace the existing root node of a libxml2 document. In that case xmlDocSetRootElement will unlink and return the old root node; if we fail to free it, it's leaked for the remainder of the session. The amount of memory at stake is not large, a couple hundred bytes per occurrence, but that could still become annoying in heavy usage. Our only other xmlDocSetRootElement call is not at risk because it's working on a just-created document, but let's modify that code too to make it clear that it's dependent on that. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Jim Jones <jim.jones@uni-muenster.de> Discussion: https://postgr.es/m/1358967.1747858817@sss.pgh.pa.us Backpatch-through: 16
1 parent 11efaaf commit 20bae06

File tree

1 file changed

+17
-4
lines changed
  • src/backend/utils/adt

1 file changed

+17
-4
lines changed

src/backend/utils/adt/xml.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -754,15 +754,22 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
754754
* content nodes, and then iterate over the nodes.
755755
*/
756756
xmlNodePtr root;
757+
xmlNodePtr oldroot;
757758
xmlNodePtr newline;
758759

759760
root = xmlNewNode(NULL, (const xmlChar *) "content-root");
760761
if (root == NULL || xmlerrcxt->err_occurred)
761762
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
762763
"could not allocate xml node");
763764

764-
/* This attaches root to doc, so we need not free it separately. */
765-
xmlDocSetRootElement(doc, root);
765+
/*
766+
* This attaches root to doc, so we need not free it separately...
767+
* but instead, we have to free the old root if there was one.
768+
*/
769+
oldroot = xmlDocSetRootElement(doc, root);
770+
if (oldroot != NULL)
771+
xmlFreeNode(oldroot);
772+
766773
xmlAddChildList(root, content_nodes);
767774

768775
/*
@@ -1850,6 +1857,7 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
18501857
else
18511858
{
18521859
xmlNodePtr root;
1860+
xmlNodePtr oldroot PG_USED_FOR_ASSERTS_ONLY;
18531861

18541862
/* set up document with empty root node to be the context node */
18551863
doc = xmlNewDoc(version);
@@ -1868,8 +1876,13 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
18681876
if (root == NULL || xmlerrcxt->err_occurred)
18691877
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
18701878
"could not allocate xml node");
1871-
/* This attaches root to doc, so we need not free it separately. */
1872-
xmlDocSetRootElement(doc, root);
1879+
1880+
/*
1881+
* This attaches root to doc, so we need not free it separately;
1882+
* and there can't yet be any old root to free.
1883+
*/
1884+
oldroot = xmlDocSetRootElement(doc, root);
1885+
Assert(oldroot == NULL);
18731886

18741887
/* allow empty content */
18751888
if (*(utf8string + count))

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