* Document clang-tidy exclusions and drop unneeded ones Re-enable every excluded check in a run of clang-tidy 22 over all tests and remove the seven that never fire (cert-err58-cpp, clang-analyzer-webkit.NoUncountedMemberChecker, cppcoreguidelines-virtual-class-destructor, google-readability-function-size, hicpp-function-size, hicpp-no-assembler, readability-function-size). Document the reason for every remaining exclusion at the top of the file. Exclude in advance the checks that only exist in clang-tidy 23 and are noise here (bugprone-signed-bitwise, *-explicit-constructor, readability-trailing-comma, modernize-use-string-view), plus modernize-use-integer-sign-comparison, which needs C++20 std::cmp_less and flags deliberate casts. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Fix clang-tidy findings in documentation examples and replace redundant aliases Apply clang-tidy fixes to the documentation examples: - performance-avoid-endl: std::endl -> '\n' - readability-qualified-auto: auto -> auto* / const auto* - performance-for-range-copy: copy -> const reference - google-readability-casting: C-style cast -> static_cast Replace redundant aliases (readability-redundant-qualified-alias) such as "using json = nlohmann::json;" with "using nlohmann::json;" in the documentation, README, examples, tests, and benchmarks. Aliases at class scope and aliases of other types (with_base_class_t etc.) are kept. No changes to the library or its public API. All changed examples were compiled and run; their output matches the stored .output files (except max_size and meta, which depend on the platform and compiler). Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Format doc examples with the pinned astyle Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
96 lines
3.0 KiB
C++
96 lines
3.0 KiB
C++
// __ _____ _____ _____
|
|
// __| | __| | | | JSON for Modern C++ (supporting code)
|
|
// | | |__ | | | | | | version 3.12.0
|
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|
//
|
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
/*
|
|
This file implements a test of json_document images suitable for fuzz
|
|
testing. The input is used twice:
|
|
|
|
- as an image: json_document::load() with image_check::full must either throw
|
|
a parse_error or yield a document that serializes to the JSON text it reads
|
|
as; with image_check::bounds, reading and serializing must be safe (checked
|
|
by the sanitizers), and serializing may only throw type_error.316
|
|
- as a JSON text: if json_document::parse() accepts it, the image of the
|
|
document must load (with every check) and serialize to the same text
|
|
|
|
The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer
|
|
drivers.
|
|
*/
|
|
|
|
#include <cassert>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <nlohmann/json.hpp>
|
|
#include <nlohmann/json_view.hpp>
|
|
|
|
// the checks below are assertions; NDEBUG would compile them away
|
|
#ifdef NDEBUG
|
|
#error "the fuzzer drivers must be built without NDEBUG"
|
|
#endif
|
|
|
|
using nlohmann::json;
|
|
using nlohmann::json_document;
|
|
using image_check = json_document::image_check;
|
|
|
|
// see http://llvm.org/docs/LibFuzzer.html
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
|
{
|
|
// the input as an image
|
|
for (const image_check check :
|
|
{
|
|
image_check::full, image_check::bounds
|
|
})
|
|
{
|
|
json_document d;
|
|
try
|
|
{
|
|
d = json_document::load(data, size, check);
|
|
}
|
|
catch (const json::parse_error& e)
|
|
{
|
|
assert(e.id == 116);
|
|
continue;
|
|
}
|
|
std::string dumped;
|
|
try
|
|
{
|
|
dumped = d.root().dump();
|
|
}
|
|
catch (const json::type_error& e)
|
|
{
|
|
// invalid UTF-8 can only pass the bounds check
|
|
assert(check == image_check::bounds && e.id == 316);
|
|
continue;
|
|
}
|
|
const json j = d.root().materialize();
|
|
if (check == image_check::full)
|
|
{
|
|
assert(json::parse(dumped) == j);
|
|
// an image of the loaded document is the input
|
|
assert(d.save() == std::vector<std::uint8_t>(data, data + size));
|
|
}
|
|
}
|
|
|
|
// the input as a JSON text
|
|
const std::string text(reinterpret_cast<const char*>(data), size); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
|
|
const json_document parsed = json_document::parse(text, false);
|
|
if (!parsed.is_discarded())
|
|
{
|
|
const std::vector<std::uint8_t> image = parsed.save();
|
|
for (const image_check check :
|
|
{
|
|
image_check::full, image_check::bounds, image_check::none
|
|
})
|
|
{
|
|
const json_document loaded = json_document::load(image, check);
|
|
assert(loaded.root().dump() == parsed.root().dump());
|
|
}
|
|
}
|
|
return 0;
|
|
}
|