From: liubingrun Date: Thu, 24 Oct 2024 10:19:28 +0000 (-0400) Subject: fix buffer out-of-bounds in HTMLFormatter X-Git-Tag: v19.2.3~263^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=70e6e82dbb806d0aee71faeb3f15402970c9e493;p=ceph.git fix buffer out-of-bounds in HTMLFormatter Use boost small_vector to allocate more buffer when content is too long to fit in the buffer pre-alloced A unittest is also added. Signed-off-by: liubingrun (cherry picked from commit 38601d0c9ea0b6fe32a27cebeb34ec785c7df676) --- diff --git a/src/common/HTMLFormatter.cc b/src/common/HTMLFormatter.cc index e7e985531d8ff..1bc8d864cb6ba 100644 --- a/src/common/HTMLFormatter.cc +++ b/src/common/HTMLFormatter.cc @@ -23,6 +23,8 @@ #include #include #include // for strdup +#include +#include // for std::cmp_greater_equal #include "common/escape.h" @@ -138,17 +140,27 @@ std::ostream& HTMLFormatter::dump_stream(std::string_view name) void HTMLFormatter::dump_format_va(std::string_view name, const char *ns, bool quoted, const char *fmt, va_list ap) { - char buf[LARGE_SIZE]; - size_t len = vsnprintf(buf, LARGE_SIZE, fmt, ap); + auto buf = boost::container::small_vector{ + LARGE_SIZE, boost::container::default_init}; + + va_list ap_copy; + va_copy(ap_copy, ap); + size_t len = vsnprintf(buf.data(), buf.size(), fmt, ap); + va_end(ap_copy); + + if(std::cmp_greater_equal(len, buf.size())){ + buf.resize(len + 1, boost::container::default_init); + vsnprintf(buf.data(), buf.size(), fmt, ap_copy); + } std::string e(name); print_spaces(); if (ns) { m_ss << "
  • " << e << ": " - << xml_stream_escaper(std::string_view(buf, len)) << "
  • "; + << xml_stream_escaper(std::string_view(buf.data(), len)) << ""; } else { m_ss << "
  • " << e << ": " - << xml_stream_escaper(std::string_view(buf, len)) << "
  • "; + << xml_stream_escaper(std::string_view(buf.data(), len)) << ""; } if (m_pretty) diff --git a/src/test/common/CMakeLists.txt b/src/test/common/CMakeLists.txt index 5d5ef29418ebd..8aabfaa98e991 100644 --- a/src/test/common/CMakeLists.txt +++ b/src/test/common/CMakeLists.txt @@ -229,6 +229,12 @@ add_executable(unittest_xmlformatter add_ceph_unittest(unittest_xmlformatter) target_link_libraries(unittest_xmlformatter ceph-common) +add_executable(unittest_htmlformatter + test_htmlformatter.cc + ) +add_ceph_unittest(unittest_htmlformatter) +target_link_libraries(unittest_htmlformatter ceph-common) + # unittest_bit_vector add_executable(unittest_bit_vector test_bit_vector.cc diff --git a/src/test/common/test_htmlformatter.cc b/src/test/common/test_htmlformatter.cc new file mode 100644 index 0000000000000..0a8d827b53a32 --- /dev/null +++ b/src/test/common/test_htmlformatter.cc @@ -0,0 +1,26 @@ +#include "gtest/gtest.h" + +#include "common/HTMLFormatter.h" +#include +#include + +using namespace ceph; + +TEST(htmlformatter, dump_format_large_item) +{ + std::stringstream sout; + HTMLFormatter formatter(false); + + std::string base_url("http://example.com"); + std::string bucket_name("bucket"); + std::string object_key(1024, 'a'); + + formatter.dump_format("Location", "%s/%s/%s", base_url.c_str(), bucket_name.c_str(), object_key.c_str()); + + formatter.flush(sout); + + std::string uri = base_url + "/" + bucket_name + "/" + object_key; + std::string expected_output = "
  • Location: " + uri + "
  • "; + + EXPECT_EQ(expected_output, sout.str()); +} \ No newline at end of file