Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a9747be

Browse files
committed
Make our back branches compatible with libxml2 2.13.x.
This back-patches HEAD commits 066e8ac, 6082b3d, e719248, and 896cd26 into supported branches. Changes: * Use xmlAddChildList not xmlAddChild in XMLSERIALIZE (affects v16 and up only). This was a flat-out coding mistake that we got away with due to lax checking in previous versions of xmlAddChild. * Use xmlParseInNodeContext not xmlParseBalancedChunkMemory. This is to dodge a bug in xmlParseBalancedChunkMemory in libxm2 releases 2.13.0-2.13.2. While that bug is now fixed upstream and will probably never be seen in any production-oriented distro, it is currently a problem on some more-bleeding-edge-friendly platforms. * Suppress "chunk is not well balanced" errors from libxml2, unless it is the only error. This eliminates an error-reporting discrepancy between 2.13 and older releases. This error is almost always redundant with previous errors, if not flat-out inappropriate, which is why 2.13 changed the behavior and why nobody's likely to miss it. Erik Wienhold and Tom Lane, per report from Frank Streitzig. Discussion: https://postgr.es/m/trinity-b0161630-d230-4598-9ebc-7a23acdb37cb-1720186432160@3c-app-gmx-bap25 Discussion: https://postgr.es/m/trinity-361ba18b-541a-4fe7-bc63-655ae3a7d599-1720259822452@3c-app-gmx-bs01
1 parent 4506d18 commit a9747be

File tree

3 files changed

+66
-36
lines changed

3 files changed

+66
-36
lines changed

src/backend/utils/adt/xml.c

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
757757

758758
/* This attaches root to doc, so we need not free it separately. */
759759
xmlDocSetRootElement(doc, root);
760-
xmlAddChild(root, content_nodes);
760+
xmlAddChildList(root, content_nodes);
761761

762762
/*
763763
* We use this node to insert newlines in the dump. Note: in at
@@ -1696,9 +1696,9 @@ xml_doctype_in_content(const xmlChar *str)
16961696
* XmlOptionType actually used to parse the input (typically the same as
16971697
* xmloption_arg, but a DOCTYPE node in the input can force DOCUMENT mode).
16981698
*
1699-
* If parsed_nodes isn't NULL and the input is not an XML document, the list
1700-
* of parsed nodes from the xmlParseBalancedChunkMemory call will be returned
1701-
* to *parsed_nodes.
1699+
* If parsed_nodes isn't NULL and we parse in CONTENT mode, the list
1700+
* of parsed nodes from the xmlParseInNodeContext call will be returned
1701+
* to *parsed_nodes. (It is caller's responsibility to free that.)
17021702
*
17031703
* Errors normally result in ereport(ERROR), but if escontext is an
17041704
* ErrorSaveContext, then "safe" errors are reported there instead, and the
@@ -1750,6 +1750,7 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
17501750
PG_TRY();
17511751
{
17521752
bool parse_as_document = false;
1753+
int options;
17531754
int res_code;
17541755
size_t count = 0;
17551756
xmlChar *version = NULL;
@@ -1758,11 +1759,6 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
17581759
/* Any errors here are reported as hard ereport's */
17591760
xmlInitParser();
17601761

1761-
ctxt = xmlNewParserCtxt();
1762-
if (ctxt == NULL || xmlerrcxt->err_occurred)
1763-
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
1764-
"could not allocate parser context");
1765-
17661762
/* Decide whether to parse as document or content */
17671763
if (xmloption_arg == XMLOPTION_DOCUMENT)
17681764
parse_as_document = true;
@@ -1785,6 +1781,18 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
17851781
parse_as_document = true;
17861782
}
17871783

1784+
/*
1785+
* Select parse options.
1786+
*
1787+
* Note that here we try to apply DTD defaults (XML_PARSE_DTDATTR)
1788+
* according to SQL/XML:2008 GR 10.16.7.d: 'Default values defined by
1789+
* internal DTD are applied'. As for external DTDs, we try to support
1790+
* them too (see SQL/XML:2008 GR 10.16.7.e), but that doesn't really
1791+
* happen because xmlPgEntityLoader prevents it.
1792+
*/
1793+
options = XML_PARSE_NOENT | XML_PARSE_DTDATTR
1794+
| (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS);
1795+
17881796
/* initialize output parameters */
17891797
if (parsed_xmloptiontype != NULL)
17901798
*parsed_xmloptiontype = parse_as_document ? XMLOPTION_DOCUMENT :
@@ -1794,18 +1802,16 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
17941802

17951803
if (parse_as_document)
17961804
{
1797-
/*
1798-
* Note, that here we try to apply DTD defaults
1799-
* (XML_PARSE_DTDATTR) according to SQL/XML:2008 GR 10.16.7.d:
1800-
* 'Default values defined by internal DTD are applied'. As for
1801-
* external DTDs, we try to support them too, (see SQL/XML:2008 GR
1802-
* 10.16.7.e)
1803-
*/
1805+
ctxt = xmlNewParserCtxt();
1806+
if (ctxt == NULL || xmlerrcxt->err_occurred)
1807+
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
1808+
"could not allocate parser context");
1809+
18041810
doc = xmlCtxtReadDoc(ctxt, utf8string,
1805-
NULL,
1811+
NULL, /* no URL */
18061812
"UTF-8",
1807-
XML_PARSE_NOENT | XML_PARSE_DTDATTR
1808-
| (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS));
1813+
options);
1814+
18091815
if (doc == NULL || xmlerrcxt->err_occurred)
18101816
{
18111817
/* Use original option to decide which error code to report */
@@ -1822,6 +1828,9 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
18221828
}
18231829
else
18241830
{
1831+
xmlNodePtr root;
1832+
1833+
/* set up document with empty root node to be the context node */
18251834
doc = xmlNewDoc(version);
18261835
if (doc == NULL || xmlerrcxt->err_occurred)
18271836
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
@@ -1834,19 +1843,38 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
18341843
"could not allocate XML document");
18351844
doc->standalone = standalone;
18361845

