Skip to content

Commit 2e616de

Browse files
committed
Fix crash with old libxml2
Certain libxml2 versions (such as the 2.7.6 commonly seen in older distributions, but apparently only on x86_64) contain a bug that causes xmlCopyNode, when called on a XML_DOCUMENT_NODE, to return a node that xmlFreeNode crashes on. Arrange to call xmlFreeDoc instead of xmlFreeNode for those nodes. Per buildfarm members lapwing and grison. Author: Pavel Stehule, light editing by Álvaro. Discussion: https://postgr.es/m/20190308024436.GA2374@alvherre.pgsql
1 parent 1b76168 commit 2e616de

File tree

1 file changed

+40
-18
lines changed
  • src/backend/utils/adt

1 file changed

+40
-18
lines changed

src/backend/utils/adt/xml.c

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3720,35 +3720,57 @@ xml_xmlnodetoxmltype(xmlNodePtr cur, PgXmlErrorContext *xmlerrcxt)
37203720

37213721
if (cur->type != XML_ATTRIBUTE_NODE && cur->type != XML_TEXT_NODE)
37223722
{
3723-
xmlBufferPtr buf;
3724-
xmlNodePtr cur_copy;
3723+
void (*nodefree) (xmlNodePtr) = NULL;
3724+
volatile xmlBufferPtr buf = NULL;
3725+
volatile xmlNodePtr cur_copy = NULL;
37253726

3726-
buf = xmlBufferCreate();
3727+
PG_TRY();
3728+
{
3729+
int bytes;
37273730

3728-
/*
3729-
* The result of xmlNodeDump() won't contain namespace definitions
3730-
* from parent nodes, but xmlCopyNode() duplicates a node along with
3731-
* its required namespace definitions.
3732-
*/
3733-
cur_copy = xmlCopyNode(cur, 1);
3731+
buf = xmlBufferCreate();
3732+
if (buf == NULL || xmlerrcxt->err_occurred)
3733+
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
3734+
"could not allocate xmlBuffer");
37343735

3735-
if (cur_copy == NULL)
3736-
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
3737-
"could not copy node");
3736+
/*
3737+
* Produce a dump of the node that we can serialize. xmlNodeDump
3738+
* does that, but the result of that function won't contain
3739+
* namespace definitions from ancestor nodes, so we first do a
3740+
* xmlCopyNode() which duplicates the node along with its required
3741+
* namespace definitions.
3742+
*
3743+
* Some old libxml2 versions such as 2.7.6 produce partially
3744+
* broken XML_DOCUMENT_NODE nodes (unset content field) when
3745+
* copying them. xmlNodeDump of such a node works fine, but
3746+
* xmlFreeNode crashes; set us up to call xmlFreeDoc instead.
3747+
*/
3748+
cur_copy = xmlCopyNode(cur, 1);
3749+
if (cur_copy == NULL || xmlerrcxt->err_occurred)
3750+
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
3751+
"could not copy node");
3752+
nodefree = (cur_copy->type == XML_DOCUMENT_NODE) ?
3753+
(void (*) (xmlNodePtr)) xmlFreeDoc : xmlFreeNode;
3754+
3755+
bytes = xmlNodeDump(buf, NULL, cur_copy, 0, 1);
3756+
if (bytes == -1 || xmlerrcxt->err_occurred)
3757+
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
3758+
"could not dump node");
37383759

3739-
PG_TRY();
3740-
{
3741-
xmlNodeDump(buf, NULL, cur_copy, 0, 1);
37423760
result = xmlBuffer_to_xmltype(buf);
37433761
}
37443762
PG_CATCH();
37453763
{
3746-
xmlFreeNode(cur_copy);
3747-
xmlBufferFree(buf);
3764+
if (nodefree)
3765+
nodefree(cur_copy);
3766+
if (buf)
3767+
xmlBufferFree(buf);
37483768
PG_RE_THROW();
37493769
}
37503770
PG_END_TRY();
3751-
xmlFreeNode(cur_copy);
3771+
3772+
if (nodefree)
3773+
nodefree(cur_copy);
37523774
xmlBufferFree(buf);
37533775
}
37543776
else

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy