From aba59d4cb8fcb6b4f66327b471fb0bff121b9ab7 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 2 Mar 2026 04:15:25 +0900 Subject: [PATCH] Remove nonnull attribute from sax_parse to fix null check optimization Clang with -O2 and -DNDEBUG optimizes away the 'sax == nullptr' safety check in sax_parse() because the parameter is annotated with JSON_HEDLEY_NON_NULL. This makes the compiler assume nullptr is never passed, allowing it to eliminate the check entirely. The result is a segfault instead of a proper exception. The existing #pragma workaround only suppresses the compiler warning but does not prevent the optimization. Remove JSON_HEDLEY_NON_NULL from all three sax_parse overloads (and the corresponding diagnostic pragmas that are no longer needed) in both include/ and single_include/ headers. Fixes #5048 --- include/nlohmann/json.hpp | 39 -------------------------------- single_include/nlohmann/json.hpp | 39 -------------------------------- 2 files changed, 78 deletions(-) diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 0b8f155ac5..03ec66acf0 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -4115,29 +4115,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief generate SAX events /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ template - JSON_HEDLEY_NON_NULL(2) static bool sax_parse(InputType&& i, SAX* sax, input_format_t format = input_format_t::json, const bool strict = true, 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(i)); return format == input_format_t::json ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict) @@ -4147,29 +4134,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief generate SAX events /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ template - JSON_HEDLEY_NON_NULL(3) static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, input_format_t format = input_format_t::json, const bool strict = true, 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) @@ -4183,29 +4157,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// sax_parse(ptr, ptr + len) instead. template JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) - JSON_HEDLEY_NON_NULL(2) static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, input_format_t format = input_format_t::json, const bool strict = true, 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) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index e2bb8517b6..95412f8dc3 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -24352,29 +24352,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief generate SAX events /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ template - JSON_HEDLEY_NON_NULL(2) static bool sax_parse(InputType&& i, SAX* sax, input_format_t format = input_format_t::json, const bool strict = true, 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(i)); return format == input_format_t::json ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict) @@ -24384,29 +24371,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief generate SAX events /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/ template - JSON_HEDLEY_NON_NULL(3) static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, input_format_t format = input_format_t::json, const bool strict = true, 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) @@ -24420,29 +24394,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// sax_parse(ptr, ptr + len) instead. template JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) - JSON_HEDLEY_NON_NULL(2) static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, input_format_t format = input_format_t::json, const bool strict = true, 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)