mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Make our back branches compatible with libxml2 2.13.x.
This back-patches HEAD commits066e8ac6e,6082b3d5d,e7192486d, and896cd266finto 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
This commit is contained in:
		@@ -1544,6 +1544,7 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,
 | 
				
			|||||||
	PG_TRY();
 | 
						PG_TRY();
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		bool		parse_as_document = false;
 | 
							bool		parse_as_document = false;
 | 
				
			||||||
 | 
							int			options;
 | 
				
			||||||
		int			res_code;
 | 
							int			res_code;
 | 
				
			||||||
		size_t		count = 0;
 | 
							size_t		count = 0;
 | 
				
			||||||
		xmlChar    *version = NULL;
 | 
							xmlChar    *version = NULL;
 | 
				
			||||||
@@ -1551,11 +1552,6 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		xmlInitParser();
 | 
							xmlInitParser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctxt = xmlNewParserCtxt();
 | 
					 | 
				
			||||||
		if (ctxt == NULL || xmlerrcxt->err_occurred)
 | 
					 | 
				
			||||||
			xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
 | 
					 | 
				
			||||||
						"could not allocate parser context");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* Decide whether to parse as document or content */
 | 
							/* Decide whether to parse as document or content */
 | 
				
			||||||
		if (xmloption_arg == XMLOPTION_DOCUMENT)
 | 
							if (xmloption_arg == XMLOPTION_DOCUMENT)
 | 
				
			||||||
			parse_as_document = true;
 | 
								parse_as_document = true;
 | 
				
			||||||
@@ -1574,20 +1570,30 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,
 | 
				
			|||||||
				parse_as_document = true;
 | 
									parse_as_document = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Select parse options.
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * Note that here we try to apply DTD defaults (XML_PARSE_DTDATTR)
 | 
				
			||||||
 | 
							 * according to SQL/XML:2008 GR 10.16.7.d: 'Default values defined by
 | 
				
			||||||
 | 
							 * internal DTD are applied'.  As for external DTDs, we try to support
 | 
				
			||||||
 | 
							 * them too (see SQL/XML:2008 GR 10.16.7.e), but that doesn't really
 | 
				
			||||||
 | 
							 * happen because xmlPgEntityLoader prevents it.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							options = XML_PARSE_NOENT | XML_PARSE_DTDATTR
 | 
				
			||||||
 | 
								| (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (parse_as_document)
 | 
							if (parse_as_document)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/*
 | 
								ctxt = xmlNewParserCtxt();
 | 
				
			||||||
			 * Note, that here we try to apply DTD defaults
 | 
								if (ctxt == NULL || xmlerrcxt->err_occurred)
 | 
				
			||||||
			 * (XML_PARSE_DTDATTR) according to SQL/XML:2008 GR 10.16.7.d:
 | 
									xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
 | 
				
			||||||
			 * 'Default values defined by internal DTD are applied'. As for
 | 
												"could not allocate parser context");
 | 
				
			||||||
			 * external DTDs, we try to support them too, (see SQL/XML:2008 GR
 | 
					
 | 
				
			||||||
			 * 10.16.7.e)
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			doc = xmlCtxtReadDoc(ctxt, utf8string,
 | 
								doc = xmlCtxtReadDoc(ctxt, utf8string,
 | 
				
			||||||
								 NULL,
 | 
													 NULL,	/* no URL */
 | 
				
			||||||
								 "UTF-8",
 | 
													 "UTF-8",
 | 
				
			||||||
								 XML_PARSE_NOENT | XML_PARSE_DTDATTR
 | 
													 options);
 | 
				
			||||||
								 | (preserve_whitespace ? 0 : XML_PARSE_NOBLANKS));
 | 
					
 | 
				
			||||||
			if (doc == NULL || xmlerrcxt->err_occurred)
 | 
								if (doc == NULL || xmlerrcxt->err_occurred)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				/* Use original option to decide which error code to throw */
 | 
									/* Use original option to decide which error code to throw */
 | 
				
			||||||
