]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
xml2: Fix stylesheet document leak in xslt_process()
authorMichael Paquier <michael@paquier.xyz>
Fri, 5 Jun 2026 05:29:27 +0000 (14:29 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 5 Jun 2026 05:29:27 +0000 (14:29 +0900)
xslt_process() parses the stylesheet text into an xmlDoc before passing it
to xsltParseStylesheetDoc().  On success, the returned stylesheet owns
that document and frees it through xsltFreeStylesheet(), calling
xmlFreeDoc() at its end.  On failure, libxslt leaves the caller
responsible for the xmlDoc.  In xml2, this would cause the memory
allocated for the xmlDoc to pile up across calls of xslt_process() when
failing to create a sheet.

While on it, I have double-checked the code of xml2 with libxslt, and it
seems that we are in the clear now, hopefully..  This leak exists for a
long time.  732061150b0 has made the fix introduced in this commit
easier to implement.

Author: Andrey Chernyy <andrey.cherny@tantorlabs.com>
Discussion: https://postgr.es/m/20260605024642.5a1b6518@andrnote

contrib/xml2/xslt_proc.c

index 8ceb8c464942f2bfeb9fee5dd93152530eda4232..c42469cfaa3b8630da55f9d286b0db9f3da87262 100644 (file)
@@ -55,6 +55,7 @@ xslt_process(PG_FUNCTION_ARGS)
        PgXmlErrorContext *xmlerrcxt;
        volatile xsltStylesheetPtr stylesheet = NULL;
        volatile xmlDocPtr doctree = NULL;
+       volatile xmlDocPtr ssdoc = NULL;
        volatile xmlDocPtr restree = NULL;
        volatile xsltSecurityPrefsPtr xslt_sec_prefs = NULL;
        volatile xsltTransformContextPtr xslt_ctxt = NULL;
@@ -78,7 +79,6 @@ xslt_process(PG_FUNCTION_ARGS)
 
        PG_TRY();
        {
-               xmlDocPtr       ssdoc;
                bool            xslt_sec_prefs_error;
                int                     reslen = 0;
 
@@ -100,8 +100,13 @@ xslt_process(PG_FUNCTION_ARGS)
                        xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_DOCUMENT,
                                                "error parsing stylesheet as XML document");
 
-               /* After this call we need not free ssdoc separately */
+               /*
+                * On success, the stylesheet owns ssdoc, with xsltFreeStylesheet()
+                * calling xmlFreeDoc() on its associated doc.
+                */
                stylesheet = xsltParseStylesheetDoc(ssdoc);
+               if (stylesheet != NULL)
+                       ssdoc = NULL;
 
                if (stylesheet == NULL || pg_xml_error_occurred(xmlerrcxt))
                        xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY,
@@ -167,6 +172,8 @@ xslt_process(PG_FUNCTION_ARGS)
                        xsltFreeSecurityPrefs(xslt_sec_prefs);
                if (stylesheet != NULL)
                        xsltFreeStylesheet(stylesheet);
+               if (ssdoc != NULL)
+                       xmlFreeDoc(ssdoc);
                if (doctree != NULL)
                        xmlFreeDoc(doctree);
                if (resstr != NULL)