Remove nullptr safety check from sax_parse functions (#5139)

PR #4873 introduced a safety check in sax_parse functions to catch
nullptr passed as SAX parser object, which had been already annotated by
JSON_HEDLEY_NON_NULL macro.

Compilers (e.g. clang) which respected the non-null annotation tended to
eliminate the safety check completely in optimized builds, while
compilers which did not, compiled the safety check in. This led to
different behaviors accross different compilers/platforms  and/or build
types (debug, release).

This commit reverts PR #4873 to remove this discrepancy. Passing null to
non-null annotated parameter is considered to be undefined behavior.

Fixes #5048

Signed-off-by: Richard Musil <risa2000x@gmail.com>
Co-authored-by: Richard Musil <risa2000x@gmail.com>
This commit is contained in:
risa2000
2026-05-08 07:55:02 +02:00
committed by GitHub
parent a038cc4ef8
commit fd17b0889e
4 changed files with 0 additions and 133 deletions
-10
View File
@@ -900,13 +900,3 @@ A JSON Patch operation 'test' failed. The unsuccessful operation is also printed
```
[json.exception.other_error.501] unsuccessful: {"op":"test","path":"/baz","value":"bar"}
```
### json.exception.other_error.502
This exception is thrown when a null pointer is passed as SAX event listener to the [sax_parse](../api/basic_json/sax_parse.md) function.
!!! failure "Example message"
```
[json.exception.other_error.502] SAX handler must not be null
```
-48
View File
@@ -4122,22 +4122,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
if (sax == nullptr)
{
JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
auto ia = detail::input_adapter(std::forward<InputType>(i));
return format == input_format_t::json
? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
@@ -4154,22 +4138,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
if (sax == nullptr)
{
JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
auto ia = detail::input_adapter(std::move(first), std::move(last));
return format == input_format_t::json
? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
@@ -4190,22 +4158,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
if (sax == nullptr)
{
JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
auto ia = i.get();
return format == input_format_t::json
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
-48
View File
@@ -24359,22 +24359,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
if (sax == nullptr)
{
JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
auto ia = detail::input_adapter(std::forward<InputType>(i));
return format == input_format_t::json
? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
@@ -24391,22 +24375,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
if (sax == nullptr)
{
JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
auto ia = detail::input_adapter(std::move(first), std::move(last));
return format == input_format_t::json
? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
@@ -24427,22 +24395,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
const bool ignore_comments = false,
const bool ignore_trailing_commas = false)
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
if (sax == nullptr)
{
JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
}
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
auto ia = i.get();
return format == input_format_t::json
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
-27
View File
@@ -1644,33 +1644,6 @@ TEST_CASE("parser class")
SECTION("SAX parser")
{
SECTION("null sax handler")
{
# if defined(__has_feature)
#if !__has_feature(undefined_behavior_sanitizer)
const std::string s = "some_string";
SaxCountdown* p = nullptr;
CHECK_THROWS_WITH_AS(json::sax_parse(s, p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker)
CHECK_THROWS_WITH_AS(json::sax_parse(s.begin(), s.end(), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker)
CHECK_THROWS_WITH_AS(json::sax_parse(nlohmann::detail::span_input_adapter(s.c_str(), s.size()), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker)
#endif
#else
const std::string s = "some_string";
SaxCountdown* p = nullptr;
CHECK_THROWS_WITH_AS(json::sax_parse(s, p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker)
CHECK_THROWS_WITH_AS(json::sax_parse(s.begin(), s.end(), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker)
CHECK_THROWS_WITH_AS(json::sax_parse(nlohmann::detail::span_input_adapter(s.c_str(), s.size()), p), "[json.exception.other_error.502] SAX handler must not be null", json::other_error&); // NOLINT(clang-analyzer-core.NonNullParamChecker)
#endif
}
SECTION("valid sax handler")
{
const std::string str = "some_string";
SaxCountdown s(1);
CHECK(json::sax_parse(str, &s) == false);
CHECK(json::sax_parse(nlohmann::detail::span_input_adapter(str.c_str(), str.size()), &s) == false);
}
SECTION("} without value")
{
SaxCountdown s(1);