I wrote: > I think we could work around it as attached. This relies on seeing > that the 2.13 code will return a node list if and only if > ctxt->wellFormed is true (and we already eliminated the empty-input > case, so an empty node list shouldn't happen). But it's not a lot > less ugly than your proposal.
> Also, this only fixes the two wrong-output-from-xmlserialize > test cases. I'm not so stressed about the cases where the errdetail > changes, but I think we need to find an answer for the places where > it fails and didn't before, like: > SELECT xmlparse(content '<invalidns xmlns=''<''/>'); > - xmlparse > ---------------------------- > - <invalidns xmlns='<'/> > -(1 row) > - > +ERROR: invalid XML content Oh! That's actually the same bug, and my patch was faulty because I didn't think about the case where the caller of xml_parse passes parsed_nodes = NULL. (And it wasn't doing the right thing in the other case either :-(.) The attached works significantly better, and cleans up these bogus errors. We're still left with missing "chunk is not well balanced" errcontext entries, which we could live without if we have to, but I wonder why those are not there. regards, tom lane
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index d75f765de0..311de91110 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -1837,16 +1837,36 @@ xml_parse(text *data, XmlOptionType xmloption_arg, /* allow empty content */ if (*(utf8string + count)) { + xmlNodePtr node_list = NULL; + res_code = xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, utf8string + count, - parsed_nodes); + &node_list); + + /* + * libxml2 2.13.x incorrectly returns parser errors even if + * the chunk is well-balanced. As a workaround, ignore the + * return code if a node list was returned. + * https://gitlab.gnome.org/GNOME/libxml2/-/issues/765 + */ +#if LIBXML_VERSION >= 21300 + if (res_code > 0 && node_list != NULL) + res_code = 0; +#endif + if (res_code != 0 || xmlerrcxt->err_occurred) { + xmlFreeNodeList(node_list); xml_errsave(escontext, xmlerrcxt, ERRCODE_INVALID_XML_CONTENT, "invalid XML content"); goto fail; } + + if (parsed_nodes != NULL) + *parsed_nodes = node_list; + else + xmlFreeNodeList(node_list); } }