From: Andrey Chernyy Date: Tue, 2 Jun 2026 01:41:38 +0300 Subject: [PATCH v2 4/4] xml2: Avoid libxml leaks in pgxml_xpath() error paths pgxml_xpath() builds an xpath_workspace before returning it to callers. If an ERROR is thrown before the function returns, callers have not received the workspace pointer yet and cannot run cleanup_workspace(). Add local error cleanup for the partially built workspace and the compiled XPath expression. Also check xmlXPathNewContext() before dereferencing the returned context. --- contrib/xml2/xpath.c | 51 +++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c index 9fe75cb5ff4..283bb51178d 100644 --- a/contrib/xml2/xpath.c +++ b/contrib/xml2/xpath.c @@ -497,36 +497,49 @@ static xpath_workspace * pgxml_xpath(text *document, xmlChar *xpath, PgXmlErrorContext *xmlerrcxt) { int32 docsize = VARSIZE_ANY_EXHDR(document); - xmlXPathCompExprPtr comppath; + xmlXPathCompExprPtr volatile comppath = NULL; xpath_workspace *workspace = palloc0_object(xpath_workspace); workspace->doctree = NULL; workspace->ctxt = NULL; workspace->res = NULL; - workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document), - docsize, NULL, NULL, - XML_PARSE_NOENT); - if (workspace->doctree != NULL) + PG_TRY(); { - workspace->ctxt = xmlXPathNewContext(workspace->doctree); - workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree); - - /* compile the path */ - comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath); - if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt)) + workspace->doctree = xmlReadMemory((char *) VARDATA_ANY(document), + docsize, NULL, NULL, + XML_PARSE_NOENT); + if (workspace->doctree != NULL) { - if (comppath != NULL) - xmlXPathFreeCompExpr(comppath); - xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, - "XPath Syntax Error"); - } + workspace->ctxt = xmlXPathNewContext(workspace->doctree); + if (workspace->ctxt == NULL) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, + "could not allocate XPath context"); - /* Now evaluate the path expression. */ - workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt); + workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree); + + /* compile the path */ + comppath = xmlXPathCtxtCompile(workspace->ctxt, xpath); + if (comppath == NULL || pg_xml_error_occurred(xmlerrcxt)) + xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_ARGUMENT_FOR_XQUERY, + "XPath Syntax Error"); + + /* Now evaluate the path expression. */ + workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt); + + xmlXPathFreeCompExpr(comppath); + comppath = NULL; + } + } + PG_CATCH(); + { + if (comppath != NULL) + xmlXPathFreeCompExpr(comppath); + cleanup_workspace(workspace); - xmlXPathFreeCompExpr(comppath); + PG_RE_THROW(); } + PG_END_TRY(); return workspace; } -- 2.54.0 --MP_/LMSk9=uMhuQ1QiIJDarDO8G--