]> granicus.if.org Git - postgresql/commitdiff
Fix xmlattribute escaping XML special characters twice (bug #4822).
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 9 Jun 2009 22:00:57 +0000 (22:00 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 9 Jun 2009 22:00:57 +0000 (22:00 +0000)
Author: Itagaki Takahiro <itagaki.takahiro@oss.ntt.co.jp>

src/backend/executor/execQual.c
src/backend/utils/adt/xml.c
src/include/utils/xml.h
src/test/regress/expected/xml.out
src/test/regress/expected/xml_1.out
src/test/regress/sql/xml.sql

index c7bfe7c76ca6b926f2dcbe1eee05b3a0b8b6ecc0..65bf01c6a8e197d46902b2570292c2122438b422 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.247 2009/06/04 18:33:07 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.248 2009/06/09 22:00:57 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3243,7 +3243,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
                                {
                                        appendStringInfo(&buf, "<%s>%s</%s>",
                                                                         argname,
-                                                                        map_sql_value_to_xml_value(value, exprType((Node *) e->expr)),
+                                                                        map_sql_value_to_xml_value(value, exprType((Node *) e->expr), true),
                                                                         argname);
                                        *isNull = false;
                                }
index 57e9595af8d35316774388aa2b0e385908c36bd0..fca92e867d08cbdc1cce73037a83622d0f928571 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.89 2009/06/08 21:32:33 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.90 2009/06/09 22:00:57 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -569,7 +569,7 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
                if (isnull)
                        str = NULL;
                else
-                       str = map_sql_value_to_xml_value(value, exprType((Node *) e->expr));
+                       str = map_sql_value_to_xml_value(value, exprType((Node *) e->expr), false);
                named_arg_strings = lappend(named_arg_strings, str);
                i++;
        }
@@ -587,7 +587,7 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
                if (!isnull)
                {
                        str = map_sql_value_to_xml_value(value,
-                                                                                        exprType((Node *) e->expr));
+                                                                                        exprType((Node *) e->expr), true);
                        arg_strings = lappend(arg_strings, str);
                }
        }
@@ -1580,9 +1580,18 @@ map_xml_name_to_sql_identifier(char *name)
 
 /*
  * Map SQL value to XML value; see SQL/XML:2003 section 9.16.
+ *
+ * When xml_escape_strings is true, then certain characters in string
+ * values are replaced by entity references (&lt; etc.), as specified
+ * in SQL/XML:2003 section 9.16 GR 8) ii).  This is normally what is
+ * wanted.  The false case is mainly useful when the resulting value
+ * is used with xmlTextWriterWriteAttribute() to write out an
+ * attribute, because that function does the escaping itself.  The SQL
+ * standard of 2003 is somewhat buggy in this regard, so we do our
+ * best to make sense.
  */
 char *
-map_sql_value_to_xml_value(Datum value, Oid type)
+map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
 {
        StringInfoData buf;
 
@@ -1616,7 +1625,7 @@ map_sql_value_to_xml_value(Datum value, Oid type)
                        appendStringInfoString(&buf, "<element>");
                        appendStringInfoString(&buf,
                                                                   map_sql_value_to_xml_value(elem_values[i],
-                                                                                                                         elmtype));
+                                                                                                                         elmtype, true));
                        appendStringInfoString(&buf, "</element>");
                }
 
@@ -1774,8 +1783,8 @@ map_sql_value_to_xml_value(Datum value, Oid type)
                getTypeOutputInfo(type, &typeOut, &isvarlena);
                str = OidOutputFunctionCall(typeOut, value);
 
-               /* ... exactly as-is for XML */
-               if (type == XMLOID)
+               /* ... exactly as-is for XML, and when escaping is not wanted */
+               if (type == XMLOID || !xml_escape_strings)
                        return str;
 
                /* otherwise, translate special characters as needed */
@@ -3183,7 +3192,7 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename,
                        appendStringInfo(result, "  <%s>%s</%s>\n",
                                                         colname,
                                                         map_sql_value_to_xml_value(colval,
-                                                                       SPI_gettypeid(SPI_tuptable->tupdesc, i)),
+                                                               SPI_gettypeid(SPI_tuptable->tupdesc, i), true),
                                                         colname);
        }
 
index f11ec721c48352ab7896cbb9d5274d1e862e85e7..af953f2b350dd73bbf2f8590ee9208d5bd524255 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.26 2009/05/13 20:27:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.27 2009/06/09 22:00:57 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -73,7 +73,7 @@ extern text *xmltotext_with_xmloption(xmltype *data, XmlOptionType xmloption_arg
 
 extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped, bool escape_period);
 extern char *map_xml_name_to_sql_identifier(char *name);
-extern char *map_sql_value_to_xml_value(Datum value, Oid type);
+extern char *map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings);
 
 typedef enum
 {
index 30b332aeccafd0e3de01a9eea35519c29f098323..ecca5896a70c2afe483e936a3b6eb2eb334881b4 100644 (file)
@@ -188,6 +188,12 @@ SELECT xmlelement(name foo, xmlattributes('2009-04-09 00:24:37'::timestamp as ba
 SELECT xmlelement(name foo, xmlattributes('infinity'::timestamp as bar));
 ERROR:  timestamp out of range
 DETAIL:  XML does not support infinite timestamp values.
+SELECT xmlelement(name foo, xmlattributes('<>&"''' as funny, xml 'b<a/>r' as funnier));
+                         xmlelement                         
+------------------------------------------------------------
+ <foo funny="&lt;&gt;&amp;&quot;'" funnier="b&lt;a/&gt;r"/>
+(1 row)
+
 SELECT xmlparse(content 'abc');
  xmlparse 
 ----------
index c8eb1e425e2c21fde0daba13c4cdd68cd2ef2cab..d542b0689a9dbc386bfb8c57237d923224488383 100644 (file)
@@ -160,6 +160,10 @@ SELECT xmlelement(name foo, xmlattributes('infinity'::timestamp as bar));
 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 xmlelement(name foo, xmlattributes('<>&"''' as funny, xml 'b<a/>r' as funnier));
+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 'abc');
 ERROR:  unsupported XML feature
 DETAIL:  This functionality requires the server to be built with libxml support.
index 50550aaa3583baaa572c1bec27afa150fd7fc720..086eedd27004edde15ab540280b3469dde846692 100644 (file)
@@ -57,6 +57,7 @@ SELECT xmlelement(name foo, bytea 'bar');
 SELECT xmlelement(name foo, xmlattributes(true as bar));
 SELECT xmlelement(name foo, xmlattributes('2009-04-09 00:24:37'::timestamp as bar));
 SELECT xmlelement(name foo, xmlattributes('infinity'::timestamp as bar));
+SELECT xmlelement(name foo, xmlattributes('<>&"''' as funny, xml 'b<a/>r' as funnier));
 
 
 SELECT xmlparse(content 'abc');