From 19fac5cccb9988264108ac5c4cee6b20dd84d3ca Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Sat, 29 Aug 2026 07:12:16 +0300 Subject: [PATCH 01/13] some trailing whitespace removed --- include/boost/json/impl/value_ref.ipp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/json/impl/value_ref.ipp b/include/boost/json/impl/value_ref.ipp index 99e75af0f..890c130c7 100644 --- a/include/boost/json/impl/value_ref.ipp +++ b/include/boost/json/impl/value_ref.ipp @@ -97,11 +97,11 @@ make_value( case what::func: return f_.f(f_.p, std::move(sp)); - + case what::strfunc: return f_.f(f_.p, std::move(sp)); - + case what::cfunc: return cf_.f(cf_.p, std::move(sp)); From 749f6d886234296e42197aeb3a1829c0167e29da Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Thu, 13 Aug 2026 18:42:06 +0300 Subject: [PATCH 02/13] more test coverage for key_value_pair --- test/object.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/object.cpp b/test/object.cpp index f66d58035..69bd104b8 100644 --- a/test/object.cpp +++ b/test/object.cpp @@ -275,6 +275,17 @@ class object_test { object o; } + { + key_value_pair kp("a", "b"); + } + { + // this test is mostly for getting more test coverage + monotonic_resource mr; + std::pair p("k", "v"); + key_value_pair kp(p, &mr); + BOOST_TEST(kp.key() == "k"); + BOOST_TEST(kp.value() == "v"); + } } void From d6906fd5e7c1a11f027305b6f3317f83e0bd2b91 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Mon, 17 Aug 2026 15:22:50 +0300 Subject: [PATCH 03/13] more parser coverage --- .drone.star | 7 ++++- test/basic_parser.cpp | 59 +++++++++++++++++++++++++++++++++++++- test/limits.cpp | 46 ++++++++++++++++++++++++++++++ test/stream_parser.cpp | 64 ++++++++++++++++++++++++------------------ 4 files changed, 146 insertions(+), 30 deletions(-) diff --git a/.drone.star b/.drone.star index ce5526b8f..6c997a42b 100644 --- a/.drone.star +++ b/.drone.star @@ -98,7 +98,6 @@ def main(ctx): 'LCOV_BRANCH_COVERAGE': '0', 'B2_CXXSTD': '23', 'B2_VARIANT': 'debug', - 'B2_DEFINES': 'BOOST_JSON_EXPENSIVE_TESTS', 'CODECOV_TOKEN': {'from_secret': 'codecov_token'}, }, }, @@ -122,9 +121,15 @@ def main(ctx): }, { 'match': {'compiler': 'clang =latest', 'os': 'linux'}, 'special': 'valgrind', + 'environment': { + 'B2_DEFINES': 'BOOST_JSON_NO_LONG_TESTS', + }, }, { 'match': {'compiler': 'gcc =latest', 'os': 'linux'}, 'special': 'valgrind', + 'environment': { + 'B2_DEFINES': 'BOOST_JSON_NO_LONG_TESTS', + }, }, ], ) + [ diff --git a/test/basic_parser.cpp b/test/basic_parser.cpp index 7b4528b5c..5b98abb75 100644 --- a/test/basic_parser.cpp +++ b/test/basic_parser.cpp @@ -659,8 +659,8 @@ class basic_parser_test good("1000000000000000000000000.000000000001"); good("1000000000000000000000000.0e1 "); good("1000000000000000000000000.0 "); - good("1000000000.1000000000 "); + good("100000000000000000000e+2147483647"); bad(""); bad("- "); @@ -1453,6 +1453,7 @@ class basic_parser_test bad("\"\xf1\x7f\xbf\xbf----------\""); bad("\"\xf2\x80\x7f\xbf----------\""); bad("\"\xf3\x80\xbf\xce----------\""); + bad("\"\xf3\x80\xbf"); // utf8 after escape good("\"\\u0000 \xf3\xbf\x80\xbf\xf3\xbf\x80\xbf\""); @@ -1821,6 +1822,60 @@ class basic_parser_test #pragma warning(pop) #endif + struct null_handler + { + constexpr static std::size_t max_object_size = std::size_t(-1); + constexpr static std::size_t max_array_size = std::size_t(-1); + constexpr static std::size_t max_key_size = std::size_t(-1); + constexpr static std::size_t max_string_size = std::size_t(-1); + + bool on_document_begin( system::error_code& ) { return true; } + bool on_document_end( system::error_code& ) { return true; } + bool on_object_begin( system::error_code& ) { return true; } + bool on_object_end( std::size_t, system::error_code& ) { return true; } + bool on_array_begin( system::error_code& ) { return true; } + bool on_array_end( std::size_t, system::error_code& ) { return true; } + bool on_key_part( string_view, std::size_t, system::error_code& ) { return true; } + bool on_key( string_view, std::size_t, system::error_code& ) { return true; } + bool on_string_part( string_view, std::size_t, system::error_code& ) { return true; } + bool on_string( string_view, std::size_t, system::error_code& ) { return true; } + bool on_number_part( string_view, system::error_code&) { return true; } + bool on_int64( std::int64_t, string_view, system::error_code& ) { return true; } + bool on_uint64( std::uint64_t, string_view, system::error_code& ) { return true; } + bool on_double( double, string_view, system::error_code& ) { return true; } + bool on_bool( bool, system::error_code& ) { return true; } + bool on_null( system::error_code& ) { return true; } + bool on_comment_part( string_view, system::error_code& ) { return true; } + bool on_comment( string_view, system::error_code& ) { return true; } + }; + + void + testManualFail() + { + basic_parser p({}); + p.fail( system::error_code() ); + BOOST_TEST( !p.done() ); + BOOST_TEST( p.last_error() == error::incomplete ); + BOOST_TEST( p.last_error().has_location() ); + + p.reset(); + + system::error_code ec; + p.write_some(false, "null", 4, ec); + BOOST_TEST( p.done() ); + p.fail( make_error_code(error::array_too_large) ); + BOOST_TEST( !p.done() ); + BOOST_TEST( p.last_error() == error::array_too_large ); + } + + void + testWhitespace() + { + parse_options opts; + opts.allow_comments = true; + bad("//\n ", opts); + } + void run() { @@ -1845,6 +1900,8 @@ class basic_parser_test testNumberLiteral(); testStickyErrors(); testStdTypes(); + testManualFail(); + testWhitespace(); } }; diff --git a/test/limits.cpp b/test/limits.cpp index df836cc3b..3d5b485a9 100644 --- a/test/limits.cpp +++ b/test/limits.cpp @@ -220,6 +220,52 @@ class limits_test BOOST_TEST(ec.has_location()); } + // string in parser, fails at the beginning of the 2nd escape sequence + { + stream_parser p; + system::error_code ec; + p.write_some("\"", 1, ec); + BOOST_TEST( !ec.failed() ); + for(std::size_t i = 0; i < string::max_size(); ++i) + { + p.write_some("0", 1, ec); + } + p.write_some("\\n\\", 3, ec); + BOOST_TEST(ec == error::string_too_large); + BOOST_TEST(ec.has_location()); + } + + // string in parser, fails at the beginning of the 2nd + // (unicode) escape sequence + { + stream_parser p; + system::error_code ec; + p.write_some("\"", 1, ec); + BOOST_TEST( !ec.failed() ); + for(std::size_t i = 0; i < string::max_size(); ++i) + { + p.write_some("0", 1, ec); + } + p.write_some("\\n\\u", 4, ec); + BOOST_TEST(ec == error::string_too_large); + BOOST_TEST(ec.has_location()); + } + + // string in parser, fails after the last escape + { + stream_parser p; + system::error_code ec; + p.write_some("\"", 1, ec); + BOOST_TEST( !ec.failed() ); + for(std::size_t i = 0; i < string::max_size(); ++i) + { + p.write_some("0", 1, ec); + } + p.write_some("\\n0", 3, ec); + BOOST_TEST(ec == error::string_too_large); + BOOST_TEST(ec.has_location()); + } + // key in parser { stream_parser p; diff --git a/test/stream_parser.cpp b/test/stream_parser.cpp index b2fe17380..8655e77ab 100644 --- a/test/stream_parser.cpp +++ b/test/stream_parser.cpp @@ -1296,79 +1296,87 @@ R"xx({ void testLongNumberOverlfow() { -#ifdef BOOST_JSON_EXPENSIVE_TESTS - std::array zeroes; +#ifndef BOOST_JSON_NO_LONG_TESTS + std::array zeroes; zeroes.fill('0'); stream_parser p; { - p.write("1", 1); + // number with too many digits before decimal point + p.write("1111111111111111111", 19); std::size_t count = 0; - while( static_cast( INT_MAX - zeroes.size() ) > count ) + std::size_t const n + = static_cast(INT_MAX) - zeroes.size(); + while(n > count) count += p.write( zeroes.data(), zeroes.size() ); + p.write(zeroes.data(), static_cast(INT_MAX) - count); system::error_code ec; - p.write(zeroes.data(), zeroes.size(), ec); - BOOST_TEST( ec == error::exponent_overflow ); + p.write("1", 1, ec); + BOOST_TEST(ec == error::exponent_overflow); + BOOST_TEST(ec.has_location()); } p.reset(); { + // number with too many digits after decimal point p.write("0.", 2); std::size_t count = 0; - while( static_cast( INT_MAX - zeroes.size() ) > count ) + std::size_t const n + = static_cast(INT_MAX) - zeroes.size(); + while(n > count) count += p.write( zeroes.data(), zeroes.size() ); + p.write(zeroes.data(), static_cast(INT_MAX) - count); system::error_code ec; - p.write(zeroes.data(), zeroes.size(), ec); - BOOST_TEST( ec == error::exponent_overflow ); + p.write_some("0", 1, ec); + BOOST_TEST(ec == error::exponent_overflow); + BOOST_TEST(ec.has_location()); } p.reset(); { + // number with non-zero mantissa, many digits after decimal point, + // and overflowing negative exponent p.write("0.", 2); int count = INT_MIN; - while( static_cast( count + zeroes.size() ) < 0 ) + while( static_cast(count + zeroes.size()) < 0 ) count += static_cast( p.write( zeroes.data(), zeroes.size() )); - p.write(zeroes.data(), -2 - count); - p.write("1e", 2); - // at this point we've filled bias to the brim - std::string const int_min = std::to_string(INT_MIN); - p.write( int_min.data(), int_min.size() ); + p.write("1e-2147483647", 13); + // 0.((-INT_MIN) - 2 zeroes)1e-2147483647 system::error_code ec; p.finish(ec); - BOOST_TEST( ec == error::exponent_overflow ); + BOOST_TEST(ec == error::exponent_overflow); + BOOST_TEST(ec.has_location()); } p.reset(); { - std::string const uint64_max - = std::to_string(18446744073709551615U); - p.write( uint64_max.data(), uint64_max.size() ); + // number with non-zero mantissa, many digits before decimal point, + // and overflowing positive exponent + p.write("1111111111111111111", 19); - std::size_t count = INT_MAX; + std::size_t count = INT_MAX - (308 - 19); while( static_cast( count - zeroes.size() ) > 0 ) count -= p.write( zeroes.data(), zeroes.size() ); + p.write(zeroes.data(), count); - p.write(zeroes.data(), count - 1); - // at this point we've filled bias to the brim - - p.write("e", 1); - std::string const int_max = std::to_string(INT_MAX); - p.write( int_max.data(), int_max.size() ); + p.write("1e+2147483647", 13); + // 1(INT_MAX - 289 zeroes)1e+2147483647 system::error_code ec; p.finish(ec); - BOOST_TEST( ec == error::exponent_overflow ); + BOOST_TEST(ec == error::exponent_overflow); + BOOST_TEST(ec.has_location()); } -#endif +#endif // BOOST_JSON_NO_LONG_TESTS } //------------------------------------------------------ From 2e8c8195862a7967f41eeb828a8ed7ba6f24760a Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Tue, 18 Aug 2026 18:06:45 +0300 Subject: [PATCH 04/13] memory resource coverage --- test/monotonic_resource.cpp | 8 ++++++++ test/null_resource.cpp | 4 ++-- test/static_resource.cpp | 16 ++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/test/monotonic_resource.cpp b/test/monotonic_resource.cpp index d682b9350..389a17544 100644 --- a/test/monotonic_resource.cpp +++ b/test/monotonic_resource.cpp @@ -186,6 +186,14 @@ class monotonic_resource_test (void)mr.allocate(10,1); } + // equality comparison + { + monotonic_resource mr1; + monotonic_resource mr2; + BOOST_TEST(mr1 != mr2); + BOOST_TEST(mr1 == mr1); + } + // coverage { monotonic_resource mr(std::size_t(-1)-2); diff --git a/test/null_resource.cpp b/test/null_resource.cpp index 5b1b17501..403fe08e0 100644 --- a/test/null_resource.cpp +++ b/test/null_resource.cpp @@ -37,8 +37,8 @@ class null_resource_test #if defined(BOOST_GCC) && BOOST_GCC >= 160000 # pragma GCC diagnostic pop #endif - BOOST_TEST( - mr == *get_null_resource()); + BOOST_TEST( mr == *get_null_resource() ); + BOOST_TEST( mr.is_equal(*get_null_resource()) ); } void diff --git a/test/static_resource.cpp b/test/static_resource.cpp index 5cae9a8ee..d5c3d1dc1 100644 --- a/test/static_resource.cpp +++ b/test/static_resource.cpp @@ -118,6 +118,22 @@ class static_resource_test mr.release(); (void)mr.allocate(10,1); } + + // misc + { + unsigned char b1[1]; + static_resource mr1(b1, 1); + + unsigned char b2[2]; + static_resource mr2(b2, 1); + + BOOST_TEST(mr1 != mr2); + BOOST_TEST(mr1 == mr1); + + // this is for higher coverage + auto const ptr = mr1.allocate(1, 1); + mr1.deallocate(ptr, 1); + } } void From 63bb43a704c5a6fe0e59d4914a482cba027c5772 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Sat, 29 Aug 2026 07:04:03 +0300 Subject: [PATCH 05/13] reformatting of a value constructor Should improve coverage and also make it more readable. --- include/boost/json/impl/value.ipp | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/include/boost/json/impl/value.ipp b/include/boost/json/impl/value.ipp index 34db8cc1d..d979258ab 100644 --- a/include/boost/json/impl/value.ipp +++ b/include/boost/json/impl/value.ipp @@ -225,30 +225,19 @@ value( // //---------------------------------------------------------- -value:: -value( - std::initializer_list init, - storage_ptr sp) +value::value(std::initializer_list init, storage_ptr sp) { - if(value_ref::maybe_object(init)) + if( value_ref::maybe_object(init) ) { - ::new(&obj_) object( - value_ref::make_object( - init, std::move(sp))); + ::new(&obj_) object( value_ref::make_object(init, std::move(sp)) ); + } + else if( init.size() == 1 ) + { + ::new(this) value( init.begin()->make_value(std::move(sp)) ); } else { - if( init.size() == 1 ) - { - ::new(this) value( - init.begin()->make_value( std::move(sp) )); - } - else - { - ::new(&arr_) array( - value_ref::make_array( - init, std::move(sp))); - } + ::new(&arr_) array( value_ref::make_array(init, std::move(sp)) ); } } From 43243fbfd7580dc5eec28926d173e88f5b97fe53 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Sat, 29 Aug 2026 07:05:26 +0300 Subject: [PATCH 06/13] more coverage for value accessors --- test/value.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/value.cpp b/test/value.cpp index 5b11491ad..97ec3dc6e 100644 --- a/test/value.cpp +++ b/test/value.cpp @@ -2268,6 +2268,9 @@ class value_test BOOST_TEST_THROWS_WITH_LOCATION( cjvo.at("null") ); BOOST_TEST( cjvo.try_at("null").error() == error::out_of_range ); + BOOST_TEST_THROWS_WITH_LOCATION( jvo.try_at(1)->as_string() ); + BOOST_TEST_THROWS_WITH_LOCATION( cjvo.try_at(1)->as_string() ); + // array value jva{true,2,"3"}; value const& cjva = jva; @@ -2282,6 +2285,9 @@ class value_test BOOST_TEST( &elem2 == &jva.at(1) ); BOOST_TEST( &elem2 == &*jva.try_at(1) ); + BOOST_TEST_THROWS_WITH_LOCATION( jva.try_at("k1")->as_string() ); + BOOST_TEST_THROWS_WITH_LOCATION( cjva.try_at("k1")->as_string() ); + BOOST_TEST_THROWS_WITH_LOCATION( value({false,2,false}).at(4) ); BOOST_TEST_THROWS_WITH_LOCATION( value({false,2,"3"}).at(4) ); BOOST_TEST_THROWS_WITH_LOCATION( value({false,false}).at(4) ); From 5b25108590c377d2894d597a7b7b81b9ffd428c9 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Sat, 29 Aug 2026 07:11:33 +0300 Subject: [PATCH 07/13] unused value_ref private function removed --- include/boost/json/impl/value_ref.ipp | 12 ------------ include/boost/json/value_ref.hpp | 7 ------- 2 files changed, 19 deletions(-) diff --git a/include/boost/json/impl/value_ref.ipp b/include/boost/json/impl/value_ref.ipp index 890c130c7..1b1b08d38 100644 --- a/include/boost/json/impl/value_ref.ipp +++ b/include/boost/json/impl/value_ref.ipp @@ -24,18 +24,6 @@ value() const return make_value({}); } -value -value_ref:: -from_init_list( - void const* p, - storage_ptr sp) -{ - return make_value( - *reinterpret_cast< - init_list const*>(p), - std::move(sp)); -} - bool value_ref:: is_key_value_pair() const noexcept diff --git a/include/boost/json/value_ref.hpp b/include/boost/json/value_ref.hpp index e3137a308..22e63f9a2 100644 --- a/include/boost/json/value_ref.hpp +++ b/include/boost/json/value_ref.hpp @@ -431,13 +431,6 @@ class value_ref void* p, storage_ptr sp); - static - BOOST_JSON_DECL - value - from_init_list( - void const* p, - storage_ptr sp); - inline bool is_key_value_pair() const noexcept; From e988a3dd272e426dad53cbc7e157487cd690d384 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Sat, 29 Aug 2026 07:26:32 +0300 Subject: [PATCH 08/13] test serialization of 128 bit integers on more configurations --- test/serializer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/serializer.cpp b/test/serializer.cpp index 5268b20f6..5b44e6464 100644 --- a/test/serializer.cpp +++ b/test/serializer.cpp @@ -802,7 +802,8 @@ class serializer_test double d = 3.12; check_udt(d, "3.12e+00"); -#if defined(BOOST_HAS_INT128) && defined(__GLIBCXX_TYPE_INT_N_0) +#if defined(BOOST_HAS_INT128) \ + && defined(BOOST_GCC) && BOOST_GCC_VERSION >= 160000 boost::int128_type ii = (std::numeric_limits::max)(); ii += 1; From 9e1b146f80ee55b737d6f934c9c0a98b62eb41c7 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Sat, 29 Aug 2026 07:43:13 +0300 Subject: [PATCH 09/13] more coverage for serialize --- include/boost/json/impl/serialize.ipp | 4 +--- include/boost/json/impl/serializer.hpp | 2 +- test/serialize.cpp | 8 ++++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/boost/json/impl/serialize.ipp b/include/boost/json/impl/serialize.ipp index 66747e7df..92451fa11 100644 --- a/include/boost/json/impl/serialize.ipp +++ b/include/boost/json/impl/serialize.ipp @@ -80,9 +80,7 @@ serialize_impl( s.max_size() / 2; for(;;) { - sv = sr.read( - &s[0] + len, - s.size() - len); + sv = sr.read(&s[0] + len, s.size() - len); len += sv.size(); if(sr.done()) break; diff --git a/include/boost/json/impl/serializer.hpp b/include/boost/json/impl/serializer.hpp index 0a7255d06..4df3a90fa 100644 --- a/include/boost/json/impl/serializer.hpp +++ b/include/boost/json/impl/serializer.hpp @@ -193,7 +193,7 @@ write_impl(string_like_conversion_tag, writer& w, stream& ss0) # pragma warning( pop ) #endif { - string_view const sv = *reinterpret_cast(w.p_); + string_view const sv = *reinterpret_cast(w.p_); // LCOV_EXCL_LINE w.cs0_ = { sv.data(), sv.size() }; return write_string(w, ss0); } diff --git a/test/serialize.cpp b/test/serialize.cpp index ff3993655..0ed4cafa1 100644 --- a/test/serialize.cpp +++ b/test/serialize.cpp @@ -56,6 +56,14 @@ class serialize_test BOOST_TEST(serialize(str) == "\"123\""); BOOST_TEST(print(str) == "\"123\""); } + { + string const str(BOOST_JSON_STACK_BUFFER_SIZE * 2, '0'); + string str_quoted = str; + str_quoted.insert(0, '"'); + str_quoted.append(1, '"'); + BOOST_TEST(serialize(str) == str_quoted); + BOOST_TEST(print(str) == str_quoted); + } } void From e4d5d157872ab58250f7dad72561edd4ba5b017f Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Thu, 13 Aug 2026 19:16:23 +0300 Subject: [PATCH 10/13] exclude unreachable lines from coverage --- include/boost/json/basic_parser_impl.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/boost/json/basic_parser_impl.hpp b/include/boost/json/basic_parser_impl.hpp index b906b6aaf..071a224c9 100644 --- a/include/boost/json/basic_parser_impl.hpp +++ b/include/boost/json/basic_parser_impl.hpp @@ -434,7 +434,7 @@ parse_comment(const char* p, st_.pop(st); switch(st) { - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE case state::com1: goto do_com1; case state::com2: goto do_com2; case state::com3: goto do_com3; @@ -723,7 +723,7 @@ resume_value(const char* p, st_.peek(st); switch(st) { - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE case state::lit1: return parse_literal(p, detail::literals_c() ); @@ -859,7 +859,7 @@ parse_literal(const char* p, Literal) } else { - BOOST_JSON_UNREACHABLE(); + BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE } cs += sz; @@ -947,7 +947,7 @@ parse_literal(const char* p, Literal) ec_))) return fail(cs.begin()); break; - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE } cs += size; @@ -977,7 +977,7 @@ parse_string(const char* p, st_.pop(total); switch(st) { - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE case state::str2: goto do_str2; case state::str8: goto do_str8; case state::str1: break; @@ -1191,7 +1191,7 @@ parse_escaped( st_.pop(st); switch(st) { - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE case state::str3: goto do_str3; case state::str4: goto do_str4; case state::str5: goto do_str5; @@ -1739,7 +1739,7 @@ parse_object(const char* p, st_.pop(size); switch(st) { - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE case state::obj1: goto do_obj1; case state::obj2: goto do_obj2; case state::obj3: goto do_obj3; @@ -1908,7 +1908,7 @@ parse_array(const char* p, st_.pop(size); switch(st) { - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE case state::arr1: goto do_arr1; case state::arr2: goto do_arr2; case state::arr3: goto do_arr3; @@ -2158,7 +2158,7 @@ parse_number(const char* p, st_.pop(st); switch(st) { - default: BOOST_JSON_UNREACHABLE(); + default: BOOST_JSON_UNREACHABLE(); // LCOV_EXCL_LINE case state::num1: goto do_num1; case state::num2: goto do_num2; case state::num3: goto do_num3; From e044e96512daaaa413c5503e10496afe5a1c6305 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Tue, 22 Sep 2026 18:38:45 +0300 Subject: [PATCH 11/13] ignore coverage false negatives --- include/boost/json/impl/serializer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/json/impl/serializer.hpp b/include/boost/json/impl/serializer.hpp index 4df3a90fa..15927b7e6 100644 --- a/include/boost/json/impl/serializer.hpp +++ b/include/boost/json/impl/serializer.hpp @@ -73,7 +73,7 @@ BOOST_FORCEINLINE bool write_impl(bool_conversion_tag, writer& w, stream& ss) { - BOOST_ASSERT( w.p_ ); + BOOST_ASSERT( w.p_ ); // LCOV_EXCL_LINE auto const t = *reinterpret_cast(w.p_); #if defined(_MSC_VER) From b19454afb3bf6327b01a1ae7cb2a16124b77445e Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Tue, 22 Sep 2026 21:32:13 +0300 Subject: [PATCH 12/13] coverage for string capacity growth overflow --- test/limits.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/test/limits.cpp b/test/limits.cpp index 3d5b485a9..73156b100 100644 --- a/test/limits.cpp +++ b/test/limits.cpp @@ -192,19 +192,12 @@ class limits_test (s.insert(0, s.subview(0, 10))) ); } - #if 0 { - // VFALCO tsan doesn't like this + // capacity overflow string s; - try - { - s.resize(s.max_size() - 1); - } - catch(std::exception const&) - { - } + s.reserve(s.max_size() - 1); + s.reserve(s.max_size()); } - #endif } // string in parser From fc70d2313193b490fc728593e3b8b4e763065548 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Tue, 22 Sep 2026 21:43:57 +0300 Subject: [PATCH 13/13] coverage for non-shrinking case of shrink_to_fit --- test/string.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/string.cpp b/test/string.cpp index 35a5e23b2..ed88c3e8e 100644 --- a/test/string.cpp +++ b/test/string.cpp @@ -1395,6 +1395,14 @@ class string_test BOOST_TEST(s.size() == n); BOOST_TEST(s.capacity() == sbo_capacity); BOOST_TEST(s == string_view(copy.data(), n)); + + s.resize(sbo_capacity + 1); + cap = s.capacity(); + s.resize(cap); + s.shrink_to_fit(); + BOOST_TEST(s.capacity() == cap); + s.shrink_to_fit(); + BOOST_TEST(s.capacity() == cap); }); }