Repro:
TEST_CASE("SECBUG-4103: from_json length truncated to negative int32", "[secbug_4103][!benchmark]") { // Smallest size whose int32 truncation is negative: 2^31 -> INT32_MIN. constexpr std::size_t size = std::size_t{1} << 31; REQUIRE(static_cast<std::int32_t>(size) < 0); // No NUL byte anywhere in the buffer, so libbson's strlen fallback runs off // the end. Leading '{' keeps it plausible JSON rather than an early reject // (the over-read happens before any parsing regardless). auto buf = std::unique_ptr<char[]>{new char[size]}; std::memset(buf.get(), 'a', size); buf[0] = '{'; stdx::string_view json{buf.get(), size}; REQUIRE(json.size() == size); // strlen over-reads past the end of the 2 GiB allocation. REQUIRE_THROWS(from_json(json)); }
Suggested fix:
Throw exception if input length does not safely cast.