diff options
author | Peter Eisentraut | 2009-06-09 22:00:57 +0000 |
---|---|---|
committer | Peter Eisentraut | 2009-06-09 22:00:57 +0000 |
commit | 0a42d887584db01f65c5215da6bedf755e027129 (patch) | |
tree | 2540fdb4282c52786758aa87ac72bdb073ae374f | |
parent | 4a8a9521d295c49b805fe14c91d49000a6f54049 (diff) |
Fix xmlattribute escaping XML special characters twice (bug #4822).
Author: Itagaki Takahiro <[email protected]>
-rw-r--r-- | src/backend/executor/execQual.c | 2 | ||||
-rw-r--r-- | src/backend/utils/adt/xml.c | 23 | ||||
-rw-r--r-- | src/include/utils/xml.h | 2 | ||||
-rw-r--r-- | src/test/regress/expected/xml.out | 6 | ||||
-rw-r--r-- | src/test/regress/expected/xml_1.out | 4 | ||||
-rw-r--r-- | src/test/regress/sql/xml.sql | 1 |
6 files changed, 29 insertions, 9 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 870b3213c6..3baad1e245 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -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; } diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 8f9ad5106a..f6292b9137 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -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 (< 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); } diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h index 636b55a16b..ebebfc9314 100644 --- a/src/include/utils/xml.h +++ b/src/include/utils/xml.h @@ -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 { diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index 30b332aecc..ecca5896a7 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -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="<>&"'" funnier="b<a/>r"/> +(1 row) + SELECT xmlparse(content 'abc'); xmlparse ---------- diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index c8eb1e425e..d542b0689a 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -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. diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index 50550aaa35..086eedd270 100644 --- a/src/test/regress/sql/xml.sql +++ b/src/test/regress/sql/xml.sql @@ -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'); |