/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 | } |