agora inbox for [email protected]
help / color / mirror / Atom feedFrom: Andrey Chernyy <[email protected]>
Subject: [PATCH 2/2] Fix libxml leaks in contrib/xml2 xpath_table
Date: Tue, 26 May 2026 00:11:06 +0300
xpath_table() did not release libxml objects allocated while evaluating
XPath expressions. xmlXPathCompiledEval() returns an xmlXPathObjectPtr
that must be freed, and string results copied into the tuple input array
must be freed after BuildTupleFromCStrings() has consumed them.
Track the current libxml objects across the existing PG_TRY block so they
are also released on error.
---
contrib/xml2/xpath.c | 47 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 42 insertions(+), 5 deletions(-)
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 94819961787..ac140a640e0 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -643,6 +643,10 @@ xpath_table(PG_FUNCTION_ARGS)
StringInfoData query_buf;
PgXmlErrorContext *xmlerrcxt;
volatile xmlDocPtr doctree = NULL;
+ xmlXPathContextPtr volatile ctxt = NULL;
+ xmlXPathObjectPtr volatile res = NULL;
+ xmlXPathCompExprPtr volatile comppath = NULL;
+ xmlChar *volatile resstr = NULL;
InitMaterializedSRF(fcinfo, MAT_SRF_USE_EXPECTED_DESC);
@@ -662,7 +666,7 @@ xpath_table(PG_FUNCTION_ARGS)
attinmeta = TupleDescGetAttInMetadata(rsinfo->setDesc);
- values = (char **) palloc(rsinfo->setDesc->natts * sizeof(char *));
+ values = (char **) palloc0(rsinfo->setDesc->natts * sizeof(char *));
xpaths = (xmlChar **) palloc(rsinfo->setDesc->natts * sizeof(xmlChar *));
/*
@@ -732,10 +736,6 @@ xpath_table(PG_FUNCTION_ARGS)
{
char *pkey;
char *xmldoc;
- xmlXPathContextPtr ctxt;
- xmlXPathObjectPtr res;
- xmlChar *resstr;
- xmlXPathCompExprPtr comppath;
HeapTuple ret_tuple;
/* Extract the row data as C Strings */
@@ -780,6 +780,11 @@ xpath_table(PG_FUNCTION_ARGS)
had_values = false;
for (j = 0; j < numpaths; j++)
{
+ ctxt = NULL;
+ res = NULL;
+ comppath = NULL;
+ resstr = NULL;
+
ctxt = xmlXPathNewContext(doctree);
if (ctxt == NULL || pg_xml_error_occurred(xmlerrcxt))
xml_ereport(xmlerrcxt,
@@ -798,6 +803,7 @@ xpath_table(PG_FUNCTION_ARGS)
/* Now evaluate the path expression. */
res = xmlXPathCompiledEval(comppath, ctxt);
xmlXPathFreeCompExpr(comppath);
+ comppath = NULL;
if (res != NULL)
{
@@ -842,8 +848,16 @@ xpath_table(PG_FUNCTION_ARGS)
* result tuple.
*/
values[j + 1] = (char *) resstr;
+ resstr = NULL;
+ }
+
+ if (res != NULL)
+ {
+ xmlXPathFreeObject(res);
+ res = NULL;
}
xmlXPathFreeContext(ctxt);
+ ctxt = NULL;
}
/* Now add the tuple to the output, if there is one. */
@@ -854,6 +868,16 @@ xpath_table(PG_FUNCTION_ARGS)
heap_freetuple(ret_tuple);
}
+ /* BuildTupleFromCStrings() has copied the values. */
+ for (j = 1; j < rsinfo->setDesc->natts; j++)
+ {
+ if (values[j] != NULL)
+ {
+ xmlFree((xmlChar *) values[j]);
+ values[j] = NULL;
+ }
+ }
+
rownr++;
} while (had_values);
}
@@ -870,6 +894,19 @@ xpath_table(PG_FUNCTION_ARGS)
}
PG_CATCH();
{
+ if (resstr != NULL)
+ xmlFree(resstr);
+ for (j = 1; j < rsinfo->setDesc->natts; j++)
+ {
+ if (values[j] != NULL)
+ xmlFree((xmlChar *) values[j]);
+ }
+ if (res != NULL)
+ xmlXPathFreeObject(res);
+ if (comppath != NULL)
+ xmlXPathFreeCompExpr(comppath);
+ if (ctxt != NULL)
+ xmlXPathFreeContext(ctxt);
if (doctree != NULL)
xmlFreeDoc(doctree);
--
2.54.0
--MP_/T7YUrG7W2jPQOBsjEYwqj9B--
view thread (554+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH 2/2] Fix libxml leaks in contrib/xml2 xpath_table
In-Reply-To: <no-message-id-450455@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox