diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index 0b608f8e2d..3d546c2706 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -128,7 +128,7 @@ class serializer const auto new_indent = current_indent + indent_step; if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { - indent_string.resize(indent_string.size() * 2, ' '); + indent_string.resize((std::max)(indent_string.size() * 2, static_cast(new_indent)), ' '); } // first n-1 elements @@ -201,7 +201,7 @@ class serializer const auto new_indent = current_indent + indent_step; if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { - indent_string.resize(indent_string.size() * 2, ' '); + indent_string.resize((std::max)(indent_string.size() * 2, static_cast(new_indent)), ' '); } // first n-1 elements @@ -262,7 +262,7 @@ class serializer const auto new_indent = current_indent + indent_step; if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { - indent_string.resize(indent_string.size() * 2, ' '); + indent_string.resize((std::max)(indent_string.size() * 2, static_cast(new_indent)), ' '); } o->write_characters(indent_string.c_str(), new_indent); diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 03d2351736..5d66ee375d 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -19835,7 +19835,7 @@ class serializer const auto new_indent = current_indent + indent_step; if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { - indent_string.resize(indent_string.size() * 2, ' '); + indent_string.resize((std::max)(indent_string.size() * 2, static_cast(new_indent)), ' '); } // first n-1 elements @@ -19908,7 +19908,7 @@ class serializer const auto new_indent = current_indent + indent_step; if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { - indent_string.resize(indent_string.size() * 2, ' '); + indent_string.resize((std::max)(indent_string.size() * 2, static_cast(new_indent)), ' '); } // first n-1 elements @@ -19969,7 +19969,7 @@ class serializer const auto new_indent = current_indent + indent_step; if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) { - indent_string.resize(indent_string.size() * 2, ' '); + indent_string.resize((std::max)(indent_string.size() * 2, static_cast(new_indent)), ' '); } o->write_characters(indent_string.c_str(), new_indent); diff --git a/tests/src/unit-serialization.cpp b/tests/src/unit-serialization.cpp index f55ed84704..44ee0a5bc2 100644 --- a/tests/src/unit-serialization.cpp +++ b/tests/src/unit-serialization.cpp @@ -150,6 +150,36 @@ TEST_CASE("serialization") } } + SECTION("dump with large indentation") + { + // the indentation buffer starts at 512 characters and grows on demand; + // a width that needs more room than a single doubling provides must keep + // growing the buffer rather than emit past its end + const unsigned int width = 1100; + + SECTION("object") + { + const json j = {{"outer", {{"inner", 1}}}}; + const std::string s = j.dump(static_cast(width)); + CHECK(s.find('\n' + std::string(width, ' ') + "\"outer\"") != std::string::npos); + CHECK(s.find('\n' + std::string(2 * width, ' ') + "\"inner\"") != std::string::npos); + } + + SECTION("array") + { + const json j = json::array({json::array({1})}); + const std::string s = j.dump(static_cast(width)); + CHECK(s.find('\n' + std::string(2 * width, ' ') + '1') != std::string::npos); + } + + SECTION("binary") + { + const json j = json::binary({1, 2, 3}); + const std::string s = j.dump(static_cast(width)); + CHECK(s.find('\n' + std::string(width, ' ') + "\"bytes\"") != std::string::npos); + } + } + SECTION("to_string") { auto test = [&](std::string const & input, std::string const & expected)