Coverage Report

Created: 2023-06-07 06:25

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