Coverage Report

Created: 2026-03-31 07:26

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