提交 cacd42d6 编写于 作者: T Tom Lane

Rewrite libxml error handling to be more robust.

libxml reports some errors (like invalid xmlns attributes) via the error
handler hook, but still returns a success indicator to the library caller.
This causes us to miss some errors that are important to report.  Since the
"generic" error handler hook doesn't know whether the message it's getting
is for an error, warning, or notice, stop using that and instead start
using the "structured" error handler hook, which gets enough information
to be useful.

While at it, arrange to save and restore the error handler hook setting in
each libxml-using function, rather than assuming we can set and forget the
hook.  This should improve the odds of working nicely with third-party
libraries that also use libxml.

In passing, volatile-ize some local variables that get modified within
PG_TRY blocks.  I noticed this while testing with an older gcc version
than I'd previously tried to compile xml.c with.

Florian Pflug and Tom Lane, with extensive review/testing by Noah Misch
上级 d79a601f
......@@ -23655,6 +23655,75 @@ fi
# Older versions of libxml2 lack the xmlStructuredErrorContext variable
# (which could be a macro referring to a function, if threading is enabled)
if test "$with_libxml" = yes ; then
{ $as_echo "$as_me:$LINENO: checking for xmlStructuredErrorContext" >&5
$as_echo_n "checking for xmlStructuredErrorContext... " >&6; }
if test "${pgac_cv_libxml_structerrctx+set}" = set; then
$as_echo_n "(cached) " >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <libxml/globals.h>
void *globptr;
int
main ()
{
globptr = xmlStructuredErrorContext
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
}; then
pgac_cv_libxml_structerrctx=yes
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
pgac_cv_libxml_structerrctx=no
fi
rm -rf conftest.dSYM
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:$LINENO: result: $pgac_cv_libxml_structerrctx" >&5
$as_echo "$pgac_cv_libxml_structerrctx" >&6; }
if test x"$pgac_cv_libxml_structerrctx" = x"yes"; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_XMLSTRUCTUREDERRORCONTEXT 1
_ACEOF
fi
fi
# This test makes sure that run tests work at all. Sometimes a shared
# library is found by the linker, but the runtime linker can't find it.
# This check should come after all modifications of compiler or linker
......
......@@ -1519,6 +1519,23 @@ AC_SUBST(LDAP_LIBS_FE)
AC_SUBST(LDAP_LIBS_BE)
# Older versions of libxml2 lack the xmlStructuredErrorContext variable
# (which could be a macro referring to a function, if threading is enabled)
if test "$with_libxml" = yes ; then
AC_CACHE_CHECK([for xmlStructuredErrorContext], pgac_cv_libxml_structerrctx,
[AC_TRY_LINK([#include <libxml/globals.h>
void *globptr;],
[globptr = xmlStructuredErrorContext],
[pgac_cv_libxml_structerrctx=yes],
[pgac_cv_libxml_structerrctx=no])])
if test x"$pgac_cv_libxml_structerrctx" = x"yes"; then
AC_DEFINE(HAVE_XMLSTRUCTUREDERRORCONTEXT,
1,
[Define to 1 if your libxml has xmlStructuredErrorContext.])
fi
fi
# This test makes sure that run tests work at all. Sometimes a shared
# library is found by the linker, but the runtime linker can't find it.
# This check should come after all modifications of compiler or linker
......
......@@ -38,7 +38,7 @@ Datum xpath_table(PG_FUNCTION_ARGS);
/* exported for use by xslt_proc.c */
void pgxml_parser_init(void);
PgXmlErrorContext *pgxml_parser_init(PgXmlStrictness strictness);
/* workspace for pgxml_xpath() */
......@@ -68,18 +68,27 @@ static void cleanup_workspace(xpath_workspace *workspace);
/*
* Initialize for xml parsing.
*
* As with the underlying pg_xml_init function, calls to this MUST be followed
* by a PG_TRY block that guarantees that pg_xml_done is called.
*/
void
pgxml_parser_init(void)
PgXmlErrorContext *
pgxml_parser_init(PgXmlStrictness strictness)
{
PgXmlErrorContext *xmlerrcxt;
/* Set up error handling (we share the core's error handler) */
pg_xml_init();
xmlerrcxt = pg_xml_init(strictness);
/* Note: we're assuming an elog cannot be thrown by the following calls */
/* Initialize libxml */
xmlInitParser();
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
return xmlerrcxt;
}
......@@ -98,16 +107,33 @@ Datum
xml_is_well_formed(PG_FUNCTION_ARGS)
{
text *t = PG_GETARG_TEXT_P(0); /* document buffer */
bool result = false;
int32 docsize = VARSIZE(t) - VARHDRSZ;
xmlDocPtr doctree;
PgXmlErrorContext *xmlerrcxt;
xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
PG_TRY();
{
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
result = (doctree != NULL);
if (doctree != NULL)
xmlFreeDoc(doctree);
}
PG_CATCH();
{
pg_xml_done(xmlerrcxt, true);
pgxml_parser_init();
PG_RE_THROW();
}
PG_END_TRY();
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
if (doctree == NULL)
PG_RETURN_BOOL(false); /* i.e. not well-formed */
xmlFreeDoc(doctree);
PG_RETURN_BOOL(true);
pg_xml_done(xmlerrcxt, false);
PG_RETURN_BOOL(result);
}
......@@ -399,41 +425,52 @@ static xmlXPathObjectPtr
pgxml_xpath(text *document, xmlChar *xpath, xpath_workspace *workspace)
{
int32 docsize = VARSIZE(document) - VARHDRSZ;
xmlXPathObjectPtr res;
PgXmlErrorContext *xmlerrcxt;
xmlXPathCompExprPtr comppath;
workspace->doctree = NULL;
workspace->ctxt = NULL;
workspace->res = NULL;
pgxml_parser_init();
xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
workspace->doctree = xmlParseMemory((char *) VARDATA(document), docsize);
if (workspace->doctree == NULL)
return NULL; /* not well-formed */
PG_TRY();
{
workspace->doctree = xmlParseMemory((char *) VARDATA(document),
docsize);
if (workspace->doctree != NULL)
{
workspace->ctxt = xmlXPathNewContext(workspace->doctree);
workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
workspace->ctxt = xmlXPathNewContext(workspace->doctree);
workspace->ctxt->node = xmlDocGetRootElement(workspace->doctree);
/* compile the path */
comppath = xmlXPathCompile(xpath);
if (comppath == NULL)
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"XPath Syntax Error");
/* compile the path */
comppath = xmlXPathCompile(xpath);
if (comppath == NULL)
/* Now evaluate the path expression. */
workspace->res = xmlXPathCompiledEval(comppath, workspace->ctxt);
xmlXPathFreeCompExpr(comppath);
}
}
PG_CATCH();
{
cleanup_workspace(workspace);
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"XPath Syntax Error");
}
/* Now evaluate the path expression. */
res = xmlXPathCompiledEval(comppath, workspace->ctxt);
workspace->res = res;
pg_xml_done(xmlerrcxt, true);
xmlXPathFreeCompExpr(comppath);
PG_RE_THROW();
}
PG_END_TRY();
if (res == NULL)
if (workspace->res == NULL)
cleanup_workspace(workspace);
return res;
pg_xml_done(xmlerrcxt, false);
return workspace->res;
}
/* Clean up after processing the result of pgxml_xpath() */
......@@ -534,6 +571,8 @@ xpath_table(PG_FUNCTION_ARGS)
* document */
bool had_values; /* To determine end of nodeset results */
StringInfoData query_buf;
PgXmlErrorContext *xmlerrcxt;
volatile xmlDocPtr doctree = NULL;
/* We only have a valid tuple description in table function mode */
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
......@@ -659,14 +698,15 @@ xpath_table(PG_FUNCTION_ARGS)
* Setup the parser. This should happen after we are done evaluating the
* query, in case it calls functions that set up libxml differently.
*/
pgxml_parser_init();
xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
PG_TRY();
{
/* For each row i.e. document returned from SPI */
for (i = 0; i < proc; i++)
{
char *pkey;
char *xmldoc;
xmlDocPtr doctree;
xmlXPathContextPtr ctxt;
xmlXPathObjectPtr res;
xmlChar *resstr;
......@@ -718,11 +758,9 @@ xpath_table(PG_FUNCTION_ARGS)
/* compile the path */
comppath = xmlXPathCompile(xpaths[j]);
if (comppath == NULL)
{
xmlFreeDoc(doctree);
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
xml_ereport(xmlerrcxt, ERROR,
ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"XPath Syntax Error");
}
/* Now evaluate the path expression. */
res = xmlXPathCompiledEval(comppath, ctxt);
......@@ -737,8 +775,7 @@ xpath_table(PG_FUNCTION_ARGS)
if (res->nodesetval != NULL &&
rownr < res->nodesetval->nodeNr)
{
resstr =
xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]);
resstr = xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]);
had_values = true;
}
else
......@@ -776,13 +813,31 @@ xpath_table(PG_FUNCTION_ARGS)
} while (had_values);
}
xmlFreeDoc(doctree);
if (doctree != NULL)
xmlFreeDoc(doctree);
doctree = NULL;
if (pkey)
pfree(pkey);
if (xmldoc)
pfree(xmldoc);
}
}
PG_CATCH();
{
if (doctree != NULL)
xmlFreeDoc(doctree);
pg_xml_done(xmlerrcxt, true);
PG_RE_THROW();
}
PG_END_TRY();
if (doctree != NULL)
xmlFreeDoc(doctree);
pg_xml_done(xmlerrcxt, false);
tuplestore_donestoring(tupstore);
......
......@@ -38,7 +38,7 @@ Datum xslt_process(PG_FUNCTION_ARGS);
#ifdef USE_LIBXSLT
/* declarations to come from xpath.c */
extern void pgxml_parser_init(void);
extern PgXmlErrorContext *pgxml_parser_init(PgXmlStrictness strictness);
/* local defs */
static const char **parse_params(text *paramstr);
......@@ -56,13 +56,14 @@ xslt_process(PG_FUNCTION_ARGS)
text *ssheet = PG_GETARG_TEXT_P(1);
text *paramstr;
const char **params;
xsltStylesheetPtr stylesheet = NULL;
xmlDocPtr doctree;
xmlDocPtr restree;
xmlDocPtr ssdoc = NULL;
xmlChar *resstr;
int resstat;
int reslen;
PgXmlErrorContext *xmlerrcxt;
volatile xsltStylesheetPtr stylesheet = NULL;
volatile xmlDocPtr doctree = NULL;
volatile xmlDocPtr restree = NULL;
volatile xmlDocPtr ssdoc = NULL;
volatile int resstat = -1;
xmlChar *resstr = NULL;
int reslen = 0;
if (fcinfo->nargs == 3)
{
......@@ -77,9 +78,11 @@ xslt_process(PG_FUNCTION_ARGS)
}
/* Setup parser */
pgxml_parser_init();
xmlerrcxt = pgxml_parser_init(PG_XML_STRICTNESS_LEGACY);
/* Check to see if document is a file or a literal */
PG_TRY();
{
/* Check to see if document is a file or a literal */
if (VARDATA(doct)[0] == '<')
doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ);
......@@ -87,7 +90,7 @@ xslt_process(PG_FUNCTION_ARGS)
doctree = xmlParseFile(text_to_cstring(doct));
if (doctree == NULL)
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"error parsing XML document");
/* Same for stylesheet */
......@@ -96,35 +99,44 @@ xslt_process(PG_FUNCTION_ARGS)
ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
VARSIZE(ssheet) - VARHDRSZ);
if (ssdoc == NULL)
{
xmlFreeDoc(doctree);
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"error parsing stylesheet as XML document");
}
stylesheet = xsltParseStylesheetDoc(ssdoc);
}
else
stylesheet = xsltParseStylesheetFile((xmlChar *) text_to_cstring(ssheet));
if (stylesheet == NULL)
{
xmlFreeDoc(doctree);
xsltCleanupGlobals();
xml_ereport(ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
xml_ereport(xmlerrcxt, ERROR, ERRCODE_EXTERNAL_ROUTINE_EXCEPTION,
"failed to parse stylesheet");
}
restree = xsltApplyStylesheet(stylesheet, doctree, params);
resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet);
}
PG_CATCH();
{
if (stylesheet != NULL)
xsltFreeStylesheet(stylesheet);
if (restree != NULL)
xmlFreeDoc(restree);
if (doctree != NULL)
xmlFreeDoc(doctree);
xsltCleanupGlobals();
pg_xml_done(xmlerrcxt, true);
PG_RE_THROW();
}
PG_END_TRY();
xsltFreeStylesheet(stylesheet);
xmlFreeDoc(restree);
xmlFreeDoc(doctree);
xsltCleanupGlobals();
pg_xml_done(xmlerrcxt, false);
if (resstat < 0)
PG_RETURN_NULL();
......
此差异已折叠。
......@@ -671,6 +671,9 @@
/* Define to 1 if you have the <winldap.h> header file. */
#undef HAVE_WINLDAP_H
/* Define to 1 if your libxml has xmlStructuredErrorContext. */
#undef HAVE_XMLSTRUCTUREDERRORCONTEXT
/* Define to the appropriate snprintf format for 64-bit ints. */
#undef INT64_FORMAT
......
......@@ -21,6 +21,31 @@
typedef struct varlena xmltype;
typedef enum
{
XML_STANDALONE_YES,
XML_STANDALONE_NO,
XML_STANDALONE_NO_VALUE,
XML_STANDALONE_OMITTED
} XmlStandaloneType;
typedef enum
{
XMLBINARY_BASE64,
XMLBINARY_HEX
} XmlBinaryType;
typedef enum
{
PG_XML_STRICTNESS_LEGACY, /* ignore errors unless function result
* indicates error condition */
PG_XML_STRICTNESS_WELLFORMED, /* ignore non-parser messages */
PG_XML_STRICTNESS_ALL /* report all notices/warnings/errors */
} PgXmlStrictness;
/* struct PgXmlErrorContext is private to xml.c */
typedef struct PgXmlErrorContext PgXmlErrorContext;
#define DatumGetXmlP(X) ((xmltype *) PG_DETOAST_DATUM(X))
#define XmlPGetDatum(X) PointerGetDatum(X)
......@@ -60,16 +85,13 @@ extern Datum database_to_xml(PG_FUNCTION_ARGS);
extern Datum database_to_xmlschema(PG_FUNCTION_ARGS);
extern Datum database_to_xml_and_xmlschema(PG_FUNCTION_ARGS);
typedef enum
{
XML_STANDALONE_YES,
XML_STANDALONE_NO,
XML_STANDALONE_NO_VALUE,
XML_STANDALONE_OMITTED
} XmlStandaloneType;
extern void pg_xml_init_library(void);
extern PgXmlErrorContext *pg_xml_init(PgXmlStrictness strictness);
extern void pg_xml_done(PgXmlErrorContext *errcxt, bool isError);
extern bool pg_xml_error_occurred(PgXmlErrorContext *errcxt);
extern void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode,
const char *msg);
extern void pg_xml_init(void);
extern void xml_ereport(int level, int sqlcode, const char *msg);
extern xmltype *xmlconcat(List *args);
extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
extern xmltype *xmlparse(text *data, XmlOptionType xmloption, bool preserve_whitespace);
......@@ -83,12 +105,6 @@ extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped, boo
extern char *map_xml_name_to_sql_identifier(char *name);
extern char *map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings);
typedef enum
{
XMLBINARY_BASE64,
XMLBINARY_HEX
} XmlBinaryType;
extern int xmlbinary; /* XmlBinaryType, but int for guc enum */
extern int xmloption; /* XmlOptionType, but int for guc enum */
......
......@@ -8,7 +8,7 @@ INSERT INTO xmltest VALUES (3, '<wrong');
ERROR: invalid XML content
LINE 1: INSERT INTO xmltest VALUES (3, '<wrong');
^
DETAIL: Entity: line 1: parser error : Couldn't find end of Start Tag wrong line 1
DETAIL: line 1: Couldn't find end of Start Tag wrong line 1
<wrong
^
SELECT * FROM xmltest;
......@@ -62,7 +62,7 @@ SELECT xmlconcat('bad', '<syntax');
ERROR: invalid XML content
LINE 1: SELECT xmlconcat('bad', '<syntax');
^
DETAIL: Entity: line 1: parser error : Couldn't find end of Start Tag syntax line 1
DETAIL: line 1: Couldn't find end of Start Tag syntax line 1
<syntax
^
SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
......@@ -206,9 +206,54 @@ SELECT xmlparse(content '<abc>x</abc>');
<abc>x</abc>
(1 row)
SELECT xmlparse(content '<invalidentity>&</invalidentity>');
ERROR: invalid XML content
DETAIL: line 1: xmlParseEntityRef: no name
<invalidentity>&</invalidentity>
^
line 1: chunk is not well balanced
<invalidentity>&</invalidentity>
^
SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
ERROR: invalid XML content
DETAIL: line 1: Entity 'idontexist' not defined
<undefinedentity>&idontexist;</undefinedentity>
^
line 1: chunk is not well balanced
<undefinedentity>&idontexist;</undefinedentity>
^
SELECT xmlparse(content '<invalidns xmlns=''&lt;''/>');
xmlparse
---------------------------
<invalidns xmlns='&lt;'/>
(1 row)
SELECT xmlparse(content '<relativens xmlns=''relative''/>');
xmlparse
--------------------------------
<relativens xmlns='relative'/>
(1 row)
SELECT xmlparse(content '<twoerrors>&idontexist;</unbalanced>');
ERROR: invalid XML content
DETAIL: line 1: Entity 'idontexist' not defined
<twoerrors>&idontexist;</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>
^
SELECT xmlparse(content '<nosuchprefix:tag/>');
xmlparse
---------------------
<nosuchprefix:tag/>
(1 row)
SELECT xmlparse(document 'abc');
ERROR: invalid XML document
DETAIL: Entity: line 1: parser error : Start tag expected, '<' not found
DETAIL: line 1: Start tag expected, '<' not found
abc
^
SELECT xmlparse(document '<abc>x</abc>');
......@@ -217,6 +262,48 @@ SELECT xmlparse(document '<abc>x</abc>');
<abc>x</abc>
(1 row)
SELECT xmlparse(document '<invalidentity>&</abc>');
ERROR: invalid XML document
DETAIL: line 1: xmlParseEntityRef: no name
<invalidentity>&</abc>
^
line 1: Opening and ending tag mismatch: invalidentity line 1 and abc
<invalidentity>&</abc>
^
SELECT xmlparse(document '<undefinedentity>&idontexist;</abc>');
ERROR: invalid XML document
DETAIL: line 1: Entity 'idontexist' not defined
<undefinedentity>&idontexist;</abc>
^
line 1: Opening and ending tag mismatch: undefinedentity line 1 and abc
<undefinedentity>&idontexist;</abc>
^
SELECT xmlparse(document '<invalidns xmlns=''&lt;''/>');
xmlparse
---------------------------
<invalidns xmlns='&lt;'/>
(1 row)
SELECT xmlparse(document '<relativens xmlns=''relative''/>');
xmlparse
--------------------------------
<relativens xmlns='relative'/>
(1 row)
SELECT xmlparse(document '<twoerrors>&idontexist;</unbalanced>');
ERROR: invalid XML document
DETAIL: line 1: Entity 'idontexist' not defined
<twoerrors>&idontexist;</unbalanced>
^
line 1: Opening and ending tag mismatch: twoerrors line 1 and unbalanced
<twoerrors>&idontexist;</unbalanced>
^
SELECT xmlparse(document '<nosuchprefix:tag/>');
xmlparse
---------------------
<nosuchprefix:tag/>
(1 row)
SELECT xmlpi(name foo);
xmlpi
---------
......@@ -379,7 +466,7 @@ SELECT '<>' IS NOT DOCUMENT;
ERROR: invalid XML content
LINE 1: SELECT '<>' IS NOT DOCUMENT;
^
DETAIL: Entity: line 1: parser error : StartTag: invalid element name
DETAIL: line 1: StartTag: invalid element name
<>
^
SELECT xmlagg(data) FROM xmltest;
......@@ -425,7 +512,7 @@ EXECUTE foo ('bad');
ERROR: invalid XML document
LINE 1: EXECUTE foo ('bad');
^
DETAIL: Entity: line 1: parser error : Start tag expected, '<' not found
DETAIL: line 1: Start tag expected, '<' not found
bad
^
SET XML OPTION CONTENT;
......@@ -679,6 +766,36 @@ SELECT xml_is_well_formed('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</p
t
(1 row)
SELECT xml_is_well_formed('<invalidentity>&</abc>');
xml_is_well_formed
--------------------
f
(1 row)
SELECT xml_is_well_formed('<undefinedentity>&idontexist;</abc>');
xml_is_well_formed
--------------------
f
(1 row)
SELECT xml_is_well_formed('<invalidns xmlns=''&lt;''/>');
xml_is_well_formed
--------------------
t
(1 row)
SELECT xml_is_well_formed('<relativens xmlns=''relative''/>');
xml_is_well_formed
--------------------
t
(1 row)
SELECT xml_is_well_formed('<twoerrors>&idontexist;</unbalanced>');
xml_is_well_formed
--------------------
f
(1 row)
SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');
xml_is_well_formed
......@@ -686,3 +803,36 @@ SELECT xml_is_well_formed('abc');
t
(1 row)
-- Since xpath() deals with namespaces, it's a bit stricter about
-- what's well-formed and what's not. If we don't obey these rules
-- (i.e. ignore namespace-related errors from libxml), xpath()
-- fails in subtle ways. The following would for example produce
-- the xml value
-- <invalidns xmlns='<'/>
-- which is invalid because '<' may not appear un-escaped in
-- attribute values.
-- Since different libxml versions emit slightly different
-- error messages, we suppress the DETAIL in this test.
\set VERBOSITY terse
SELECT xpath('/*', '<invalidns xmlns=''&lt;''/>');
ERROR: could not parse XML document
\set VERBOSITY default
-- Again, the XML isn't well-formed for namespace purposes
SELECT xpath('/*', '<nosuchprefix:tag/>');
ERROR: could not parse XML document
DETAIL: line 1: Namespace prefix nosuchprefix on tag is not defined
<nosuchprefix:tag/>
^
CONTEXT: SQL function "xpath" statement 1
-- XPath deprecates relative namespaces, but they're not supposed to
-- throw an error, only a warning.
SELECT xpath('/*', '<relativens xmlns=''relative''/>');
WARNING: line 1: xmlns: URI relative is not absolute
<relativens xmlns='relative'/>
^
CONTEXT: SQL function "xpath" statement 1
xpath
--------------------------------------
{"<relativens xmlns=\"relative\"/>"}
(1 row)
......@@ -172,6 +172,30 @@ SELECT xmlparse(content '<abc>x</abc>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(content '<invalidentity>&</invalidentity>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(content '<invalidns xmlns=''&lt;''/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(content '<relativens xmlns=''relative''/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(content '<twoerrors>&idontexist;</unbalanced>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(content '<nosuchprefix:tag/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(document 'abc');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
......@@ -180,6 +204,30 @@ SELECT xmlparse(document '<abc>x</abc>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(document '<invalidentity>&</abc>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(document '<undefinedentity>&idontexist;</abc>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(document '<invalidns xmlns=''&lt;''/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(document '<relativens xmlns=''relative''/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(document '<twoerrors>&idontexist;</unbalanced>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlparse(document '<nosuchprefix:tag/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xmlpi(name foo);
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
......@@ -627,8 +675,57 @@ SELECT xml_is_well_formed('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</p
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xml_is_well_formed('<invalidentity>&</abc>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xml_is_well_formed('<undefinedentity>&idontexist;</abc>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xml_is_well_formed('<invalidns xmlns=''&lt;''/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xml_is_well_formed('<relativens xmlns=''relative''/>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SELECT xml_is_well_formed('<twoerrors>&idontexist;</unbalanced>');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');
ERROR: unsupported XML feature
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
-- Since xpath() deals with namespaces, it's a bit stricter about
-- what's well-formed and what's not. If we don't obey these rules
-- (i.e. ignore namespace-related errors from libxml), xpath()
-- fails in subtle ways. The following would for example produce
-- the xml value
-- <invalidns xmlns='<'/>
-- which is invalid because '<' may not appear un-escaped in
-- attribute values.
-- Since different libxml versions emit slightly different
-- error messages, we suppress the DETAIL in this test.
\set VERBOSITY terse
SELECT xpath('/*', '<invalidns xmlns=''&lt;''/>');
ERROR: unsupported XML feature at character 20
\set VERBOSITY default
-- Again, the XML isn't well-formed for namespace purposes
SELECT xpath('/*', '<nosuchprefix:tag/>');
ERROR: unsupported XML feature
LINE 1: SELECT xpath('/*', '<nosuchprefix:tag/>');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
-- XPath deprecates relative namespaces, but they're not supposed to
-- throw an error, only a warning.
SELECT xpath('/*', '<relativens xmlns=''relative''/>');
ERROR: unsupported XML feature
LINE 1: SELECT xpath('/*', '<relativens xmlns=''relative''/>');
^
DETAIL: This functionality requires the server to be built with libxml support.
HINT: You need to rebuild PostgreSQL using --with-libxml.
......@@ -62,9 +62,21 @@ SELECT xmlelement(name foo, xmlattributes('<>&"''' as funny, xml 'b<a/>r' as fun
SELECT xmlparse(content 'abc');
SELECT xmlparse(content '<abc>x</abc>');
SELECT xmlparse(content '<invalidentity>&</invalidentity>');
SELECT xmlparse(content '<undefinedentity>&idontexist;</undefinedentity>');
SELECT xmlparse(content '<invalidns xmlns=''&lt;''/>');
SELECT xmlparse(content '<relativens xmlns=''relative''/>');
SELECT xmlparse(content '<twoerrors>&idontexist;</unbalanced>');
SELECT xmlparse(content '<nosuchprefix:tag/>');
SELECT xmlparse(document 'abc');
SELECT xmlparse(document '<abc>x</abc>');
SELECT xmlparse(document '<invalidentity>&</abc>');
SELECT xmlparse(document '<undefinedentity>&idontexist;</abc>');
SELECT xmlparse(document '<invalidns xmlns=''&lt;''/>');
SELECT xmlparse(document '<relativens xmlns=''relative''/>');
SELECT xmlparse(document '<twoerrors>&idontexist;</unbalanced>');
SELECT xmlparse(document '<nosuchprefix:tag/>');
SELECT xmlpi(name foo);
......@@ -208,6 +220,32 @@ SELECT xml_is_well_formed('<foo><bar>baz</foo>');
SELECT xml_is_well_formed('<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>');
SELECT xml_is_well_formed('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</my:foo>');
SELECT xml_is_well_formed('<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</pg:foo>');
SELECT xml_is_well_formed('<invalidentity>&</abc>');
SELECT xml_is_well_formed('<undefinedentity>&idontexist;</abc>');
SELECT xml_is_well_formed('<invalidns xmlns=''&lt;''/>');
SELECT xml_is_well_formed('<relativens xmlns=''relative''/>');
SELECT xml_is_well_formed('<twoerrors>&idontexist;</unbalanced>');
SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');
-- Since xpath() deals with namespaces, it's a bit stricter about
-- what's well-formed and what's not. If we don't obey these rules
-- (i.e. ignore namespace-related errors from libxml), xpath()
-- fails in subtle ways. The following would for example produce
-- the xml value
-- <invalidns xmlns='<'/>
-- which is invalid because '<' may not appear un-escaped in
-- attribute values.
-- Since different libxml versions emit slightly different
-- error messages, we suppress the DETAIL in this test.
\set VERBOSITY terse
SELECT xpath('/*', '<invalidns xmlns=''&lt;''/>');
\set VERBOSITY default
-- Again, the XML isn't well-formed for namespace purposes
SELECT xpath('/*', '<nosuchprefix:tag/>');
-- XPath deprecates relative namespaces, but they're not supposed to
-- throw an error, only a warning.
SELECT xpath('/*', '<relativens xmlns=''relative''/>');
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册