From: Sage Weil Date: Tue, 10 Apr 2018 03:25:17 +0000 (-0500) Subject: common/Formatter: fix string_view usage for {json,xml}_stream_escaper X-Git-Tag: v13.1.0~274^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=54f1e4e614dcd185d28c5644fc049a6ea2838d12;p=ceph.git common/Formatter: fix string_view usage for {json,xml}_stream_escaper These are passing a simple const char* without a length, which breaks for binary strings with \0 in them. Broken by b40f76a7a0cf460f2a851b001885a4831a6f6503. This code is still a mess because there is a mix of boost::string_view and std::string_view throughout the code. A cleanup is in order! Signed-off-by: Sage Weil --- diff --git a/src/common/Formatter.cc b/src/common/Formatter.cc index d0cc2d2aeda8..6b57027e3a7b 100644 --- a/src/common/Formatter.cc +++ b/src/common/Formatter.cc @@ -163,7 +163,7 @@ void JSONFormatter::print_comma(json_formatter_stack_entry_d& entry) void JSONFormatter::print_quoted_string(std::string_view s) { - m_ss << '\"' << json_stream_escaper(s.data()) << '\"'; + m_ss << '\"' << json_stream_escaper(s) << '\"'; } void JSONFormatter::print_name(const char *name) @@ -447,7 +447,7 @@ void XMLFormatter::dump_string(const char *name, std::string_view s) [this](char c) { return this->to_lower_underscore(c); }); print_spaces(); - m_ss << "<" << e << ">" << xml_stream_escaper(s.data()) << ""; + m_ss << "<" << e << ">" << xml_stream_escaper(s) << ""; if (m_pretty) m_ss << "\n"; } @@ -461,7 +461,7 @@ void XMLFormatter::dump_string_with_attrs(const char *name, std::string_view s, std::string attrs_str; get_attrs_str(&attrs, attrs_str); print_spaces(); - m_ss << "<" << e << attrs_str << ">" << xml_stream_escaper(s.data()) << ""; + m_ss << "<" << e << attrs_str << ">" << xml_stream_escaper(s) << ""; if (m_pretty) m_ss << "\n"; } @@ -477,7 +477,7 @@ std::ostream& XMLFormatter::dump_stream(const char *name) void XMLFormatter::dump_format_va(const char* name, const char *ns, bool quoted, const char *fmt, va_list ap) { char buf[LARGE_SIZE]; - vsnprintf(buf, LARGE_SIZE, fmt, ap); + size_t len = vsnprintf(buf, LARGE_SIZE, fmt, ap); std::string e(name); std::transform(e.begin(), e.end(), e.begin(), [this](char c) { return this->to_lower_underscore(c); }); @@ -486,7 +486,7 @@ void XMLFormatter::dump_format_va(const char* name, const char *ns, bool quoted, if (ns) { m_ss << "<" << e << " xmlns=\"" << ns << "\">" << buf << ""; } else { - m_ss << "<" << e << ">" << xml_stream_escaper(buf) << ""; + m_ss << "<" << e << ">" << xml_stream_escaper(std::string_view(buf, len)) << ""; } if (m_pretty) diff --git a/src/common/HTMLFormatter.cc b/src/common/HTMLFormatter.cc index 1ad6a6d88e56..725bc39ff70d 100644 --- a/src/common/HTMLFormatter.cc +++ b/src/common/HTMLFormatter.cc @@ -114,7 +114,7 @@ void HTMLFormatter::dump_float(const char *name, double d) void HTMLFormatter::dump_string(const char *name, std::string_view s) { - dump_template(name, xml_stream_escaper(s.data())); + dump_template(name, xml_stream_escaper(s)); } void HTMLFormatter::dump_string_with_attrs(const char *name, std::string_view s, const FormatterAttrs& attrs) @@ -123,7 +123,7 @@ void HTMLFormatter::dump_string_with_attrs(const char *name, std::string_view s, std::string attrs_str; get_attrs_str(&attrs, attrs_str); print_spaces(); - m_ss << "
  • " << e << ": " << xml_stream_escaper(s.data()) << attrs_str << "
  • "; + m_ss << "
  • " << e << ": " << xml_stream_escaper(s) << attrs_str << "
  • "; if (m_pretty) m_ss << "\n"; } @@ -139,14 +139,16 @@ std::ostream& HTMLFormatter::dump_stream(const char *name) void HTMLFormatter::dump_format_va(const char* name, const char *ns, bool quoted, const char *fmt, va_list ap) { char buf[LARGE_SIZE]; - vsnprintf(buf, LARGE_SIZE, fmt, ap); + size_t len = vsnprintf(buf, LARGE_SIZE, fmt, ap); std::string e(name); print_spaces(); if (ns) { - m_ss << "
  • " << e << ": " << xml_stream_escaper(buf) << "
  • "; + m_ss << "
  • " << e << ": " + << xml_stream_escaper(std::string_view(buf, len)) << "
  • "; } else { - m_ss << "
  • " << e << ": " << xml_stream_escaper(buf) << "
  • "; + m_ss << "
  • " << e << ": " + << xml_stream_escaper(std::string_view(buf, len)) << "
  • "; } if (m_pretty) diff --git a/src/common/escape.h b/src/common/escape.h index 22da777212a5..97178520b7ec 100644 --- a/src/common/escape.h +++ b/src/common/escape.h @@ -51,13 +51,13 @@ void escape_json_attr(const char *buf, size_t src_len, char *out); struct xml_stream_escaper { boost::string_view str; - xml_stream_escaper(boost::string_view str) : str(str) {} + xml_stream_escaper(std::string_view str) : str(str.data(), str.size()) {} }; std::ostream& operator<<(std::ostream& out, const xml_stream_escaper& e); struct json_stream_escaper { boost::string_view str; - json_stream_escaper(boost::string_view str) : str(str) {} + json_stream_escaper(std::string_view str) : str(str.data(), str.size()) {} }; std::ostream& operator<<(std::ostream& out, const json_stream_escaper& e); diff --git a/src/test/escape.cc b/src/test/escape.cc index 82591cba1e19..cab87043ffcc 100644 --- a/src/test/escape.cc +++ b/src/test/escape.cc @@ -66,18 +66,21 @@ TEST(EscapeXml, Utf8) { ASSERT_EQ(escape_xml_stream("<\xe6\xb1\x89\xe5\xad\x97>\n"), "<\xe6\xb1\x89\xe5\xad\x97>\n"); } -static std::string escape_json_attrs(const char *str) +static std::string escape_json_attrs(const char *str, size_t src_len = 0) { - int src_len = strlen(str); + if (!src_len) + src_len = strlen(str); int len = escape_json_attr_len(str, src_len); char out[len]; escape_json_attr(str, src_len, out); return out; } -static std::string escape_json_stream(const char *str) +static std::string escape_json_stream(const char *str, size_t src_len = 0) { + if (!src_len) + src_len = strlen(str); std::stringstream ss; - ss << json_stream_escaper(str); + ss << json_stream_escaper(std::string_view(str, src_len)); return ss.str(); } @@ -110,6 +113,10 @@ TEST(EscapeJson, Escapes1) { TEST(EscapeJson, ControlChars) { ASSERT_EQ(escape_json_attrs("\x01\x02\x03"), "\\u0001\\u0002\\u0003"); ASSERT_EQ(escape_json_stream("\x01\x02\x03"), "\\u0001\\u0002\\u0003"); + ASSERT_EQ(escape_json_stream("\x00\x02\x03", 3), "\\u0000\\u0002\\u0003"); + + // json can't print binary data! + ASSERT_EQ(escape_json_stream("\x00\x7f\xff", 3), "\\u0000\\u007f\xff"); ASSERT_EQ(escape_json_attrs("abc\x7f"), "abc\\u007f"); ASSERT_EQ(escape_json_stream("abc\x7f"), "abc\\u007f");