Coverage Report

Created: 2025-11-16 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kea-fuzzer/fuzz_pgsql4.cc
Line
Count
Source
1
// Copyright (C) 2025 Ada Logcis Ltd.
2
//
3
// This Source Code Form is subject to the terms of the Mozilla Public
4
// License, v. 2.0. If a copy of the MPL was not distributed with this
5
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
////////////////////////////////////////////////////////////////////////////////
7
#include <config.h>
8
#include <fuzzer/FuzzedDataProvider.h>
9
10
#include <asiolink/io_address.h>
11
#include <database/database_connection.h>
12
#include <database/server_selector.h>
13
#include <dhcp/pgsql/pgsql_cb_impl.h>
14
#include <dhcp/pgsql/pgsql_cb_dhcp4.h>
15
#include <dhcpsrv/subnet.h>
16
#include <dhcpsrv/host.h>
17
#include <pgsql/pgsql_exchange.h>
18
19
#include <log/logger_support.h>
20
#include <process/daemon.h>
21
#include <exceptions/exceptions.h>
22
23
#include <cstdint>
24
#include <cstddef>
25
#include <string>
26
#include <vector>
27
#include <map>
28
#include <utility>
29
#include <iostream>
30
31
using namespace isc::asiolink;
32
using namespace isc::db;
33
using namespace isc::dhcp;
34
using namespace isc::util;
35
36
extern "C" void pgmock_load_bytes(const uint8_t* data, size_t size);
37
38
5.21k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
39
    // Initialise logging
40
5.21k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
41
5.21k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
42
5.21k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
43
5.21k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
44
5.21k
    try {
45
5.21k
        isc::log::initLogger("fuzzer");
46
5.21k
        isc::process::Daemon::loggerInit("fuzzer", false);
47
5.21k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
48
5.21k
    } catch (...) {
49
        // Early exit if logging initialisation failed
50
0
        return 0;
51
0
    }
52
53
5.21k
    FuzzedDataProvider fdp(data, size);
54
5.21k
    pgmock_load_bytes(data, size);
55
56
5.21k
    DbCallback db_cb;
57
5.21k
    size_t index = 0;
58
59
    // Prepare tags
60
5.21k
    std::set<std::string> tags;
61
5.21k
    std::string tag = fdp.ConsumeRandomLengthString(16);
62
5.21k
    if (tag.size() == 0) {
63
3.02k
        tag = "default-tag";
64
3.02k
    }
65
5.21k
    tags.insert(tag);
66
67
    // Preparer DatabaseConnection parameter map
68
5.21k
    DatabaseConnection::ParameterMap params;
69
5.21k
    params["name"] = fdp.ConsumeRandomLengthString(32);
70
5.21k
    params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32);
71
5.21k
    params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32);
72
5.21k
    params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32);
73
74
    // Prepare Binding array
75
5.21k
    PsqlBindArray binds;
76
5.21k
    binds.add(fdp.ConsumeRandomLengthString(256));
77
5.21k
    binds.add(fdp.ConsumeRandomLengthString(256));
78
5.21k
    binds.add(fdp.ConsumeRandomLengthString(256));
79
80
    // Prepare server selector
81
5.21k
    ServerSelector selector = ServerSelector::UNASSIGNED();
82
5.21k
    try {
83
5.21k
        switch (fdp.ConsumeIntegralInRange<int>(0, 3)) {
84
2.86k
            case 0:
85
2.86k
                selector = ServerSelector::ALL();
86
2.86k
                break;
87
1.30k
            case 1:
88
1.30k
                selector = ServerSelector::ONE(tag);
89
1.30k
                break;
90
328
            case 2:
91
328
                selector = ServerSelector::MULTIPLE(tags);
92
328
                break;
93
726
            case 3:
94
726
                selector = ServerSelector::ANY();
95
726
                break;
96
5.21k
        }
97
5.21k
    } catch (const isc::Exception&) {
98
        // Slient exceptions use default unassigned server selector
99
59
    }
