Do not violate UTF-8 in XML output

According to UTF-8 encoding rules, there are no valid one byte long codepoints which start with a bigh bit set (i.e. 0x80 or higher value). Hence such XML output needs to be escaped, same as a control character.
This commit is contained in:
Bronek Kozicki 2018-03-12 20:34:13 +00:00
parent e11508b48a
commit 27fa7218ca
7 changed files with 57 additions and 8 deletions

View File

@ -45,10 +45,14 @@ namespace Catch {
default:
// Escape control chars - based on contribution by @espenalb in PR #465 and
// by @mrpi PR #588
if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
// Also take care to avoid violation of UTF-8 encoding rules
if ( ( c >= 0 && c < '\x09' )
|| ( c > '\x0D' && c < '\x20')
|| ( c & 0x80 )
|| c=='\x7F') {
// see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
<< static_cast<int>( c );
<< static_cast<int>( static_cast<unsigned char>(c) );
}
else
os << c;

View File

@ -905,6 +905,8 @@ Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode:
"don't &quot;quote&quot; me on that"
Xml.tests.cpp:<line number>: passed: encode( "[/x01]" ) == "[//x01]" for: "[/x01]" == "[/x01]"
Xml.tests.cpp:<line number>: passed: encode( "[/x7F]" ) == "[//x7F]" for: "[/x7F]" == "[/x7F]"
Xml.tests.cpp:<line number>: passed: encode( "[/x80]" ) == "[//x80]" for: "[/x80]" == "[/x80]"
Xml.tests.cpp:<line number>: passed: encode( "[/xFF]" ) == "[//xFF]" for: "[/xFF]" == "[/xFF]"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{ }" for: "{ }" == "{ }"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"

View File

@ -1085,5 +1085,5 @@ due to unexpected exception with message:
===============================================================================
test cases: 202 | 149 passed | 49 failed | 4 failed as expected
assertions: 1015 | 887 passed | 107 failed | 21 failed as expected
assertions: 1017 | 889 passed | 107 failed | 21 failed as expected

View File

@ -7112,6 +7112,25 @@ PASSED:
with expansion:
"[\x7F]" == "[\x7F]"
-------------------------------------------------------------------------------
XmlEncode
string with high bit set (x80 and xFF)
-------------------------------------------------------------------------------
Xml.tests.cpp:<line number>
...............................................................................
Xml.tests.cpp:<line number>:
PASSED:
REQUIRE( encode( "[\x80]" ) == "[\\x80]" )
with expansion:
"[\x80]" == "[\x80]"
Xml.tests.cpp:<line number>:
PASSED:
REQUIRE( encode( "[\xFF]" ) == "[\\xFF]" )
with expansion:
"[\xFF]" == "[\xFF]"
-------------------------------------------------------------------------------
array<int, N> -> toString
-------------------------------------------------------------------------------
@ -8599,5 +8618,5 @@ PASSED:
===============================================================================
test cases: 202 | 136 passed | 62 failed | 4 failed as expected
assertions: 1029 | 887 passed | 121 failed | 21 failed as expected
assertions: 1031 | 889 passed | 121 failed | 21 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="105" tests="1030" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuite name="<exe-name>" errors="17" failures="105" tests="1032" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
@ -706,6 +706,7 @@ Exception.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="XmlEncode/string with quotes" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (1)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode/string with control char (x7F)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="XmlEncode/string with high bit set (x80 and xFF)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="array&lt;int, N> -> toString" time="{duration}"/>
<testcase classname="<exe-name>.global" name="atomic if" time="{duration}"/>
<testcase classname="<exe-name>.global" name="boolean member" time="{duration}"/>

View File

@ -7992,6 +7992,25 @@ Message from section two
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="string with high bit set (x80 and xFF)" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode( "[\x80]" ) == "[\\x80]"
</Original>
<Expanded>
"[\x80]" == "[\x80]"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
<Original>
encode( "[\xFF]" ) == "[\\xFF]"
</Original>
<Expanded>
"[\xFF]" == "[\xFF]"
</Expanded>
</Expression>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="array&lt;int, N> -> toString" tags="[array][containers][toString]" filename="projects/<exe-name>/UsageTests/ToStringVector.tests.cpp" >
@ -9469,7 +9488,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="887" failures="122" expectedFailures="21"/>
<OverallResults successes="889" failures="122" expectedFailures="21"/>
</Group>
<OverallResults successes="887" failures="121" expectedFailures="21"/>
<OverallResults successes="889" failures="121" expectedFailures="21"/>
</Catch>

View File

@ -38,4 +38,8 @@ TEST_CASE( "XmlEncode" ) {
SECTION( "string with control char (x7F)" ) {
REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" );
}
}
SECTION( "string with high bit set (x80 and xFF)" ) {
REQUIRE( encode( "[\x80]" ) == "[\\x80]" );
REQUIRE( encode( "[\xFF]" ) == "[\\xFF]" );
}
}