diff options
author | Tom Lane | 2011-07-20 17:03:12 +0000 |
---|---|---|
committer | Tom Lane | 2011-07-20 17:03:49 +0000 |
commit | cacd42d62cb2ddf32135b151f627780a5509780f (patch) | |
tree | 5b46e972260f1c12c777cb4dd071c4b29ee84c0d /src/test | |
parent | d79a601fd9ec59772395d16b33fe79296021a350 (diff) |
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
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/regress/expected/xml.out | 160 | ||||
-rw-r--r-- | src/test/regress/expected/xml_1.out | 97 | ||||
-rw-r--r-- | src/test/regress/sql/xml.sql | 38 |
3 files changed, 290 insertions, 5 deletions
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index eaa5a74ef07..379777aced8 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -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=''<''/>'); + xmlparse +--------------------------- + <invalidns xmlns='<'/> +(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=''<''/>'); + xmlparse +--------------------------- + <invalidns xmlns='<'/> +(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=''<''/>'); + 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=''<''/>'); +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) + diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index 711b4358a25..1f17bffc0b2 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -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=''<''/>'); +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=''<''/>'); +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=''<''/>'); +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=''<''/>'); +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. diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index 717a1e7170e..f4e423618ec 100644 --- a/src/test/regress/sql/xml.sql +++ b/src/test/regress/sql/xml.sql @@ -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=''<''/>'); +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=''<''/>'); +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=''<''/>'); +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=''<''/>'); +\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''/>'); |