]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix low-probability memory leak in XMLSERIALIZE(... INDENT).
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 8 Jul 2025 16:50:19 +0000 (12:50 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 8 Jul 2025 16:50:33 +0000 (12:50 -0400)
xmltotext_with_options() did not consider the possibility that
pg_xml_init() could fail --- most likely due to OOM.  If that
happened, the already-parsed xmlDoc structure would be leaked.
Oversight in commit 483bdb2af.

Bug: #18981
Author: Dmitry Kovalenko <d.kovalenko@postgrespro.ru>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/18981-9bc3c80f107ae925@postgresql.org
Backpatch-through: 16

src/backend/utils/adt/xml.c

index 2bd39b6ac4b09861f4a17f7a10a7c4bbb822454a..f7b731825fca0d80073d07ae69a5ac3c4fc4d039 100644 (file)
@@ -532,7 +532,7 @@ xmltext(PG_FUNCTION_ARGS)
        volatile xmlChar *xmlbuf = NULL;
        PgXmlErrorContext *xmlerrcxt;
 
-       /* Otherwise, we gotta spin up some error handling. */
+       /* First we gotta spin up some error handling. */
        xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
 
        PG_TRY();
@@ -685,7 +685,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
        volatile xmlBufferPtr buf = NULL;
        volatile xmlSaveCtxtPtr ctxt = NULL;
        ErrorSaveContext escontext = {T_ErrorSaveContext};
-       PgXmlErrorContext *xmlerrcxt;
+       PgXmlErrorContext *volatile xmlerrcxt = NULL;
 #endif
 
        if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
@@ -726,13 +726,18 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
                return (text *) data;
        }
 
-       /* Otherwise, we gotta spin up some error handling. */
-       xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
-
+       /*
+        * Otherwise, we gotta spin up some error handling.  Unlike most other
+        * routines in this module, we already have a libxml "doc" structure to
+        * free, so we need to call pg_xml_init() inside the PG_TRY and be
+        * prepared for it to fail (typically due to palloc OOM).
+        */
        PG_TRY();
        {
                size_t          decl_len = 0;
 
+               xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
+
                /* The serialized data will go into this buffer. */
                buf = xmlBufferCreate();
 
@@ -863,10 +868,10 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
                        xmlSaveClose(ctxt);
                if (buf)
                        xmlBufferFree(buf);
-               if (doc)
-                       xmlFreeDoc(doc);
+               xmlFreeDoc(doc);
 
-               pg_xml_done(xmlerrcxt, true);
+               if (xmlerrcxt)
+                       pg_xml_done(xmlerrcxt, true);
 
                PG_RE_THROW();
        }