Coverage Report

Created: 2025-06-24 06:38

/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
15.7k
    void run(stream_parser& p) {
27
15.7k
        boost::system::error_code ec;
28
29
        // Write the first part of the buffer
30
15.7k
        p.write( jsontext, ec);
31
32
15.7k
        if(! ec)
33
10.4k
            p.finish( ec );
34
35
        // Take ownership of the resulting value.
36
15.7k
        if(! ec)
37
7.13k
        {
38
7.13k
            value jv = p.release();
39
7.13k
            res=serialize(jv).size()==42;
40
7.13k
        } else
41
8.61k
            res=false;
42
15.7k
    }
43
44
    // easy case - everything default
45
4.97k
    void useDefault() {
46
4.97k
        stream_parser p(storage_ptr{}, opt);
47
4.97k
        run(p);
48
4.97k
    }
49
50
4.07k
    void useMonotonic() {
51
4.07k
        monotonic_resource mr;
52
4.07k
        stream_parser p(storage_ptr{}, opt);
53
4.07k
        p.reset( &mr );
54
55
4.07k
        run(p);
56
4.07k
    }
57
58
3.67k
    void useLocalBuffer() {
59
3.67k
        std::unique_ptr<unsigned char[]> temp(new unsigned char[memlimit1]);
60
3.67k
        stream_parser p(
61
3.67k
                    storage_ptr(),
62
3.67k
                    opt,
63
3.67k
                    temp.get(),
64
3.67k
                    memlimit1);
65
3.67k
        run(p);
66
3.67k
    }
67
68
3.02k
    void useDynLess() {
69
        // this is on the heap because the size is chosen dynamically
70
3.02k
        std::unique_ptr<unsigned char[]> temp(new unsigned char[memlimit1]);
71
3.02k
        stream_parser p(get_null_resource(),
72
3.02k
                 opt,
73
3.02k
                 temp.get(),
74
3.02k
                 memlimit1);
75
76
        // this is on the heap because the size is chosen dynamically
77
3.02k
        std::unique_ptr<unsigned char[]> buf(new unsigned char[memlimit2]);
78
3.02k
        static_resource mr2( buf.get(), memlimit2 );
79
3.02k
        p.reset( &mr2 );
80
81
3.02k
        run(p);
82
3.02k
    }
83
84
};
85
86
87
extern "C"
88
int
89
LLVMFuzzerTestOneInput(
90
        const uint8_t* data, size_t size)
91
15.7k
{
92
15.7k
    if(size<=5)
93
4
        return 0;
94
95
15.7k
    FuzzHelper fh;
96
97
    // set parse options
98
15.7k
    fh.opt.allow_comments=!!(data[0]&0x1);
99
15.7k
    fh.opt.allow_trailing_commas=!!(data[0]&0x2);
100
15.7k
    fh.opt.allow_invalid_utf8=!!(data[0]&0x4);
101
15.7k
    fh.opt.max_depth= (data[0]>>3);
102
103
    // select memory strategy to use
104
15.7k
    const int strategy=data[1] & 0x3;
105
106
    // select number precision to use
107
15.7k
    const int precision=((data[1] & 0xC) >> 2) % 3;
108
15.7k
    fh.opt.numbers = static_cast<number_precision>(precision);
109
110
    // memory limits
111
15.7k
    fh.memlimit1=data[2]*256+data[3];
112
15.7k
    fh.memlimit2=data[4]*256+data[5];
113
114
15.7k
    data+=6;
115
15.7k
    size-=6;
116
117
    //set the json string to parse
118
15.7k
    fh.jsontext=string_view{
119
15.7k
            reinterpret_cast<const char*>(
120
15.7k
                data), size};
121
15.7k
    try
122
15.7k
    {
123
15.7k
        switch(strategy) {
124
4.97k
        case 0:
125
4.97k
            fh.useDefault();
126
4.97k
            break;
127
4.07k
        case 1:
128
4.07k
            fh.useMonotonic();
129
4.07k
            break;
130
3.67k
        case 2:
131
3.67k
            fh.useLocalBuffer();
132
3.67k
            break;
133
3.02k
        case 3:
134
3.02k
            fh.useDynLess();
135
3.02k
            break;
136
15.7k
        }
137
15.7k
    }
138
15.7k
    catch(...)
139
15.7k
    {
140
139
    }
141
15.7k
    return 0;
142
15.7k
}
143