Coverage Report

Created: 2026-02-14 07:22

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
6.02k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
39
    // Initialise logging
40
6.02k
    setenv("KEA_LOGGER_DESTINATION", "/dev/null", 0);
41
6.02k
    setenv("KEA_LOCKFILE_DIR", "/tmp", 0);
42
6.02k
    setenv("KEA_PIDFILE_DIR", "/tmp", 0);
43
6.02k
    setenv("KEA_LFC_EXECUTABLE", "/bin/true", 0);
44
6.02k
    try {
45
6.02k
        isc::log::initLogger("fuzzer");
46
6.02k
        isc::process::Daemon::loggerInit("fuzzer", false);
47
6.02k
        isc::process::Daemon::setDefaultLoggerName("fuzzer");
48
6.02k
    } catch (...) {
49
        // Early exit if logging initialisation failed
50
0
        return 0;
51
0
    }
52
53
6.02k
    FuzzedDataProvider fdp(data, size);
54
6.02k
    pgmock_load_bytes(data, size);
55
56
6.02k
    DbCallback db_cb;
57
6.02k
    size_t index = 0;
58
59
    // Prepare tags
60
6.02k
    std::set<std::string> tags;
61
6.02k
    std::string tag = fdp.ConsumeRandomLengthString(16);
62
6.02k
    if (tag.size() == 0) {
63
5.24k
        tag = "default-tag";
64
5.24k
    }
65
6.02k
    tags.insert(tag);
66
67
    // Preparer DatabaseConnection parameter map
68
6.02k
    DatabaseConnection::ParameterMap params;
69
6.02k
    params["name"] = fdp.ConsumeRandomLengthString(32);
70
6.02k
    params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32);
71
6.02k
    params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32);
72
6.02k
    params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32);
73
74
    // Prepare Binding array
75
6.02k
    PsqlBindArray binds;
76
6.02k
    binds.add(fdp.ConsumeRandomLengthString(256));
77
6.02k
    binds.add(fdp.ConsumeRandomLengthString(256));
78
6.02k
    binds.add(fdp.ConsumeRandomLengthString(256));
79
80
    // Prepare server selector
81
6.02k
    ServerSelector selector = ServerSelector::UNASSIGNED();
82
6.02k
    try {
83
6.02k
        switch (fdp.ConsumeIntegralInRange<int>(0, 3)) {
84
5.35k
            case 0:
85
5.35k
                selector = ServerSelector::ALL();
86
5.35k
                break;
87
226
            case 1:
88
226
                selector = ServerSelector::ONE(tag);
89
226
                break;
90
313
            case 2:
91
313
                selector = ServerSelector::MULTIPLE(tags);
92
313
                break;
93
134
            case 3:
94
134
                selector = ServerSelector::ANY();
95
134
                break;
96
6.02k
        }
97
6.02k
    } catch (const isc::Exception&) {
98
        // Slient exceptions use default unassigned server selector
99
26
    }
