• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*
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
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)35 extern "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