1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2020 Paul Dreik (github@pauldreik.se)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/json
//
#include <boost/json/parse_options.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/stream_parser.hpp>
#include <boost/json/monotonic_resource.hpp>
#include <boost/json/null_resource.hpp>
#include <boost/json/static_resource.hpp>
#include <memory>
using namespace boost::json;
struct FuzzHelper {
parse_options opt;
string_view jsontext;
std::size_t memlimit1;
std::size_t memlimit2;
bool res;
void run(stream_parser& p) {
boost::system::error_code ec;
// Write the first part of the buffer
p.write( jsontext, ec);
if(! ec)
p.finish( ec );
// Take ownership of the resulting value.
if(! ec)
{
value jv = p.release();
res=serialize(jv).size()==42;
} else
res=false;
}
// easy case - everything default
void useDefault() {
stream_parser p(storage_ptr{}, opt);
run(p);
}
void useMonotonic() {
monotonic_resource mr;
stream_parser p(storage_ptr{}, opt);
p.reset( &mr );
run(p);
}
void useLocalBuffer() {
std::unique_ptr<unsigned char[]> temp(new unsigned char[memlimit1]);
stream_parser p(
storage_ptr(),
opt,
temp.get(),
memlimit1);
run(p);
}
void useDynLess() {
// this is on the heap because the size is chosen dynamically
std::unique_ptr<unsigned char[]> temp(new unsigned char[memlimit1]);
stream_parser p(get_null_resource(),
opt,
temp.get(),
memlimit1);
// this is on the heap because the size is chosen dynamically
std::unique_ptr<unsigned char[]> buf(new unsigned char[memlimit2]);
static_resource mr2( buf.get(), memlimit2 );
p.reset( &mr2 );
run(p);
}
};
extern "C"
int
LLVMFuzzerTestOneInput(
const uint8_t* data, size_t size)
{
if(size<=5)
return 0;
FuzzHelper fh;
// set parse options
fh.opt.allow_comments=!!(data[0]&0x1);
fh.opt.allow_trailing_commas=!!(data[0]&0x2);
fh.opt.allow_invalid_utf8=!!(data[0]&0x4);
fh.opt.max_depth= (data[0]>>3);
// select memory strategy to use
const int strategy=data[1] & 0x3;
// select number precision to use
const int precision=((data[1] & 0xC) >> 2) % 3;
fh.opt.numbers = static_cast<number_precision>(precision);
// memory limits
fh.memlimit1=data[2]*256+data[3];
fh.memlimit2=data[4]*256+data[5];
data+=6;
size-=6;
//set the json string to parse
fh.jsontext=string_view{
reinterpret_cast<const char*>(
data), size};
try
{
switch(strategy) {
case 0:
fh.useDefault();
break;
case 1:
fh.useMonotonic();
break;
case 2:
fh.useLocalBuffer();
break;
case 3:
fh.useDynLess();
break;
}
}
catch(...)
{
}
return 0;
}
|