@@ -142,6 +142,21 @@ static void SPI_sql_row_to_xmlelement(int rownum, StringInfo result,
142
142
#define NAMESPACE_XSI "http://www.w3.org/2001/XMLSchema-instance"
143
143
#define NAMESPACE_SQLXML "http://standards.iso.org/iso/9075/2003/sqlxml"
144
144
145
+ /* forbidden C0 control chars */
146
+ #define FORBIDDEN_C0 \
147
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11" \
148
+ "\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
149
+
150
+ static inline void
151
+ check_forbidden_chars (char * str )
152
+ {
153
+ if (strpbrk (str ,FORBIDDEN_C0 ) != NULL )
154
+ ereport (ERROR ,
155
+ (errcode (ERRCODE_INVALID_TEXT_REPRESENTATION ),
156
+ errmsg ("character out of range" ),
157
+ errdetail ("XML does not support control characters." )));
158
+
159
+ }
145
160
146
161
#ifdef USE_LIBXML
147
162
@@ -411,6 +426,8 @@ xmlcomment(PG_FUNCTION_ARGS)
411
426
appendStringInfoText (& buf , arg );
412
427
appendStringInfo (& buf , "-->" );
413
428
429
+ check_forbidden_chars (buf .data );
430
+
414
431
PG_RETURN_XML_P (stringinfo_to_xmltype (& buf ));
415
432
#else
416
433
NO_XML_SUPPORT ();
@@ -718,6 +735,8 @@ xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null)
718
735
}
719
736
appendStringInfoString (& buf , "?>" );
720
737
738
+ check_forbidden_chars (buf .data );
739
+
721
740
result = stringinfo_to_xmltype (& buf );
722
741
pfree (buf .data );
723
742
return result ;
@@ -741,6 +760,8 @@ xmlroot(xmltype *data, text *version, int standalone)
741
760
len = VARSIZE (data ) - VARHDRSZ ;
742
761
str = text_to_cstring ((text * ) data );
743
762
763
+ check_forbidden_chars (str );
764
+
744
765
parse_xml_decl ((xmlChar * ) str , & len , & orig_version , NULL , & orig_standalone );
745
766
746
767
if (version )
@@ -1184,6 +1205,9 @@ xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace,
1184
1205
encoding ,
1185
1206
PG_UTF8 );
1186
1207
1208
+ /* check for illegal XML chars */
1209
+ check_forbidden_chars ((char * ) utf8string );
1210
+
1187
1211
/* Start up libxml and its parser (no-ops if already done) */
1188
1212
pg_xml_init ();
1189
1213
xmlInitParser ();
@@ -1804,6 +1828,9 @@ map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
1804
1828
getTypeOutputInfo (type , & typeOut , & isvarlena );
1805
1829
str = OidOutputFunctionCall (typeOut , value );
1806
1830
1831
+ /* check for illegal XML chars */
1832
+ check_forbidden_chars (str );
1833
+
1807
1834
/* ... exactly as-is for XML, and when escaping is not wanted */
1808
1835
if (type == XMLOID || !xml_escape_strings )
1809
1836
return str ;
0 commit comments