Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uHpvQ-00Aits-29 for pgsql-hackers@arkaria.postgresql.org; Wed, 21 May 2025 20:20:28 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uHpvN-00AnWv-Qs for pgsql-hackers@arkaria.postgresql.org; Wed, 21 May 2025 20:20:25 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uHpvN-00AnWn-HK for pgsql-hackers@lists.postgresql.org; Wed, 21 May 2025 20:20:25 +0000 Received: from sss.pgh.pa.us ([68.162.161.243]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1uHpvK-000C6P-1T for pgsql-hackers@lists.postgresql.org; Wed, 21 May 2025 20:20:24 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 54LKKH2v1358968; Wed, 21 May 2025 16:20:17 -0400 From: Tom Lane To: Jim Jones cc: Peter Smith , Peter Eisentraut , Nikolay Samokhvalov , PostgreSQL Hackers , Andrey Borodin Subject: Re: [PATCH] Add pretty-printed XML output option In-reply-to: <1c7cf9f0-14c3-0341-6894-8ca577bf325e@uni-muenster.de> References: <2f5df461-dad8-6d7d-4568-08e10608a69b@uni-muenster.de> <2eac4d78-2b20-e8ec-54cc-22a88653a1cc@uni-muenster.de> <6cb296fe-4b49-3691-633e-2e2366997b04@uni-muenster.de> <3baf8f25-3bd7-7db5-0b31-e4c92b6269ba@enterprisedb.com> <1cbe1087-6acb-2b0a-dc9b-0a2d5b99e466@uni-muenster.de> <532259.1678393296@sss.pgh.pa.us> <906cfd1d-63a0-3cf5-7291-2dadb2e! 149ff@uni-muenster.de> <803304.1678458776@sss.pgh.pa.us> <2752578.1678815625@sss.pgh.pa.us> <3057762.1678836321@sss.pgh.pa.us> <3622266.1678914816@sss.pgh.pa.us> <1c7cf9f0-14c3-0341-6894! -8ca577bf325e@uni-muenster.de> Comments: In-reply-to Jim Jones message dated "Thu, 16 Mar 2023 20:07:06 +0100" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <1358881.1747858770.0@sss.pgh.pa.us> Date: Wed, 21 May 2025 16:20:17 -0400 Message-ID: <1358967.1747858817@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <1358881.1747858770.1@sss.pgh.pa.us> Jim Jones 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 ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="fix-leakage-in-xmlserialize-indent.patch"; charset="us-ascii" Content-ID: <1358881.1747858770.2@sss.pgh.pa.us> Content-Description: fix-leakage-in-xmlserialize-indent.patch Content-Transfer-Encoding: quoted-printable 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 xm= loption_arg, bool indent) * content nodes, and then iterate over the nodes. */ xmlNodePtr root; + xmlNodePtr oldroot; xmlNodePtr newline; = root =3D xmlNewNode(NULL, (const xmlChar *) "content-root"); @@ -761,8 +762,14 @@ xmltotext_with_options(xmltype *data, XmlOptionType x= mloption_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 =3D xmlDocSetRootElement(doc, root); + if (oldroot !=3D NULL) + xmlFreeNode(oldroot); + xmlAddChildList(root, content_nodes); = /* ------- =_aaaaaaaaaa0--