Skip to content

Commit 38601d0

Browse files
committed
<comomon> 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 <[email protected]>
1 parent 207003c commit 38601d0

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

src/common/HTMLFormatter.cc

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include <stdlib.h>
2424
#include <string>
2525
#include <string.h> // for strdup
26+
#include <boost/container/small_vector.hpp>
27+
#include <utility> // for std::cmp_greater_equal
2628

2729
#include "common/escape.h"
2830

@@ -138,17 +140,27 @@ std::ostream& HTMLFormatter::dump_stream(std::string_view name)
138140

139141
void HTMLFormatter::dump_format_va(std::string_view name, const char *ns, bool quoted, const char *fmt, va_list ap)
140142
{
141-
char buf[LARGE_SIZE];
142-
size_t len = vsnprintf(buf, LARGE_SIZE, fmt, ap);
143+
auto buf = boost::container::small_vector<char, LARGE_SIZE>{
144+
LARGE_SIZE, boost::container::default_init};
145+
146+
va_list ap_copy;
147+
va_copy(ap_copy, ap);
148+
size_t len = vsnprintf(buf.data(), buf.size(), fmt, ap);
149+
va_end(ap_copy);
150+
151+
if(std::cmp_greater_equal(len, buf.size())){
152+
buf.resize(len + 1, boost::container::default_init);
153+
vsnprintf(buf.data(), buf.size(), fmt, ap_copy);
154+
}
143155

144156
std::string e(name);
145157
print_spaces();
146158
if (ns) {
147159
m_ss << "<li xmlns=\"" << ns << "\">" << e << ": "
148-
<< xml_stream_escaper(std::string_view(buf, len)) << "</li>";
160+
<< xml_stream_escaper(std::string_view(buf.data(), len)) << "</li>";
149161
} else {
150162
m_ss << "<li>" << e << ": "
151-
<< xml_stream_escaper(std::string_view(buf, len)) << "</li>";
163+
<< xml_stream_escaper(std::string_view(buf.data(), len)) << "</li>";
152164
}
153165

154166
if (m_pretty)

src/test/common/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ add_executable(unittest_xmlformatter
229229
add_ceph_unittest(unittest_xmlformatter)
230230
target_link_libraries(unittest_xmlformatter ceph-common)
231231

232+
add_executable(unittest_htmlformatter
233+
test_htmlformatter.cc
234+
)
235+
add_ceph_unittest(unittest_htmlformatter)
236+
target_link_libraries(unittest_htmlformatter ceph-common)
237+
232238
# unittest_bit_vector
233239
add_executable(unittest_bit_vector
234240
test_bit_vector.cc
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include "gtest/gtest.h"
2+
3+
#include "common/HTMLFormatter.h"
4+
#include <sstream>
5+
#include <string>
6+
7+
using namespace ceph;
8+
9+
TEST(htmlformatter, dump_format_large_item)
10+
{
11+
std::stringstream sout;
12+
HTMLFormatter formatter(false);
13+
14+
std::string base_url("http://example.com");
15+
std::string bucket_name("bucket");
16+
std::string object_key(1024, 'a');
17+
18+
formatter.dump_format("Location", "%s/%s/%s", base_url.c_str(), bucket_name.c_str(), object_key.c_str());
19+
20+
formatter.flush(sout);
21+
22+
std::string uri = base_url + "/" + bucket_name + "/" + object_key;
23+
std::string expected_output = "<li>Location: " + uri + "</li>";
24+
25+
EXPECT_EQ(expected_output, sout.str());
26+
}

0 commit comments

Comments
 (0)