Coverage Report

Created: 2025-10-25 06:36

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