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