Jim Jones <jim.jo...@uni-muenster.de> writes: > In my environment (libxml2 v2.9.10 and Ubuntu 22.04) I couldn't > reproduce this memory leak.
Just when you thought it was safe to go back in the water ... Experimenting with the improved valgrind leak detection code at [1], I discovered that XMLSERIALIZE(... INDENT) has yet a different memory leak problem. It turns out that xmlDocSetRootElement() doesn't merely install the given root node: it unlinks the document's old root node and returns it to you. If you don't free it, it's leaked (for the session, since this is a malloc not palloc). The amount of leakage isn't that large, seems to be a couple hundred bytes per iteration, which may explain why this escaped our notice in the previous testing. Still, it could add up under extensive usage. So I think we need to apply the attached, back to PG 16. regards, tom lane [1] https://www.postgresql.org/message-id/1295385.1747847681%40sss.pgh.pa.us
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index db8d0d6a7e8..73fd4fa090c 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -754,6 +754,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) * content nodes, and then iterate over the nodes. */ xmlNodePtr root; + xmlNodePtr oldroot; xmlNodePtr newline; root = xmlNewNode(NULL, (const xmlChar *) "content-root"); @@ -761,8 +762,14 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent) xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY, "could not allocate xml node"); - /* This attaches root to doc, so we need not free it separately. */ - xmlDocSetRootElement(doc, root); + /* + * This attaches root to doc, so we need not free it separately... + * but instead, we have to free the old root if there was one. + */ + oldroot = xmlDocSetRootElement(doc, root); + if (oldroot != NULL) + xmlFreeNode(oldroot); + xmlAddChildList(root, content_nodes); /*