Coverage Report

Created: 2025-06-13 06:26

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