100
101
6.02k
    try {
102
        // Prepare PgSql backend
103
6.02k
        PgSqlConfigBackendImpl backend(fdp.ConsumeRandomLengthString(32), params, db_cb, index);
104
6.02k
        PgSqlConfigBackendDHCPv4 dhcp_backend(params);
105
106
        // Target selectQuery
107
6.02k
        try {
108
6.02k
            backend.selectQuery(0, binds, PgSqlConnection::ConsumeResultRowFun([](PgSqlResult&, int) {}));
109
6.02k
        } catch (const isc::Exception&) {
110
            // Slient exceptions
111
2.30k
        }
112
113
        // Target insertQuery
114
6.02k
        try {
115
2.30k
            backend.insertQuery(0, binds);
116
2.30k
        } catch (const isc::Exception&) {
117
            // Slient exceptions
118
2.30k
        }
119
120
        // Target updateDeleteQuery
121
2.30k
        try {
122
2.30k
            backend.updateDeleteQuery(0, binds);
123
2.30k
        } catch (const isc::Exception&) {
124
            // Slient exceptions
125
2.30k
        }
126
127
        // Target upper level getGlobalParameter4
128
2.30k
        try {
129
2.30k
            dhcp_backend.getGlobalParameter4(selector, fdp.ConsumeRandomLengthString(32));
130
2.30k
        } catch (const isc::Exception&) {
131
            // Slient exceptions
132
2.09k
        }
133
134
        // Target upper level getAllSubnets4
135
2.30k
        try {
136
2.30k
            dhcp_backend.getAllSubnets4(selector);
137
2.30k
        } catch (const isc::Exception&) {
138
            // Slient exceptions
139
2.30k
        }
140
141
        // Target upper level createUpdateSubnet4
142
2.30k
        try {
143
2.30k
            IOAddress address(fdp.ConsumeRandomLengthString(15));
144
2.30k
            uint32_t a1 = fdp.ConsumeIntegral<uint32_t>();
145
2.30k
            uint32_t b1 = fdp.ConsumeIntegral<uint32_t>();
146
2.30k
            uint32_t c1 = fdp.ConsumeIntegral<uint32_t>();
147
2.30k
            Triplet<uint32_t> t1(a1, b1, c1);
148
149
2.30k
            uint32_t a2 = fdp.ConsumeIntegral<uint32_t>();
150
2.30k
            uint32_t b2 = fdp.ConsumeIntegral<uint32_t>();
151
2.30k
            uint32_t c2 = fdp.ConsumeIntegral<uint32_t>();
152
2.30k
            Triplet<uint32_t> t2(a2, b2, c2);
153
154
2.30k
            uint32_t a3 = fdp.ConsumeIntegral<uint32_t>();
155
2.30k
            uint32_t b3 = fdp.ConsumeIntegral<uint32_t>();
156
2.30k
            uint32_t c3 = fdp.ConsumeIntegral<uint32_t>();
157
2.30k
            Triplet<uint32_t> t3(a3, b3, c3);
158
159
2.30k
            SubnetID sid = static_cast<SubnetID>(fdp.ConsumeIntegral<uint32_t>());
160
161
2.30k
            Subnet4Ptr subnet(Subnet4::create(address, fdp.ConsumeIntegralInRange(0, 32), t1, t2, t3, sid));
162
2.30k
            dhcp_backend.createUpdateSubnet4(selector, subnet);
163
2.30k
        } catch (const isc::Exception&) {
164
            // Slient exceptions
165
2.30k
        }
166
167
        // Target upper level deleteSubnet4
168
2.30k
        try {
169
2.30k
            dhcp_backend.deleteSubnet4(selector, fdp.ConsumeRandomLengthString(32));
170
2.30k
        } catch (const isc::Exception&) {
171
            // Slient exceptions
172
1.89k
        }
173
174
        // Target upper level createUpdateOption4
175
2.30k
        try {
176
2.30k
            OptionBuffer opt_buf;
177
2.30k
            OptionPtr opt(new Option(Option::V4, 0, opt_buf));
178
2.30k
            OptionDescriptorPtr opt_desc(new OptionDescriptor(opt, true, true));
179
180
2.30k
            std::string opt_space = "dhcp4";
181
2.30k
            std::string opt_name  = fdp.ConsumeRandomLengthString(32);
182
2.30k
            if (opt_name.empty()) {
183
1.36k
                opt_name = "fuzz-opt";
184
1.36k
            }
185
186
2.30k
            dhcp_backend.createUpdateOption4(selector, opt_name, opt_desc);
187
2.30k
        } catch (const isc::Exception&) {
188
            // Slient exceptions
189
186
        }
190
3.72k
    } catch (const isc::Exception& e) {
191
        // Slient exceptions
192
3.72k
    }
193
194
6.02k
    return 0;
195
6.02k
}