From 07876e22920ccc6770af188f4eb2ba4febb98508 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 2 Nov 2026 19:11:07 +0100 Subject: [PATCH 1/2] json_view: a value that is not found has no bytes in its exception context (#6015) --- include/nlohmann/detail/view/errors.hpp | 8 ++++++-- single_include/nlohmann/json_view.hpp | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/view/errors.hpp b/include/nlohmann/detail/view/errors.hpp index 3c97cef5c..74597edf0 100644 --- a/include/nlohmann/detail/view/errors.hpp +++ b/include/nlohmann/detail/view/errors.hpp @@ -251,8 +251,12 @@ std::string diagnostics(const error_site site) std::string context; #if JSON_DIAGNOSTICS std::vector tokens; - // a value that is not found leaves no tokens, like the root - static_cast(edited ? value_path(d, site.value(), tokens) : value_path(d, site.value(), tokens)); + const bool found = edited ? value_path(d, site.value(), tokens) : value_path(d, site.value(), tokens); + if (!found) + { + // a value that is not found has no path, and with it no bytes + return context; + } if (!tokens.empty()) { // the root value has no path, but still has a byte range diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index ea04acdbe..1c6cd6cef 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -5080,8 +5080,12 @@ std::string diagnostics(const error_site site) std::string context; #if JSON_DIAGNOSTICS std::vector tokens; - // a value that is not found leaves no tokens, like the root - static_cast(edited ? value_path(d, site.value(), tokens) : value_path(d, site.value(), tokens)); + const bool found = edited ? value_path(d, site.value(), tokens) : value_path(d, site.value(), tokens); + if (!found) + { + // a value that is not found has no path, and with it no bytes + return context; + } if (!tokens.empty()) { // the root value has no path, but still has a byte range From baba5db36f1747556499d70067a60b56d8989c06 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 2 Nov 2026 20:07:00 +0100 Subject: [PATCH 2/2] Fix the MSVC and GCC builds of develop (C4127, -Weffc++) (#6016) json_view number(): #6006 folded the check of the digit after a minus sign into `else if (!negative || ...)`, which MSVC 19.44 reports as C4127 (conditional expression is constant) and /WX turns into an error in every MSVC and clang-cl job. The check now sits in the `if (negative)` block, right after the sign is skipped; the error and its position are unchanged. unit-locale-cpp.cpp: the locale_switching_token added in #5997 held a `const char*`, so GCC's -Weffc++ asked for a copy constructor and copy assignment. The locale name is now a std::string. Signed-off-by: Niels Lohmann --- include/nlohmann/detail/view/builder.hpp | 12 ++++++------ single_include/nlohmann/json_view.hpp | 12 ++++++------ tests/src/unit-locale-cpp.cpp | 8 ++++---- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/nlohmann/detail/view/builder.hpp b/include/nlohmann/detail/view/builder.hpp index 283cae075..14be4ea7c 100644 --- a/include/nlohmann/detail/view/builder.hpp +++ b/include/nlohmann/detail/view/builder.hpp @@ -1168,20 +1168,20 @@ indent_done: if (negative) { ++p; + if (NLOHMANN_VIEW_UNLIKELY(cur() < '0' || cur() > '9')) + { + return fail(error_code::number_after_minus); + } } const unsigned char* const int_start = p; if (cur() == '0') { ++p; } - else if (!negative || NLOHMANN_VIEW_LIKELY(cur() >= '1' && cur() <= '9')) - { - // (without a sign, the dispatch saw a digit) - p = skip_digits(p + 1, e); - } else { - return fail(error_code::number_after_minus); + // (a digit: the dispatch or the check after the sign saw it) + p = skip_digits(p + 1, e); } const auto int_digits = static_cast(p - int_start); std::size_t frac_digits = 0; diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index 1c6cd6cef..22c72d982 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -2473,20 +2473,20 @@ indent_done: if (negative) { ++p; + if (NLOHMANN_VIEW_UNLIKELY(cur() < '0' || cur() > '9')) + { + return fail(error_code::number_after_minus); + } } const unsigned char* const int_start = p; if (cur() == '0') { ++p; } - else if (!negative || NLOHMANN_VIEW_LIKELY(cur() >= '1' && cur() <= '9')) - { - // (without a sign, the dispatch saw a digit) - p = skip_digits(p + 1, e); - } else { - return fail(error_code::number_after_minus); + // (a digit: the dispatch or the check after the sign saw it) + p = skip_digits(p + 1, e); } const auto int_digits = static_cast(p - int_start); std::size_t frac_digits = 0; diff --git a/tests/src/unit-locale-cpp.cpp b/tests/src/unit-locale-cpp.cpp index 441563b3c..19c08166c 100644 --- a/tests/src/unit-locale-cpp.cpp +++ b/tests/src/unit-locale-cpp.cpp @@ -505,8 +505,8 @@ struct locale_switching_token { using value_type = char; - locale_switching_token(std::string text_, const char* switch_to_) - : text(std::move(text_)), switch_to(switch_to_) + locale_switching_token(std::string text_, std::string switch_to_) + : text(std::move(text_)), switch_to(std::move(switch_to_)) {} std::size_t size() const @@ -523,13 +523,13 @@ struct locale_switching_token { if (!switched) { - switched = std::setlocale(LC_NUMERIC, switch_to) != nullptr; + switched = std::setlocale(LC_NUMERIC, switch_to.c_str()) != nullptr; } return &text[0]; } std::string text; - const char* switch_to; + std::string switch_to; bool switched = false; };