Skip to content

Commit ee58de1

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 0d20635 commit ee58de1

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
@@ -733,15 +733,22 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
733733
* content nodes, and then iterate over the nodes.
734734
*/
735735
xmlNodePtr root;
736+
xmlNodePtr oldroot;
736737
xmlNodePtr newline;
737738

738739
root = xmlNewNode(NULL, (const xmlChar *) "content-root");
739740
if (root == NULL || xmlerrcxt->err_occurred)
740741
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
741742
"could not allocate xml node");
742743

743-
/* This attaches root to doc, so we need not free it separately. */
744-
xmlDocSetRootElement(doc, root);
744+
/*
745+
* This attaches root to doc, so we need not free it separately...
746+
* but instead, we have to free the old root if there was one.
747+
*/
748+
oldroot = xmlDocSetRootElement(doc, root);
749+
if (oldroot != NULL)
750+
xmlFreeNode(oldroot);
751+
745752
xmlAddChildList(root, content_nodes);
746753

747754
/*
@@ -1829,6 +1836,7 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
18291836
else
18301837
{
18311838
xmlNodePtr root;
1839+
xmlNodePtr oldroot PG_USED_FOR_ASSERTS_ONLY;
18321840

18331841
/* set up document with empty root node to be the context node */
18341842
doc = xmlNewDoc(version);
@@ -1847,8 +1855,13 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
18471855
if (root == NULL || xmlerrcxt->err_occurred)
18481856
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
18491857
"could not allocate xml node");
1850-
/* This attaches root to doc, so we need not free it separately. */
1851-
xmlDocSetRootElement(doc, root);
1858+
1859+
/*
1860+
* This attaches root to doc, so we need not free it separately;
1861+
* and there can't yet be any old root to free.
1862+
*/
1863+
oldroot = xmlDocSetRootElement(doc, root);
1864+
Assert(oldroot == NULL);
18521865

18531866
/* allow empty content */
18541867
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