100
101
5.21k
    try {
102
        // Prepare PgSql backend
103
5.21k
        PgSqlConfigBackendImpl backend(fdp.ConsumeRandomLengthString(32), params, db_cb, index);
104
5.21k
        PgSqlConfigBackendDHCPv4 dhcp_backend(params);
105
106
        // Target selectQuery
107
5.21k
        try {
108
5.21k
            backend.selectQuery(0, binds, PgSqlConnection::ConsumeResultRowFun([](PgSqlResult&, int) {}));
109
5.21k
        } catch (const isc::Exception&) {
110
            // Slient exceptions
111
2.65k
        }
112
113
        // Target insertQuery
114
5.21k
        try {
115
2.65k
            backend.insertQuery(0, binds);
116
2.65k
        } catch (const isc::Exception&) {
117
            // Slient exceptions
118
2.65k
        }
119
120
        // Target updateDeleteQuery
121
2.65k
        try {
122
2.65k
            backend.updateDeleteQuery(0, binds);
123
2.65k
        } catch (const isc::Exception&) {
124
            // Slient exceptions
125
2.65k
        }
126
127
        // Target upper level getGlobalParameter4
128
2.65k
        try {
129
2.65k
            dhcp_backend.getGlobalParameter4(selector, fdp.ConsumeRandomLengthString(32));
130
2.65k
        } catch (const isc::Exception&) {
131
            // Slient exceptions
132
1.82k
        }
133
134
        // Target upper level getAllSubnets4
135
2.65k
        try {
136
2.65k
            dhcp_backend.getAllSubnets4(selector);
137
2.65k
        } catch (const isc::Exception&) {
138
            // Slient exceptions
139
2.65k
        }
140
141
        // Target upper level createUpdateSubnet4
142
2.65k
        try {
143
2.65k
            IOAddress address(fdp.ConsumeRandomLengthString(15));
144
2.65k
            uint32_t a1 = fdp.ConsumeIntegral<uint32_t>();
145
2.65k
            uint32_t b1 = fdp.ConsumeIntegral<uint32_t>();
146
2.65k
            uint32_t c1 = fdp.ConsumeIntegral<uint32_t>();
147
2.65k
            Triplet<uint32_t> t1(a1, b1, c1);
148
149
2.65k
            uint32_t a2 = fdp.ConsumeIntegral<uint32_t>();
150
2.65k
            uint32_t b2 = fdp.ConsumeIntegral<uint32_t>();
151
2.65k
            uint32_t c2 = fdp.ConsumeIntegral<uint32_t>();
152
2.65k
            Triplet<uint32_t> t2(a2, b2, c2);
153
154
2.65k
            uint32_t a3 = fdp.ConsumeIntegral<uint32_t>();
155
2.65k
            uint32_t b3 = fdp.ConsumeIntegral<uint32_t>();
156
2.65k
            uint32_t c3 = fdp.ConsumeIntegral<uint32_t>();
157
2.65k
            Triplet<uint32_t> t3(a3, b3, c3);
158
159
2.65k
            SubnetID sid = static_cast<SubnetID>(fdp.ConsumeIntegral<uint32_t>());
160
161
2.65k
            Subnet4Ptr subnet(Subnet4::create(address, fdp.ConsumeIntegralInRange(0, 32), t1, t2, t3, sid));
162
2.65k
            dhcp_backend.createUpdateSubnet4(selector, subnet);
163
2.65k
        } catch (const isc::Exception&) {
164
            // Slient exceptions
165
2.65k
        }
166
167
        // Target upper level deleteSubnet4
168
2.65k
        try {
169
2.65k
            dhcp_backend.deleteSubnet4(selector, fdp.ConsumeRandomLengthString(32));
170
2.65k
        } catch (const isc::Exception&) {
171
            // Slient exceptions
172
2.37k
        }
173
174
        // Target upper level createUpdateOption4
175
2.65k
        try {
176
2.65k
            OptionBuffer opt_buf;
177
2.65k
            OptionPtr opt(new Option(Option::V4, 0, opt_buf));
178
2.65k
            OptionDescriptorPtr opt_desc(new OptionDescriptor(opt, true, true));
179
180
2.65k
            std::string opt_space = "dhcp4";
181
2.65k
            std::string opt_name  = fdp.ConsumeRandomLengthString(32);
182
2.65k
            if (opt_name.empty()) {
183
1.56k
                opt_name = "fuzz-opt";
184
1.56k
            }
185
186
2.65k
            dhcp_backend.createUpdateOption4(selector, opt_name, opt_desc);
187
2.65k
        } catch (const isc::Exception&) {
188
            // Slient exceptions
189
217
        }
190
2.65k
    } catch (const isc::Exception& e) {
191
        // Slient exceptions
192
2.56k
    }
193
194
5.21k
    return 0;
195
5.21k
}