boost/libs/json/fuzzing/fuzz_parser.cpp
2021-10-05 21:37:46 +02:00

140 lines
3.2 KiB
C++

// 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) {
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;
// 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.useDefault();
break;
case 2:
fh.useLocalBuffer();
break;
case 3:
fh.useDynLess();
break;
}
}
catch(...)
{
}
return 0;
}