mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
Fix low-probability memory leak in XMLSERIALIZE(... INDENT).
xmltotext_with_options() did not consider the possibility that
pg_xml_init() could fail --- most likely due to OOM. If that
happened, the already-parsed xmlDoc structure would be leaked.
Oversight in commit 483bdb2af
.
Bug: #18981
Author: Dmitry Kovalenko <d.kovalenko@postgrespro.ru>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/18981-9bc3c80f107ae925@postgresql.org
Backpatch-through: 16
This commit is contained in:
@ -532,7 +532,7 @@ xmltext(PG_FUNCTION_ARGS)
|
|||||||
volatile xmlChar *xmlbuf = NULL;
|
volatile xmlChar *xmlbuf = NULL;
|
||||||
PgXmlErrorContext *xmlerrcxt;
|
PgXmlErrorContext *xmlerrcxt;
|
||||||
|
|
||||||
/* Otherwise, we gotta spin up some error handling. */
|
/* First we gotta spin up some error handling. */
|
||||||
xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
|
xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
|
||||||
|
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
@ -685,7 +685,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
|
|||||||
volatile xmlBufferPtr buf = NULL;
|
volatile xmlBufferPtr buf = NULL;
|
||||||
volatile xmlSaveCtxtPtr ctxt = NULL;
|
volatile xmlSaveCtxtPtr ctxt = NULL;
|
||||||
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
PgXmlErrorContext *xmlerrcxt;
|
PgXmlErrorContext *volatile xmlerrcxt = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
|
if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
|
||||||
@ -726,13 +726,18 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
|
|||||||
return (text *) data;
|
return (text *) data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, we gotta spin up some error handling. */
|
/*
|
||||||
xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
|
* Otherwise, we gotta spin up some error handling. Unlike most other
|
||||||
|
* routines in this module, we already have a libxml "doc" structure to
|
||||||
|
* free, so we need to call pg_xml_init() inside the PG_TRY and be
|
||||||
|
* prepared for it to fail (typically due to palloc OOM).
|
||||||
|
*/
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
{
|
{
|
||||||
size_t decl_len = 0;
|
size_t decl_len = 0;
|
||||||
|
|
||||||
|
xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
|
||||||
|
|
||||||
/* The serialized data will go into this buffer. */
|
/* The serialized data will go into this buffer. */
|
||||||
buf = xmlBufferCreate();
|
buf = xmlBufferCreate();
|
||||||
|
|
||||||
@ -863,10 +868,10 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
|
|||||||
xmlSaveClose(ctxt);
|
xmlSaveClose(ctxt);
|
||||||
if (buf)
|
if (buf)
|
||||||
xmlBufferFree(buf);
|
xmlBufferFree(buf);
|
||||||
if (doc)
|
xmlFreeDoc(doc);
|
||||||
xmlFreeDoc(doc);
|
|
||||||
|
|
||||||
pg_xml_done(xmlerrcxt, true);
|
if (xmlerrcxt)
|
||||||
|
pg_xml_done(xmlerrcxt, true);
|
||||||
|
|
||||||
PG_RE_THROW();
|
PG_RE_THROW();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user