]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
<comomon> fix buffer out-of-bounds in HTMLFormatter 61104/head
authorliubingrun <liubr1@chinatelecom.cn>
Thu, 24 Oct 2024 10:19:28 +0000 (06:19 -0400)
committerCasey Bodley <cbodley@redhat.com>
Mon, 16 Dec 2024 18:21:04 +0000 (13:21 -0500)
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 <liubr1@chinatelecom.cn>
(cherry picked from commit 38601d0c9ea0b6fe32a27cebeb34ec785c7df676)

src/common/HTMLFormatter.cc
src/test/common/CMakeLists.txt
src/test/common/test_htmlformatter.cc [new file with mode: 0644]

index e7e985531d8ff3986b7618a4da776c0208c38bfd..1bc8d864cb6ba369373e715dc783e2cab6916eed 100644 (file)
@@ -23,6 +23,8 @@
 #include <stdlib.h>
 #include <string>
 #include <string.h>     // for strdup
+#include <boost/container/small_vector.hpp>
+#include <utility>  // 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<char, LARGE_SIZE>{
+      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 << "<li xmlns=\"" << ns << "\">" << e << ": "
-        << xml_stream_escaper(std::string_view(buf, len)) << "</li>";
+        << xml_stream_escaper(std::string_view(buf.data(), len)) << "</li>";
   } else {
     m_ss << "<li>" << e << ": "
-        << xml_stream_escaper(std::string_view(buf, len)) << "</li>";
+        << xml_stream_escaper(std::string_view(buf.data(), len)) << "</li>";
   }
 
   if (m_pretty)
index 5d5ef29418ebdfa38f3bcae2aaaed9ee001ac18b..8aabfaa98e991bdadaaa6b698b89298494621253 100644 (file)
@@ -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 (file)
index 0000000..0a8d827
--- /dev/null
@@ -0,0 +1,26 @@
+#include "gtest/gtest.h"
+
+#include "common/HTMLFormatter.h"
+#include <sstream>
+#include <string>
+
+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 = "<li>Location: " + uri + "</li>";
+
+  EXPECT_EQ(expected_output, sout.str());
+}
\ No newline at end of file