1846+
root = xmlNewNode(NULL, (const xmlChar *) "content-root");
1847+
if (root == NULL || xmlerrcxt->err_occurred)
1848+
xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
1849+
"could not allocate xml node");
1850+
/* This attaches root to doc, so we need not free it separately. */
1851+
xmlDocSetRootElement(doc, root);
1852+
18371853
/* allow empty content */
18381854
if (*(utf8string + count))
18391855
{
1840-
res_code = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0,
1841-
utf8string + count,
1842-
parsed_nodes);
1843-
if (res_code != 0 || xmlerrcxt->err_occurred)
1856+
xmlNodePtr node_list = NULL;
1857+
xmlParserErrors res;
1858+
1859+
res = xmlParseInNodeContext(root,
1860+
(char *) utf8string + count,
1861+
strlen((char *) utf8string + count),
1862+
options,
1863+
&node_list);
1864+
1865+
if (res != XML_ERR_OK || xmlerrcxt->err_occurred)
18441866
{
1867+
xmlFreeNodeList(node_list);
18451868
xml_errsave(escontext, xmlerrcxt,
18461869
ERRCODE_INVALID_XML_CONTENT,
18471870
"invalid XML content");
18481871
goto fail;
18491872
}
1873+
1874+
if (parsed_nodes != NULL)
1875+
*parsed_nodes = node_list;
1876+
else
1877+
xmlFreeNodeList(node_list);
18501878
}
18511879
}
18521880

@@ -1866,7 +1894,8 @@ xml_parse(text *data, XmlOptionType xmloption_arg,
18661894
}
18671895
PG_END_TRY();
18681896

1869-
xmlFreeParserCtxt(ctxt);
1897+
if (ctxt != NULL)
1898+
xmlFreeParserCtxt(ctxt);
18701899

18711900
pg_xml_done(xmlerrcxt, false);
18721901

@@ -2085,6 +2114,19 @@ xml_errorHandler(void *data, PgXmlErrorPtr error)
20852114
switch (domain)
20862115
{
20872116
case XML_FROM_PARSER:
2117+
2118+
/*
2119+
* XML_ERR_NOT_WELL_BALANCED is typically reported after some
2120+
* other, more on-point error. Furthermore, libxml2 2.13 reports
2121+
* it under a completely different set of rules than prior
2122+
* versions. To avoid cross-version behavioral differences,
2123+
* suppress it so long as we already logged some error.
2124+
*/
2125+
if (error->code == XML_ERR_NOT_WELL_BALANCED &&
2126+
xmlerrcxt->err_occurred)
2127+
return;
2128+
/* fall through */
2129+
20882130
case XML_FROM_NONE:
20892131
case XML_FROM_MEMORY:
20902132
case XML_FROM_IO:

src/test/regress/expected/xml.out

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,17 +254,11 @@ ERROR: invalid XML content
254254
DETAIL: line 1: xmlParseEntityRef: no name
255255
<invalidentity>&</invalidentity>
256256
^
257-
line 1: chunk is not well balanced
258-
<invalidentity>&</invalidentity>
259-
^
260257
SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
261258
ERROR: invalid XML content
262259
DETAIL: line 1: Entity 'idontexist' not defined
263260
<undefinedentity>&idontexist;</undefinedentity>
264261
^
265-
line 1: chunk is not well balanced
266-
<undefinedentity>&idontexist;</undefinedentity>
267-
^
268262
SELECT xmlparse(content '<invalidns xmlns=''&lt;''/>');
269263
xmlparse
270264
---------------------------
@@ -283,9 +277,6 @@ DETAIL: line 1: Entity 'idontexist' not defined
283277
<twoerrors>&idontexist;</unbalanced>
284278
^
285279
line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
286-
<twoerrors>&idontexist;</unbalanced>
287-
^
288-
line 1: chunk is not well balanced
289280
<twoerrors>&idontexist;</unbalanced>
290281
^
291282
SELECT xmlparse(content '<nosuchprefix:tag/>');

src/test/regress/expected/xml_2.out

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,11 @@ ERROR: invalid XML content
250250
DETAIL: line 1: xmlParseEntityRef: no name
251251
<invalidentity>&</invalidentity>
252252
^
253-
line 1: chunk is not well balanced
254253
SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
255254
ERROR: invalid XML content
256255
DETAIL: line 1: Entity 'idontexist' not defined
257256
<undefinedentity>&idontexist;</undefinedentity>
258257
^
259-
line 1: chunk is not well balanced
260258
SELECT xmlparse(content '<invalidns xmlns=''&lt;''/>');
261259
xmlparse
262260
---------------------------
@@ -275,7 +273,6 @@ DETAIL: line 1: Entity 'idontexist' not defined
275273
<twoerrors>&idontexist;</unbalanced>
276274
^
277275
line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
278-
line 1: chunk is not well balanced
279276
SELECT xmlparse(content '<nosuchprefix:tag/>');
280277
xmlparse
281278
---------------------

0 commit comments

Comments
 (0)