diff --git a/lib/errorlogger.cpp b/lib/errorlogger.cpp index 48732b850..b5ccd0a74 100644 --- a/lib/errorlogger.cpp +++ b/lib/errorlogger.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -211,6 +212,27 @@ std::string ErrorLogger::ErrorMessage::getXMLFooter(int xml_version) return (xml_version<=1) ? "" : " \n"; } +// There is no utf-8 support around but the strings should at least be safe for to tinyxml2. +// See #5300 "Invalid encoding in XML output" +static std::string fixInvalidChars(const std::string& raw) +{ + std::string result; + result.reserve(raw.length()); + std::string::const_iterator from=raw.begin(); + while (from!=raw.end()) { + if (std::isprint(*from)) { + result.push_back(*from); + } else { + std::ostringstream es; + // straight cast to (unsigned) doesn't work out. + es << '\\' << std::setbase(8) << std::setw(3) << std::setfill('0') << (unsigned)(unsigned char)*from; + result += es.str(); + } + ++from; + } + return result; +} + std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const { // The default xml format @@ -239,7 +261,7 @@ std::string ErrorLogger::ErrorMessage::toXML(bool verbose, int version) const printer.PushAttribute("id", _id.c_str()); printer.PushAttribute("severity", Severity::toString(_severity).c_str()); printer.PushAttribute("msg", _shortMessage.c_str()); - printer.PushAttribute("verbose", _verboseMessage.c_str()); + printer.PushAttribute("verbose", fixInvalidChars(_verboseMessage).c_str()); if (_inconclusive) printer.PushAttribute("inconclusive", "true"); diff --git a/test/testerrorlogger.cpp b/test/testerrorlogger.cpp index 7d9ccbaa2..0b275466a 100644 --- a/test/testerrorlogger.cpp +++ b/test/testerrorlogger.cpp @@ -46,6 +46,7 @@ private: TEST_CASE(ToVerboseXmlLocations); TEST_CASE(ToXmlV2); TEST_CASE(ToXmlV2Locations); + TEST_CASE(ToXmlV2Encoding); // Inconclusive results in xml reports.. TEST_CASE(InconclusiveXml); @@ -215,6 +216,13 @@ private: ASSERT_EQUALS(message, msg.toXML(false, 2)); } + void ToXmlV2Encoding() const { + std::list locs; + ErrorMessage msg(locs, Severity::error, "Programming error.\nComparing \"\203\" with \"\003\"", "errorId", false); + const std::string message(" "); + ASSERT_EQUALS(message, msg.toXML(false, 2)); + } + void InconclusiveXml() const { // Location std::list locs(1, fooCpp5);