/src/json/tests/src/fuzzer-parse_bjdata.cpp
Line | Count | Source |
1 | | // __ _____ _____ _____ |
2 | | // __| | __| | | | JSON for Modern C++ (supporting code) |
3 | | // | | |__ | | | | | | version 3.12.0 |
4 | | // |_____|_____|_____|_|___| https://github.com/nlohmann/json |
5 | | // |
6 | | // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me> |
7 | | // SPDX-License-Identifier: MIT |
8 | | |
9 | | /* |
10 | | This file implements a parser test suitable for fuzz testing. Given a byte |
11 | | array data, it performs the following steps: |
12 | | |
13 | | - j1 = from_bjdata(data) |
14 | | - vec = to_bjdata(j1) |
15 | | - j2 = from_bjdata(vec) |
16 | | - assert(j1 == j2) |
17 | | - vec2 = to_bjdata(j1, use_size = true, use_type = false) |
18 | | - j3 = from_bjdata(vec2) |
19 | | - assert(j1 == j3) |
20 | | - vec3 = to_bjdata(j1, use_size = true, use_type = true) |
21 | | - j4 = from_bjdata(vec3) |
22 | | - assert(j1 == j4) |
23 | | |
24 | | The provided function `LLVMFuzzerTestOneInput` can be used in different fuzzer |
25 | | drivers. |
26 | | */ |
27 | | |
28 | | #include <iostream> |
29 | | #include <sstream> |
30 | | #include <nlohmann/json.hpp> |
31 | | |
32 | | using json = nlohmann::json; |
33 | | |
34 | | // see http://llvm.org/docs/LibFuzzer.html |
35 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) |
36 | 10.3k | { |
37 | 10.3k | try |
38 | 10.3k | { |
39 | | // step 1: parse input |
40 | 10.3k | std::vector<uint8_t> const vec1(data, data + size); |
41 | 10.3k | json const j1 = json::from_bjdata(vec1); |
42 | | |
43 | 10.3k | try |
44 | 10.3k | { |
45 | | // step 2.1: round trip without adding size annotations to container types |
46 | 10.3k | std::vector<uint8_t> const vec2 = json::to_bjdata(j1, false, false); |
47 | | |
48 | | // step 2.2: round trip with adding size annotations but without adding type annotations to container types |
49 | 10.3k | std::vector<uint8_t> const vec3 = json::to_bjdata(j1, true, false); |
50 | | |
51 | | // step 2.3: round trip with adding size as well as type annotations to container types |
52 | 10.3k | std::vector<uint8_t> const vec4 = json::to_bjdata(j1, true, true); |
53 | | |
54 | | // parse serialization |
55 | 10.3k | json const j2 = json::from_bjdata(vec2); |
56 | 10.3k | json const j3 = json::from_bjdata(vec3); |
57 | 10.3k | json const j4 = json::from_bjdata(vec4); |
58 | | |
59 | | // serializations must match |
60 | 10.3k | assert(json::to_bjdata(j2, false, false) == vec2); |
61 | 10.3k | assert(json::to_bjdata(j3, true, false) == vec3); |
62 | 3.84k | assert(json::to_bjdata(j4, true, true) == vec4); |
63 | 3.84k | } |
64 | 10.3k | catch (const json::parse_error&) |
65 | 10.3k | { |
66 | | // parsing a BJData serialization must not fail |
67 | 0 | assert(false); |
68 | 0 | } |
69 | 10.3k | } |
70 | 10.3k | catch (const json::parse_error&) |
71 | 10.3k | { |
72 | | // parse errors are ok, because input may be random bytes |
73 | 5.91k | } |
74 | 10.3k | catch (const json::type_error&) |
75 | 10.3k | { |
76 | | // type errors can occur during parsing, too |
77 | 217 | } |
78 | 10.3k | catch (const json::out_of_range&) |
79 | 10.3k | { |
80 | | // out of range errors may happen if provided sizes are excessive |
81 | 353 | } |
82 | | |
83 | | // return 0 - non-zero return values are reserved for future use |
84 | 10.3k | return 0; |
85 | 10.3k | } |