@@ -1601,17 +1607,36 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								xmlNodePtr	root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* set up document with empty root node to be the context node */
 | 
				
			||||||
			doc = xmlNewDoc(version);
 | 
								doc = xmlNewDoc(version);
 | 
				
			||||||
			Assert(doc->encoding == NULL);
 | 
								Assert(doc->encoding == NULL);
 | 
				
			||||||
			doc->encoding = xmlStrdup((const xmlChar *) "UTF-8");
 | 
								doc->encoding = xmlStrdup((const xmlChar *) "UTF-8");
 | 
				
			||||||
			doc->standalone = standalone;
 | 
								doc->standalone = standalone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								root = xmlNewNode(NULL, (const xmlChar *) "content-root");
 | 
				
			||||||
 | 
								if (root == NULL || xmlerrcxt->err_occurred)
 | 
				
			||||||
 | 
									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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* allow empty content */
 | 
								/* allow empty content */
 | 
				
			||||||
			if (*(utf8string + count))
 | 
								if (*(utf8string + count))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				res_code = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0,
 | 
									xmlNodePtr	node_list = NULL;
 | 
				
			||||||
													   utf8string + count, NULL);
 | 
									xmlParserErrors res;
 | 
				
			||||||
				if (res_code != 0 || xmlerrcxt->err_occurred)
 | 
					
 | 
				
			||||||
 | 
									res = xmlParseInNodeContext(root,
 | 
				
			||||||
 | 
																(char *) utf8string + count,
 | 
				
			||||||
 | 
																strlen((char *) utf8string + count),
 | 
				
			||||||
 | 
																options,
 | 
				
			||||||
 | 
																&node_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									xmlFreeNodeList(node_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (res != XML_ERR_OK || xmlerrcxt->err_occurred)
 | 
				
			||||||
					xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_CONTENT,
 | 
										xml_ereport(xmlerrcxt, ERROR, ERRCODE_INVALID_XML_CONTENT,
 | 
				
			||||||
								"invalid XML content");
 | 
													"invalid XML content");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -1630,7 +1655,8 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	PG_END_TRY();
 | 
						PG_END_TRY();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xmlFreeParserCtxt(ctxt);
 | 
						if (ctxt != NULL)
 | 
				
			||||||
 | 
							xmlFreeParserCtxt(ctxt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pg_xml_done(xmlerrcxt, false);
 | 
						pg_xml_done(xmlerrcxt, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1811,6 +1837,19 @@ xml_errorHandler(void *data, PgXmlErrorPtr error)
 | 
				
			|||||||
	switch (domain)
 | 
						switch (domain)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case XML_FROM_PARSER:
 | 
							case XML_FROM_PARSER:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * XML_ERR_NOT_WELL_BALANCED is typically reported after some
 | 
				
			||||||
 | 
								 * other, more on-point error.  Furthermore, libxml2 2.13 reports
 | 
				
			||||||
 | 
								 * it under a completely different set of rules than prior
 | 
				
			||||||
 | 
								 * versions.  To avoid cross-version behavioral differences,
 | 
				
			||||||
 | 
								 * suppress it so long as we already logged some error.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								if (error->code == XML_ERR_NOT_WELL_BALANCED &&
 | 
				
			||||||
 | 
									xmlerrcxt->err_occurred)
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								/* fall through */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case XML_FROM_NONE:
 | 
							case XML_FROM_NONE:
 | 
				
			||||||
		case XML_FROM_MEMORY:
 | 
							case XML_FROM_MEMORY:
 | 
				
			||||||
		case XML_FROM_IO:
 | 
							case XML_FROM_IO:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -223,17 +223,11 @@ ERROR:  invalid XML content
 | 
				
			|||||||
DETAIL:  line 1: xmlParseEntityRef: no name
 | 
					DETAIL:  line 1: xmlParseEntityRef: no name
 | 
				
			||||||
<invalidentity>&</invalidentity>
 | 
					<invalidentity>&</invalidentity>
 | 
				
			||||||
                ^
 | 
					                ^
 | 
				
			||||||
line 1: chunk is not well balanced
 | 
					 | 
				
			||||||
<invalidentity>&</invalidentity>
 | 
					 | 
				
			||||||
                                ^
 | 
					 | 
				
			||||||
SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
 | 
					SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
 | 
				
			||||||
ERROR:  invalid XML content
 | 
					ERROR:  invalid XML content
 | 
				
			||||||
DETAIL:  line 1: Entity 'idontexist' not defined
 | 
					DETAIL:  line 1: Entity 'idontexist' not defined
 | 
				
			||||||
<undefinedentity>&idontexist;</undefinedentity>
 | 
					<undefinedentity>&idontexist;</undefinedentity>
 | 
				
			||||||
                             ^
 | 
					                             ^
 | 
				
			||||||
line 1: chunk is not well balanced
 | 
					 | 
				
			||||||
<undefinedentity>&idontexist;</undefinedentity>
 | 
					 | 
				
			||||||
                                               ^
 | 
					 | 
				
			||||||
SELECT xmlparse(content '<invalidns xmlns=''<''/>');
 | 
					SELECT xmlparse(content '<invalidns xmlns=''<''/>');
 | 
				
			||||||
         xmlparse          
 | 
					         xmlparse          
 | 
				
			||||||
---------------------------
 | 
					---------------------------
 | 
				
			||||||
@@ -252,9 +246,6 @@ DETAIL:  line 1: Entity 'idontexist' not defined
 | 
				
			|||||||
<twoerrors>&idontexist;</unbalanced>
 | 
					<twoerrors>&idontexist;</unbalanced>
 | 
				
			||||||
                       ^
 | 
					                       ^
 | 
				
			||||||
line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
 | 
					line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
 | 
				
			||||||
<twoerrors>&idontexist;</unbalanced>
 | 
					 | 
				
			||||||
                                    ^
 | 
					 | 
				
			||||||
line 1: chunk is not well balanced
 | 
					 | 
				
			||||||
<twoerrors>&idontexist;</unbalanced>
 | 
					<twoerrors>&idontexist;</unbalanced>
 | 
				
			||||||
                                    ^
 | 
					                                    ^
 | 
				
			||||||
SELECT xmlparse(content '<nosuchprefix:tag/>');
 | 
					SELECT xmlparse(content '<nosuchprefix:tag/>');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -219,13 +219,11 @@ ERROR:  invalid XML content
 | 
				
			|||||||
DETAIL:  line 1: xmlParseEntityRef: no name
 | 
					DETAIL:  line 1: xmlParseEntityRef: no name
 | 
				
			||||||
<invalidentity>&</invalidentity>
 | 
					<invalidentity>&</invalidentity>
 | 
				
			||||||
                ^
 | 
					                ^
 | 
				
			||||||
line 1: chunk is not well balanced
 | 
					 | 
				
			||||||
SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
 | 
					SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
 | 
				
			||||||
ERROR:  invalid XML content
 | 
					ERROR:  invalid XML content
 | 
				
			||||||
DETAIL:  line 1: Entity 'idontexist' not defined
 | 
					DETAIL:  line 1: Entity 'idontexist' not defined
 | 
				
			||||||
<undefinedentity>&idontexist;</undefinedentity>
 | 
					<undefinedentity>&idontexist;</undefinedentity>
 | 
				
			||||||
                             ^
 | 
					                             ^
 | 
				
			||||||
line 1: chunk is not well balanced
 | 
					 | 
				
			||||||
SELECT xmlparse(content '<invalidns xmlns=''<''/>');
 | 
					SELECT xmlparse(content '<invalidns xmlns=''<''/>');
 | 
				
			||||||
         xmlparse          
 | 
					         xmlparse          
 | 
				
			||||||
---------------------------
 | 
					---------------------------
 | 
				
			||||||
@@ -244,7 +242,6 @@ DETAIL:  line 1: Entity 'idontexist' not defined
 | 
				
			|||||||
<twoerrors>&idontexist;</unbalanced>
 | 
					<twoerrors>&idontexist;</unbalanced>
 | 
				
			||||||
                       ^
 | 
					                       ^
 | 
				
			||||||
line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
 | 
					line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
 | 
				
			||||||
line 1: chunk is not well balanced
 | 
					 | 
				
			||||||
SELECT xmlparse(content '<nosuchprefix:tag/>');
 | 
					SELECT xmlparse(content '<nosuchprefix:tag/>');
 | 
				
			||||||
      xmlparse       
 | 
					      xmlparse       
 | 
				
			||||||
---------------------
 | 
					---------------------
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user