Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

direct parsing fuzzing test #1052

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/run_fuzzer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ jobs:
buildtype: 'boost'
path: 'head'
toolset: clang-18
cxxstd: 17
targets: libs/json/fuzzing//run
- name: Pack the corpus
working-directory: boost-root/libs/json/fuzzing/
Expand Down
1 change: 1 addition & 0 deletions fuzzing/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ corpus.tar
fuzzer_basic_parser
fuzzer_parse
fuzzer_parser
fuzzer_direct_parse
out*/
fuzz-*.log

4 changes: 4 additions & 0 deletions fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ source_group("" FILES
fuzz_basic_parser.cpp
fuzz_parse.cpp
fuzz_parser.cpp
fuzz_direct_parse.cpp
)

# The fuzzers are built as libraries, to make
Expand All @@ -33,3 +34,6 @@ add_library(fuzzerlib_parser fuzz_parser.cpp)
set_property(TARGET fuzzerlib_parser PROPERTY FOLDER "fuzzing")
target_link_libraries(fuzzerlib_parser PRIVATE Boost::json)

add_library(fuzzerlib_direct_parse fuzz_direct_parse.cpp)
set_property(TARGET fuzzerlib_direct_parse PROPERTY FOLDER "fuzzing")
target_link_libraries(fuzzerlib_direct_parse PRIVATE Boost::json)
4 changes: 2 additions & 2 deletions fuzzing/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ explicit old-corpus ;
local initial-corpus = [ glob-tree-ex ../test : *.json ] ;


local variants = basic_parser parse parser ;
for local variant in basic_parser parse parser
local variants = basic_parser parse parser direct_parse ;
for local variant in basic_parser parse parser direct_parse
{
local $(variant)-runs ;
local fuzzer = fuzzer_$(variant) ;
Expand Down
2 changes: 1 addition & 1 deletion fuzzing/fuzz.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ JOBS=
# set a timelimit (you may want to adjust this if you run locally)
MAXTIME="-max_total_time=30"

variants="basic_parser parse parser"
variants="basic_parser parse parser direct_parse"

for variant in $variants; do

Expand Down
84 changes: 84 additions & 0 deletions fuzzing/fuzz_direct_parse.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 2024 Mikhail Khachayants ([email protected])
//
// 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_into.hpp>
#include <boost/variant2/variant.hpp>
#include <boost/describe.hpp>
#include <map>

#ifndef BOOST_NO_CXX17_HDR_OPTIONAL
# include <optional>
# define IF_CXX17_HDR_OPTIONAL(...) __VA_ARGS__
#else
# define IF_CXX17_HDR_OPTIONAL(...)
#endif // BOOST_NO_CXX17_HDR_OPTIONAL

using namespace boost::json;

struct Object
{
bool b;
float f;
double d;
std::int64_t i64;
std::uint64_t u64;
std::string s;
std::vector<bool> v1;
std::vector<std::int64_t> v2;
std::vector<std::uint64_t> v3;
std::array<bool, 3> a1;
std::array<std::int64_t, 3> a2;
std::array<std::uint64_t, 3> a3;
std::map<std::string, std::int64_t> m1;
std::map<std::string, std::string> m2;
std::map<std::string, double> m3;
std::tuple<bool, std::uint64_t, std::int64_t, double, std::string> t1;
std::tuple<std::array<std::string, 3>, std::array<double, 3>, std::nullptr_t> t2;
std::tuple<std::vector<std::string>, std::vector<double>> t3;
boost::variant2::variant<bool, std::uint64_t, std::int64_t, double, std::string> v;

#ifndef BOOST_NO_CXX17_HDR_OPTIONAL
std::optional<bool> ob;
std::optional<std::int64_t> oi;
std::optional<std::uint64_t> ou;
std::optional<double> od;
std::optional<std::string> os;
#endif // BOOST_NO_CXX17_HDR_OPTIONAL
};

BOOST_DESCRIBE_STRUCT(Object, (),
(b, i64, u64, f, d, s, v1, v2, v3, a1, a2, a3, m1, m2, m3, t1, t2, t3, v,
IF_CXX17_HDR_OPTIONAL(ob, oi, ou, od, os)))


bool
fuzz_direct_parse(string_view sv)
{
Object object;
boost::system::error_code ec;
parse_into(object, sv, ec);
return !ec;
}

extern "C"
int
LLVMFuzzerTestOneInput(
const uint8_t* data, size_t size)
{
try
{
string_view sv{reinterpret_cast<
const char*>(data), size};
fuzz_direct_parse(sv);
}
catch(...)
{
}
return 0;
}

1 change: 1 addition & 0 deletions fuzzing/old_crashes/direct_parse/array.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"a2":[977,775500052916,9216,77552916,9216]}
1 change: 1 addition & 0 deletions fuzzing/old_crashes/direct_parse/tuple.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"t1":[]}
21 changes: 21 additions & 0 deletions fuzzing/old_crashes/direct_parse/valid_cxx14.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"b": true,
"i64": -123,
"u64": 123,
"f": 123.45,
"d": 0.9832747263462,
"s": "text",
"v1": [true, false],
"v2": [-12, 89],
"v3": [1000, 0],
"a1": [true, false, true],
"a2": [-1, 2, 3],
"a3": [1, 2, 3],
"m1": {"k": 42},
"m2": {"k": "v"},
"m3": {"k": 0.42},
"t1": [true, 1, 2, 1.23, "s"],
"t2": [["a", "b", "c"], [1.0, 0.1, 2.2], null],
"t3": [[], []],
"v": "text"
}
26 changes: 26 additions & 0 deletions fuzzing/old_crashes/direct_parse/valid_cxx17.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"b": true,
"i64": -123,
"u64": 123,
"f": 123.45,
"d": 0.9832747263462,
"s": "text",
"v1": [true, false],
"v2": [-12, 89],
"v3": [1000, 0],
"a1": [true, false, true],
"a2": [-1, 2, 3],
"a3": [1, 2, 3],
"m1": {"k": 42},
"m2": {"k": "v"},
"m3": {"k": 0.42},
"t1": [true, 1, 2, 1.23, "s"],
"t2": [["a", "b", "c"], [1.0, 0.1, 2.2], null],
"t3": [[], []],
"ob": null,
"oi": 123,
"ou": 456,
"od": 1.1,
"os": null,
"v": "text"
}
Loading