Clean up dubious error handling in wellformed_xml().

This ancient bit of code was summarily trapping any ereport longjmp
whatsoever and assuming that it must represent an invalid-XML report.
It's not really appropriate to handle OOM-like situations that way:
maybe the input is valid or maybe not, but we couldn't find out.
And it'd be a seriously bad idea to ignore, say, a query cancel
error that way.  (Perhaps that can't happen because there is no
CHECK_FOR_INTERRUPTS anywhere within xml_parse, but even if that's
true today it's obviously a very fragile assumption.)

But in the wake of the previous commit, we can drop the PG_TRY
here altogether, and use the soft error mechanism to catch only
the kinds of errors that are legitimate to treat as invalid-XML.

(This is our first use of the soft error mechanism for something
not directly related to a datatype input function.  It won't be
the last.)

xml_is_document can be converted in the same way.  That one is
not actively broken, because it was checking specifically for
ERRCODE_INVALID_XML_DOCUMENT rather than trapping everything;
but the code is still shorter and probably faster this way.

Discussion: https://postgr.es/m/3564577.1671142683@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2022-12-16 11:10:36 -05:00
parent 37bef842f5
commit c4939f1215
1 changed files with 17 additions and 47 deletions

View File

@ -81,6 +81,7 @@
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/execnodes.h"
#include "nodes/miscnodes.h"
#include "nodes/nodeFuncs.h"
#include "utils/array.h"
#include "utils/builtins.h"
@ -894,41 +895,18 @@ bool
xml_is_document(xmltype *arg)
{
#ifdef USE_LIBXML
bool result;
volatile xmlDocPtr doc = NULL;
MemoryContext ccxt = CurrentMemoryContext;
/* We want to catch ereport(INVALID_XML_DOCUMENT) and return false */
PG_TRY();
{
doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
GetDatabaseEncoding(), NULL);
result = true;
}
PG_CATCH();
{
ErrorData *errdata;
MemoryContext ecxt;
ecxt = MemoryContextSwitchTo(ccxt);
errdata = CopyErrorData();
if (errdata->sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)
{
FlushErrorState();
result = false;
}
else
{
MemoryContextSwitchTo(ecxt);
PG_RE_THROW();
}
}
PG_END_TRY();
xmlDocPtr doc;
ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* We'll report "true" if no soft error is reported by xml_parse().
*/
doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
GetDatabaseEncoding(), (Node *) &escontext);
if (doc)
xmlFreeDoc(doc);
return result;
return !escontext.error_occurred;
#else /* not USE_LIBXML */
NO_XML_SUPPORT();
return false;
@ -4320,26 +4298,18 @@ xpath_exists(PG_FUNCTION_ARGS)
static bool
wellformed_xml(text *data, XmlOptionType xmloption_arg)
{
bool result;
volatile xmlDocPtr doc = NULL;
/* We want to catch any exceptions and return false */
PG_TRY();
{
doc = xml_parse(data, xmloption_arg, true, GetDatabaseEncoding(), NULL);
result = true;
}
PG_CATCH();
{
FlushErrorState();
result = false;
}
PG_END_TRY();
xmlDocPtr doc;
ErrorSaveContext escontext = {T_ErrorSaveContext};
/*
* We'll report "true" if no soft error is reported by xml_parse().
*/
doc = xml_parse(data, xmloption_arg, true,
GetDatabaseEncoding(), (Node *) &escontext);
if (doc)
xmlFreeDoc(doc);
return result;
return !escontext.error_occurred;
}
#endif