merge bitcoin#17095: Filter control characters out of log messages

This commit is contained in:
Kittywhiskers Van Gogh 2019-10-10 13:25:08 +02:00
parent 6db0332d14
commit 13e26024c4
2 changed files with 41 additions and 1 deletions

View File

@ -261,10 +261,32 @@ std::string BCLog::Logger::LogTimestampStr(const std::string& str)
return strStamped; return strStamped;
} }
namespace BCLog {
/** Belts and suspenders: make sure outgoing log messages don't contain
* potentially suspicious characters, such as terminal control codes.
*
* This escapes control characters except newline ('\n') in C syntax.
* It escapes instead of removes them to still allow for troubleshooting
* issues where they accidentally end up in strings.
*/
std::string LogEscapeMessage(const std::string& str) {
std::string ret;
for (char ch_in : str) {
uint8_t ch = (uint8_t)ch_in;
if ((ch >= 32 || ch == '\n') && ch != '\x7f') {
ret += ch_in;
} else {
ret += strprintf("\\x%02x", ch);
}
}
return ret;
}
}
void BCLog::Logger::LogPrintStr(const std::string& str) void BCLog::Logger::LogPrintStr(const std::string& str)
{ {
StdLockGuard scoped_lock(m_cs); StdLockGuard scoped_lock(m_cs);
std::string str_prefixed = str; std::string str_prefixed = LogEscapeMessage(str);
if (m_log_threadnames && m_started_new_line) { if (m_log_threadnames && m_started_new_line) {
// 16 chars total, "dash-" is 5 of them and another 1 is a NUL terminator // 16 chars total, "dash-" is 5 of them and another 1 is a NUL terminator

View File

@ -25,6 +25,11 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
/* defined in logging.cpp */
namespace BCLog {
std::string LogEscapeMessage(const std::string& str);
}
BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(util_criticalsection) BOOST_AUTO_TEST_CASE(util_criticalsection)
@ -1474,4 +1479,17 @@ BOOST_AUTO_TEST_CASE(test_spanparsing)
BOOST_CHECK_EQUAL(SpanToStr(results[3]), ""); BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
} }
BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
{
// ASCII and UTF-8 must pass through unaltered.
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
// Newlines must pass through unaltered.
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
// Other control characters are escaped in C syntax.
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
// Embedded NULL characters are escaped too.
const std::string NUL("O\x00O", 3);
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()