From aaf15e5c1cf8d2c27d2f9841343f00027762cb4e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 20 Jul 2011 18:44:09 -0400 Subject: [PATCH] Ensure that xpath() escapes special characters in string values. Without this it's possible for the output to not be legal XML, as illustrated by the added regression test cases. NB: this change will need to be called out as an incompatibility in the 9.2 release notes, since it's possible somebody was relying on the old behavior, even though it's clearly wrong. Florian Pflug, reviewed by Radoslaw Smogura --- src/backend/utils/adt/xml.c | 6 +++++- src/test/regress/expected/xml.out | 12 ++++++++++++ src/test/regress/expected/xml_1.out | 12 ++++++++++++ src/test/regress/sql/xml.sql | 2 ++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 6786cd91bb..c07232575e 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -3537,7 +3537,11 @@ xml_xmlnodetoxmltype(xmlNodePtr cur) str = xmlXPathCastNodeToString(cur); PG_TRY(); { - result = (xmltype *) cstring_to_text((char *) str); + /* Here we rely on XML having the same representation as TEXT */ + char *escaped = escape_xml((char *) str); + + result = (xmltype *) cstring_to_text(escaped); + pfree(escaped); } PG_CATCH(); { diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index 379777aced..5cd602107b 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -589,6 +589,18 @@ SELECT xpath('//b', 'one two three etc'); {two,etc} (1 row) +SELECT xpath('//text()', '<'); + xpath +-------- + {<} +(1 row) + +SELECT xpath('//@value', ''); + xpath +-------- + {<} +(1 row) + -- Test xmlexists and xpath_exists SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF 'Bidford-on-AvonCwmbranBristol'); xmlexists diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index 1f17bffc0b..53675f5536 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -504,6 +504,18 @@ LINE 1: SELECT xpath('//b', 'one two three etc'... ^ DETAIL: This functionality requires the server to be built with libxml support. HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT xpath('//text()', '<'); +ERROR: unsupported XML feature +LINE 1: SELECT xpath('//text()', '<'); + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. +SELECT xpath('//@value', ''); +ERROR: unsupported XML feature +LINE 1: SELECT xpath('//@value', ''); + ^ +DETAIL: This functionality requires the server to be built with libxml support. +HINT: You need to rebuild PostgreSQL using --with-libxml. -- Test xmlexists and xpath_exists SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF 'Bidford-on-AvonCwmbranBristol'); ERROR: unsupported XML feature diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index f4e423618e..3270e15721 100644 --- a/src/test/regress/sql/xml.sql +++ b/src/test/regress/sql/xml.sql @@ -175,6 +175,8 @@ SELECT xpath('', ''); SELECT xpath('//text()', 'number one'); SELECT xpath('//loc:piece/@id', 'number one', ARRAY[ARRAY['loc', 'http://127.0.0.1']]); SELECT xpath('//b', 'one two three etc'); +SELECT xpath('//text()', '<'); +SELECT xpath('//@value', ''); -- Test xmlexists and xpath_exists SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF 'Bidford-on-AvonCwmbranBristol'); -- GitLab