File: fuzz_parser.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (143 lines) | stat: -rw-r--r-- 3,463 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2020 Paul Dreik (github@pauldreik.se)
//
// 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_options.hpp>
#include <boost/json/serialize.hpp>
#include <boost/json/stream_parser.hpp>
#include <boost/json/monotonic_resource.hpp>
#include <boost/json/null_resource.hpp>
#include <boost/json/static_resource.hpp>
#include <memory>

using namespace boost::json;

struct FuzzHelper {
    parse_options opt;
    string_view jsontext;
    std::size_t memlimit1;
    std::size_t memlimit2;
    bool res;
    void run(stream_parser& p) {
        boost::system::error_code ec;

        // Write the first part of the buffer
        p.write( jsontext, ec);

        if(! ec)
            p.finish( ec );

        // Take ownership of the resulting value.
        if(! ec)
        {
            value jv = p.release();
            res=serialize(jv).size()==42;
        } else
            res=false;
    }

    // easy case - everything default
    void useDefault() {
        stream_parser p(storage_ptr{}, opt);
        run(p);
    }

    void useMonotonic() {
        monotonic_resource mr;
        stream_parser p(storage_ptr{}, opt);
        p.reset( &mr );

        run(p);
    }

    void useLocalBuffer() {
        std::unique_ptr<unsigned char[]> temp(new unsigned char[memlimit1]);
        stream_parser p(
                    storage_ptr(),
                    opt,
                    temp.get(),
                    memlimit1);
        run(p);
    }

    void useDynLess() {
        // this is on the heap because the size is chosen dynamically
        std::unique_ptr<unsigned char[]> temp(new unsigned char[memlimit1]);
        stream_parser p(get_null_resource(),
                 opt,
                 temp.get(),
                 memlimit1);

        // this is on the heap because the size is chosen dynamically
        std::unique_ptr<unsigned char[]> buf(new unsigned char[memlimit2]);
        static_resource mr2( buf.get(), memlimit2 );
        p.reset( &mr2 );

        run(p);
    }

};


extern "C"
int
LLVMFuzzerTestOneInput(
        const uint8_t* data, size_t size)
{
    if(size<=5)
        return 0;

    FuzzHelper fh;

    // set parse options
    fh.opt.allow_comments=!!(data[0]&0x1);
    fh.opt.allow_trailing_commas=!!(data[0]&0x2);
    fh.opt.allow_invalid_utf8=!!(data[0]&0x4);
    fh.opt.max_depth= (data[0]>>3);

    // select memory strategy to use
    const int strategy=data[1] & 0x3;

    // select number precision to use
    const int precision=((data[1] & 0xC) >> 2) % 3;
    fh.opt.numbers = static_cast<number_precision>(precision);

    // memory limits
    fh.memlimit1=data[2]*256+data[3];
    fh.memlimit2=data[4]*256+data[5];

    data+=6;
    size-=6;

    //set the json string to parse
    fh.jsontext=string_view{
            reinterpret_cast<const char*>(
                data), size};
    try
    {
        switch(strategy) {
        case 0:
            fh.useDefault();
            break;
        case 1:
            fh.useMonotonic();
            break;
        case 2:
            fh.useLocalBuffer();
            break;
        case 3:
            fh.useDynLess();
            break;
        }
    }
    catch(...)
    {
    }
    return 0;
}