Make the "buffers are large enough" reasoning explicit: before the copy,
assert that `copied` fits both the caller-provided destination (`wanted`
bytes) and the remaining input range (`available` bytes). These hold by
construction (`copied = min(wanted, available)`) but were previously only
implied; the asserts document the invariant and would catch a future
regression that breaks it.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Flawfinder flags the bare identifier `read` as the POSIX read() syscall
(CWE-120/CWE-20), producing several false-positive code-scanning alerts.
Renaming the local variable removes them; the byte-copy itself is
unchanged and remains bounds-checked (get_elements caps the copy to the
bytes available). This is a pure rename with identical semantics.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- get_bytes(): replace `len -= static_cast<NumberType>(wanted)` with an
explicit `len = static_cast<NumberType>(len - ...)`. The compound
assignment promoted the operands to int and narrowed back, which GCC
rejects under -Werror=arith-conversion when NumberType is narrower than
int (e.g. UBJSON's int16 length). This also fixes the CodeQL build.
- get_bytes(): add JSON_ASSERT(read == wanted) documenting that
get_elements() never returns more than requested (per review).
- iterator_input_adapter: de-duplicate the iterator_is_contiguous
definition with the #if inside the initializer (per review).
- Add a comment explaining why the memcpy source is &*current (needed for
non-pointer contiguous iterators), and drop the redundant parentheses.
- Run astyle on the new unit test so the amalgamation/format check passes.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The binary reader read CBOR/MessagePack/BSON/UBJSON strings and byte
arrays one byte at a time via get()/push_back(), and the iterator input
adapter's get_elements() fallback was itself a per-byte loop, so even
contiguous inputs never benefited from a block copy.
Two changes:
1. iterator_input_adapter::get_elements() gains a contiguous fast path
that copies the whole requested range with std::memcpy. Contiguity is
detected via std::is_pointer (all standards) and, in C++20,
std::contiguous_iterator (so std::vector/std::string iterators also
qualify). Non-contiguous iterators keep the element-by-element loop.
2. get_string()/get_binary() now share get_bytes(), which reads into the
result in bounded chunks through get_elements() instead of byte by
byte. Capping the chunk size preserves the deliberate "do not
reserve(len) for an untrusted length" DoS protection while turning the
inner loop into block copies. The min(chunk_size, len) computation is
width-safe so narrow length types (e.g. MessagePack ext-8's uint8_t)
cannot truncate chunk_size to zero.
Microbenchmark (2 MiB string + 2 MiB blob + 2000x1 KiB strings, Apple
clang, -O2):
C++20 from_cbor(vector) 20.1 ms -> 1.0 ms (~20x)
from_cbor(pointer) 18.9 ms -> 1.0 ms (~19x)
C++17 from_cbor(pointer) 18.7 ms -> 1.0 ms (~19x, memcpy)
from_cbor(vector) 18.7 ms -> 4.0 ms (~4.6x, tight loop)
Behavior is unchanged: truncated input still throws parse_error.110 at
the same byte offset, and all binary-format unit tests pass.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Added NLOHNMANN_JSON_SERIALIZE_ENUM_STRICT
- duplicate of NLOHMANN_JSON_SERIALIZE_ENUM
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* Added failing tests for NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* modified NLOHMANN_JSON_SERIALIZE_STRICT to throw
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* added documentation and changed readme to include NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* ran amalgamate
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* docs(macros): add page for JSON_SERIALIZE_ENUM_STRICT
- added page to nav
- added links to new page where appropriate
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* refactor(macros): make JSON_SERIALIZE_ENUM_STRICT use JSON_THROW
- added templated wrapper function to fix scope error in calling JSON_THROW
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* refactor(macros): make NLOHMANN_SERIALIZE_ENUM_STRICT use error code 410
- added error code 410 to docs
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* tests(macros): add test for to_json with enum value not mentioned
in mapping for NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* Apply suggestions from code review
Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com>
Signed-off-by: Caillin Nugent <nugentcaillin@gmail.com>
* fix(macro): prevent compilation error with -Werror and -Wunused-parameter
with NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
- casted exception to void to avoid warning
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* fix(docs): add link to NLOHMANN_SERIALIZE_ENUM_STRICT docs to exception page
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* docs(macros): add example of exception throwing for NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
* refactor(macros): add more in-depth error message to NLOHMANN_JSON_SERIALIZE_ENUM_STRICT
- changed error message to follow style of nlohmann/json#4989
- made description of throw wrapper more general
- updated tests and example of exceptions
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
---------
Signed-off-by: Caillin Nugent <caillinn@student.unimelb.edu.au>
Signed-off-by: Caillin Nugent <nugentcaillin@gmail.com>
Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com>
* Add new macros for named conversions
* Unit tests for the named conversion macros
* Update the docs to include the new macros
* Fix the documentation for the macros
the correct maximum number of member variables is 63
* Fix CI tests
* update the named macros
* move the example files
* update the explicit macros expansion
* update documentation
* fix documentation hiccups
* astyle changes
* add static analysis exceptions
* change md header to explicit html to fit the length
* Small corrections to docs
Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com>
Signed-off-by: George Sedov <radist.morse@gmail.com>
---------
Signed-off-by: George Sedov <radist.morse@gmail.com>
Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com>
* Fix compile error when using nlohmann ordered_map with WITH_DEFAULT macros
ordered_map inherits its copy and move assignment from the underlying std vector, which requires value_type to be CopyAssignable. value_type is pair<const Key, T> whose assignment is deleted because of the const Key, so any code that assigns ordered_map (for example the ternary in NLOHMANN_JSON_FROM_WITH_DEFAULT) fails to compile (issue #5122). Provide assignment operators on ordered_map that rebuild via clear plus push_back for copy and transfer the underlying buffer for move, neither of which needs pair assignment. Also switch the map-shaped from_json overload from a transform plus inserter idiom to a range-for plus emplace, which avoids the same hazard.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Update ordered_map.hpp
removed unwanted comments
Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Update json.hpp
Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Address CI issues for ordered_map fix
Declare an explicit defaulted destructor on ordered_map so the rule of five is complete (clang-tidy cppcoreguidelines-special-member-functions and hicpp-special-member-functions). Initialize the ordered_map field in the regression test struct so GCC effective-C++ stops flagging Example_5122 with a missing member initializer.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Suppress redundant-member-init lint on Example_5122::c
The empty brace-init on c{} is required by GCC -Weffc++ to mark the member as initialized in the synthesized default constructor, but clang-tidy readability-redundant-member-init flags the same line because ordered_map already has a default constructor. The two checks pull in opposite directions, so add a targeted NOLINT to keep both happy.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Address review: strong exception safety in copy-assign, simplify move-assign noexcept
Copy assignment now constructs a temporary copy before move-assigning the
Container subobject, preserving *this if the copy throws. Move assignment
uses std::is_nothrow_move_assignable<Container> for a cleaner noexcept
specifier, matching the style of the move constructor.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Restore self-assignment check in copy-assign to satisfy cert-oop54-cpp
clang-tidy's cert-oop54-cpp flagged the previous revision because it could
not recognize the implicit self-safety of the copy-then-move pattern.
Restore the explicit `if (this != &other)` guard — strong exception safety
is preserved since the temporary copy is still constructed before the
move-assign of the Container subobject.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Address review: add explicit self-assignment and move-assignment tests for ordered_map
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Address review: gate -Wself-assign-overloaded suppression on Clang version
-Wself-assign-overloaded was introduced in Clang 7. Older Clang versions fail the build with "unknown warning group" when the suppression pragma references it unconditionally. Use __has_warning inside an __clang__ branch so the suppression is only emitted on Clang versions that recognize the warning. The inner check stays inside the __clang__ guard because GCC does not provide __has_warning and would tokenize-error on the argument list.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Address CI: drop unused gating macro to silence -Wunused-macros
The previous attempt defined JSON_TEST_5122_SUPPRESS_SELF_ASSIGN_OVERLOADED
as 0 unconditionally and then overrode it to 1 on Clang versions that recognize the warning. On those Clangs the initial define is immediately
undef'd without being read, which trips Clang's -Wunused-macros under -Weverything in the ci_test_clang job. Drop the macro and gate the
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH/POP pragmas directly with __has_warning inside the existing __clang__ branch.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
---------
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
When iteration_proxy_value<iter_impl<ordered_json>> appears in a context
that requires it to be complete (function or lambda parameter), the
compiler instantiates basic_json<ordered_map> and walks into
set_parents(iterator, typename iterator::difference_type)
while iterator is still incomplete, failing with "invalid use of
incomplete type".
basic_json::difference_type is already std::ptrdiff_t, so just naming
the underlying type directly avoids the dependent lookup. Behavior and
ABI are unchanged. This was the approach suggested in the issue thread.
Added a regression case in unit-ordered_json.cpp using the same trigger
pattern (lambda parameter naming the proxy type).
Fixes#3732
Signed-off-by: Akhilesh Arora <akhildawra@gmail.com>
* fix: treat single-element brace-init as copy/move
When passing a json value using brace initialization with a single element
(e.g., `json j{someObj}` or `foo({someJson})`), C++ always prefers the
initializer_list constructor over the copy/move constructor. This caused
the value to be unexpectedly wrapped in a single-element array.
This bug was previously compiler-dependent (GCC wrapped, Clang did not),
but Clang 20 started matching GCC behavior, making it a universal issue.
Fix: In the initializer_list constructor, when type deduction is enabled
and the list has exactly one element, copy/move it directly instead of
creating a single-element array.
Before:
json obj = {{"key", 1}};
json j{obj}; // -> [{"key":1}] (wrong: array)
foo({obj}); // -> [{"key":1}] (wrong: array)
After:
json j{obj}; // -> {"key":1} (correct: copy)
foo({obj}); // -> {"key":1} (correct: copy)
To explicitly create a single-element array, use json::array({value}).
Fixes the issue #5074
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* fix: regenerate amalgamated single_include/nlohmann/json.hpp
- Add missing comment from include/nlohmann/json.hpp explaining the
single-element brace-init fix (issue #5074)
- Fix extra 4-space indentation in embedded json_fwd.hpp section
Regenerated by running: make amalgamate
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Revert brace-init semantics change and fix amalgamation
The single-element brace-init change was a breaking change that cannot be accepted upstream. Reverted all related source, test, and doc changes, then regenerated single_include with correct indentation to pass the amalgamation CI check.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* Fix: add JSON_BRACE_INIT_COPY_SEMANTICS opt-in macro for issue #5074
Single-element brace initialization wrapping in an array cannot be fixed without breaking existing code. Added JSON_BRACE_INIT_COPY_SEMANTICS as an opt-in macro (default 0) so users can enable copy/move semantics for single-element brace init without affecting anyone relying on the current behavior.
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* docs: add dedicated macro page and CI test target for JSON_BRACE_INIT_COPY_SEMANTICS
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* fix: remove compiler-dependent assertions from #5074 regression test
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* fix: use defined() guard for JSON_BRACE_INIT_COPY_SEMANTICS to satisfy -Wundef
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* docs: fix section name in json_brace_init_copy_semantics.md to pass style check
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
* docs: move Default definition section before Notes to fix style check order
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
---------
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
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>
* Add reference handling to tuples
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* Remove template template type because pair isn't working
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* amalgamate std::tie changes
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* allow the elation of a move by removing the ref requirement
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* force all number_xxx_t to be interchangeable
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* Finally got amalgamate to work correctly
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* remove const version, add a test case for scrambled number representations.
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* Use the logical set of requirements instead of decltype because VS 2015 doesn't like it
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
---------
Signed-off-by: Evelyn LePain <ava.lepain@gmail.com>
* fix(cbor): reject negative ints overflowing int64
CBOR encodes negative integers as "-1 - n" where n is uint64_t. When
n > INT64_MAX, casting to int64_t caused undefined behavior and silent
data corruption. Large negative values were incorrectly parsed as
positive integers (e.g., -9223372036854775809 became 9223372036854775807).
Add bounds check for to reject values that exceed int64_t
representable range, returning parse_error instead of silently
corrupting data.
Added regression test cases to verify.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
* chore: clarify tests
Add test for "n=0" case (result=-1) to cover the smallest magnitude
boundary. Update comments to explain CBOR 0x3B encoding and why
"result=0" is not possible. Clarify that n is an unsigned integer
in the formula "result = -1 - n" to help understanding the tests.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
* fix(cbor): extend overflow checks for other types
Extend negative integer overflow detection to all CBOR negative
integer cases (0x38, 0x39, 0x3A) for consistency with the existing
0x3B check.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
---------
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
Adds pre-multiplication overflow detection to catch cases where dimension
products would exceed size_t max. The previous check only detected when
overflow resulted in exactly 0 or SIZE_MAX, missing other cases.
Retains the original post-multiplication check for backward compatibility.
Adds tests verifying overflow detection with dimensions (2^32+1)×(2^32),
which previously overflowed silently to 2^32.
This prevents custom SAX handlers from receiving incorrect array sizes
that could lead to buffer overflows.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>