Fix the remaining CI failures of the tests from #5997 and #5991

- unit-custom-object-key-type: drop the redundant member initializer and
  return a braced init list (clang-tidy); direct-initialize the converted
  value, as copy-initialization makes GCC 4.8 instantiate the copy
  constructor, which needs a range constructor strict_object lacks
- unit-stream-bulk-scan: pick the claimed get area size by tag dispatch
  instead of a constant condition (MSVC C4127)
- unit-allocator: skip the parser callback and sax_parse sweeps with
  Clang 3.4 and 3.5, which leak memory when an element constructor throws
  inside a libstdc++ std::map copy or std::vector reallocation

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-11-03 07:11:04 +01:00
1 parent 59ccf04a39
commit cd83d48100
3 files changed
+25 -4

No files matched your search

+5
View File
@@ -1167,6 +1167,10 @@ TEST_CASE("parse() survives a failing allocation at every point (#5985)")
// terminates the program instead of throwing std::bad_alloc. Nothing to // terminates the program instead of throwing std::bad_alloc. Nothing to
// check there. // check there.
#if !(defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL > 0) #if !(defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL > 0)
// Clang 3.4 and 3.5 leak memory when an element constructor throws
// inside libstdc++'s containers (a std::map copy, a std::vector
// reallocation), without any json value involved.
#if !(defined(__clang__) && !defined(__apple_build_version__) && __clang_major__ == 3 && __clang_minor__ < 6)
SECTION("parser callback") SECTION("parser callback")
{ {
const auto keep_all = [](int /*depth*/, sweep_json::parse_event_t /*event*/, sweep_json& /*parsed*/) noexcept const auto keep_all = [](int /*depth*/, sweep_json::parse_event_t /*event*/, sweep_json& /*parsed*/) noexcept
@@ -1201,5 +1205,6 @@ TEST_CASE("parse() survives a failing allocation at every point (#5985)")
}); });
} }
#endif #endif
#endif
} }
#endif #endif
+5 -3
View File
@@ -160,12 +160,12 @@ class strict_key
} }
private: private:
std::string m_value{}; std::string m_value;
}; };
strict_key make_strict_key(const std::string& key) strict_key make_strict_key(const std::string& key)
{ {
return strict_key(key.c_str()); return {key.c_str()};
} }
template<class Key, class Value, class Compare, class Allocator> template<class Key, class Value, class Compare, class Allocator>
@@ -224,7 +224,9 @@ TEST_CASE("converting a value with keys that cannot be made from a std::string n
} }
} }
const strict_json converted = value; // direct-initialization: a copy-initialization makes GCC 4.8 instantiate the
// copy constructor, which needs a range constructor strict_object lacks
const strict_json converted(value);
// at() needs to make a std::string of a key for its error message // at() needs to make a std::string of a key for its error message
const auto member = [](const strict_json & object, const char* name) -> const strict_json & const auto member = [](const strict_json & object, const char* name) -> const strict_json &
+15 -1
View File
@@ -120,6 +120,20 @@ class oversized_get_area_streambuf : public std::streambuf
private: private:
std::array<char, 8> m_data{{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}}; std::array<char, 8> m_data{{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}};
}; };
// the size the oversized_get_area_streambuf claims: 3 GiB with a 64-bit
// std::size_t, else 0 to skip the test (tag dispatch, as a constant condition
// triggers MSVC's C4127)
template<std::size_t SizeOfSizeT>
std::size_t oversized_get_area_size(std::integral_constant<std::size_t, SizeOfSizeT> /*unused*/)
{
return 0;
}
std::size_t oversized_get_area_size(std::integral_constant<std::size_t, 8> /*unused*/)
{
return std::size_t{3} << 30u;
}
#endif #endif
// how a test reads from the stream // how a test reads from the stream
@@ -466,7 +480,7 @@ TEST_CASE("parsing from a std::istream scans the get area in bulk")
SECTION("skipping more characters than gbump() takes at once") SECTION("skipping more characters than gbump() takes at once")
{ {
// gbump() takes an int, but a get area can be larger // gbump() takes an int, but a get area can be larger
const std::size_t claimed = sizeof(std::size_t) < 8 ? 0 : std::size_t{3} << 30u; const std::size_t claimed = oversized_get_area_size(std::integral_constant<std::size_t, sizeof(std::size_t)>());
oversized_get_area_streambuf buf(claimed); oversized_get_area_streambuf buf(claimed);
if (claimed == 0 || static_cast<std::size_t>(buf.in_avail()) != claimed) if (claimed == 0 || static_cast<std::size_t>(buf.in_avail()) != claimed)
{ {