/src/kea-fuzzer/fuzz_pgsql6.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_dhcp6.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[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32); |
70 | 5.21k | params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32); |
71 | 5.21k | params[fdp.ConsumeRandomLengthString(32)] = fdp.ConsumeRandomLengthString(32); |
72 | | |
73 | | // Prepare Binding array |
74 | 5.21k | PsqlBindArray binds; |
75 | 5.21k | binds.add(fdp.ConsumeRandomLengthString(256)); |
76 | 5.21k | binds.add(fdp.ConsumeRandomLengthString(256)); |
77 | 5.21k | binds.add(fdp.ConsumeRandomLengthString(256)); |
78 | | |
79 | | // Prepare server selector |
80 | 5.21k | ServerSelector selector = ServerSelector::UNASSIGNED(); |
81 | 5.21k | try { |
82 | 5.21k | switch (fdp.ConsumeIntegralInRange<int>(0, 3)) { |
83 | 2.86k | case 0: |
84 | 2.86k | selector = ServerSelector::ALL(); |
85 | 2.86k | break; |
86 | 1.30k | case 1: |
87 | 1.30k | selector = ServerSelector::ONE(tag); |
88 | 1.30k | break; |
89 | 328 | case 2: |
90 | 328 | selector = ServerSelector::MULTIPLE(tags); |
91 | 328 | break; |
92 | 726 | case 3: |
93 | 726 | selector = ServerSelector::ANY(); |
94 | 726 | break; |
95 | 5.21k | } |
96 | 5.21k | } catch (const isc::Exception&) { |
97 | | // Slient exceptions use default unassigned server selector |
98 | 59 | } |
99 | | |
100 | 5.21k | try { |
101 | | // Prepare PgSql backend |
102 | 5.21k | PgSqlConfigBackendImpl backend(fdp.ConsumeRandomLengthString(32), params, db_cb, index); |
103 | 5.21k | PgSqlConfigBackendDHCPv6 dhcp_backend(params); |
104 | | |
105 | | // Target selectQuery |
106 | 5.21k | try { |
107 | 5.21k | backend.selectQuery(0, binds, PgSqlConnection::ConsumeResultRowFun([](PgSqlResult&, int) {})); |
108 | 5.21k | } catch (const isc::Exception&) { |
109 | | // Slient exceptions |
110 | 2.65k | } |
111 | | |
112 | | // Target insertQuery |
113 | 5.21k | try { |
114 | 2.65k | backend.insertQuery(0, binds); |
115 | 2.65k | } catch (const isc::Exception&) { |
116 | | // Slient exceptions |
117 | 2.65k | } |
118 | | |
119 | | // Target updateDeleteQuery |
120 | 2.65k | try { |
121 | 2.65k | backend.updateDeleteQuery(0, binds); |
122 | 2.65k | } catch (const isc::Exception&) { |
123 | | // Slient exceptions |
124 | 2.65k | } |
125 | | |
126 | | // Target upper level getGlobalParameter6 |
127 | 2.65k | try { |
128 | 2.65k | dhcp_backend.getGlobalParameter6(selector, fdp.ConsumeRandomLengthString(32)); |
129 | 2.65k | } catch (const isc::Exception&) { |
130 | | // Slient exceptions |
131 | 1.82k | } |
132 | | |
133 | | // Target upper level getAllSubnets6 |
134 | 2.65k | try { |
135 | 2.65k | dhcp_backend.getAllSubnets6(selector); |
136 | 2.65k | } catch (const isc::Exception&) { |
137 | | // Slient exceptions |
138 | 2.65k | } |
139 | | |
140 | | // Target upper level createUpdateSubnet6 |
141 | 2.65k | try { |
142 | 2.65k | IOAddress address(fdp.ConsumeRandomLengthString(64)); |
143 | 2.65k | uint32_t a1 = fdp.ConsumeIntegral<uint32_t>(); |
144 | 2.65k | uint32_t b1 = fdp.ConsumeIntegral<uint32_t>(); |
145 | 2.65k | uint32_t c1 = fdp.ConsumeIntegral<uint32_t>(); |
146 | 2.65k | Triplet<uint32_t> t1(a1, b1, c1); |
147 | | |
148 | 2.65k | uint32_t a2 = fdp.ConsumeIntegral<uint32_t>(); |
149 | 2.65k | uint32_t b2 = fdp.ConsumeIntegral<uint32_t>(); |
150 | 2.65k | uint32_t c2 = fdp.ConsumeIntegral<uint32_t>(); |
151 | 2.65k | Triplet<uint32_t> t2(a2, b2, c2); |
152 | | |
153 | 2.65k | uint32_t a3 = fdp.ConsumeIntegral<uint32_t>(); |
154 | 2.65k | uint32_t b3 = fdp.ConsumeIntegral<uint32_t>(); |
155 | 2.65k | uint32_t c3 = fdp.ConsumeIntegral<uint32_t>(); |
156 | 2.65k | Triplet<uint32_t> t3(a3, b3, c3); |
157 | | |
158 | 2.65k | uint32_t a4 = fdp.ConsumeIntegral<uint32_t>(); |
159 | 2.65k | uint32_t b4 = fdp.ConsumeIntegral<uint32_t>(); |
160 | 2.65k | uint32_t c4 = fdp.ConsumeIntegral<uint32_t>(); |
161 | 2.65k | Triplet<uint32_t> t4(a4, b4, c4); |
162 | | |
163 | 2.65k | SubnetID sid = static_cast<SubnetID>(fdp.ConsumeIntegral<uint32_t>()); |
164 | | |
165 | 2.65k | Subnet6Ptr subnet(Subnet6::create(address, fdp.ConsumeIntegralInRange(0, 128), t1, t2, t3, t4, sid)); |
166 | 2.65k | dhcp_backend.createUpdateSubnet6(selector, subnet); |
167 | 2.65k | } catch (const isc::Exception&) { |
168 | | // Slient exceptions |
169 | 2.65k | } |
170 | | |
171 | | // Target upper level deleteSubnet6 |
172 | 2.65k | try { |
173 | 2.65k | dhcp_backend.deleteSubnet6(selector, fdp.ConsumeRandomLengthString(32)); |
174 | 2.65k | } catch (const isc::Exception&) { |
175 | | // Slient exceptions |
176 | 2.37k | } |
177 | | |
178 | | // Target upper level createUpdateOption6 |
179 | 2.65k | try { |
180 | 2.65k | OptionBuffer opt_buf; |
181 | 2.65k | OptionPtr opt(new Option(Option::V6, 0, opt_buf)); |
182 | 2.65k | OptionDescriptorPtr opt_desc(new OptionDescriptor(opt, true, true)); |
183 | | |
184 | 2.65k | std::string opt_space = "dhcp4"; |
185 | 2.65k | std::string opt_name = fdp.ConsumeRandomLengthString(32); |
186 | 2.65k | if (opt_name.empty()) { |
187 | 1.56k | opt_name = "fuzz-opt"; |
188 | 1.56k | } |
189 | | |
190 | 2.65k | dhcp_backend.createUpdateOption6(selector, opt_name, opt_desc); |
191 | 2.65k | } catch (const isc::Exception&) { |
192 | | // Slient exceptions |
193 | 217 | } |
194 | 2.65k | } catch (const isc::Exception&) { |
195 | | // Slient exceptions |
196 | 2.56k | } |
197 | | |
198 | 5.21k | return 0; |
199 | 5.21k | } |