1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <cstdint>
16 #include <string>
17 #include <vector>
18 #include <chrono>
19 #include <cstring>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <linux/if_packet.h>
24 #include <poll.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <algorithm>
28 #include <regex>
29 #include <malloc.h>
30 #include <arpa/inet.h>
31 #include <netinet/if_ether.h>
32 #include <sys/ioctl.h>
33 #include <net/if_arp.h>
34
35 #include "securec.h"
36 #include "dhcp_logger.h"
37 #include "dhcp_common_utils.h"
38 #include "dhcp_fuzz_common_func.h"
39 using namespace std;
40 namespace OHOS {
41 namespace DHCP {
42 constexpr size_t U32_AT_SIZE_ZERO = 4;
43 constexpr size_t INDEX = 4;
44 constexpr size_t SIZEOFHOST = 5;
TestIpv6Anonymize(const uint8_t * data,size_t size)45 void TestIpv6Anonymize(const uint8_t* data, size_t size)
46 {
47 if (data == nullptr || size < U32_AT_SIZE_ZERO) {
48 return;
49 }
50 size_t pos = 0;
51 uint32_t strLen = U32_AT(data);
52 pos += sizeof(uint32_t);
53 if (pos + strLen > size) {
54 return;
55 }
56 string str(reinterpret_cast<const char*>(data + pos), strLen);
57
58 Ipv6Anonymize(str);
59 }
60
TestIpv4Anonymize(const uint8_t * data,size_t size)61 void TestIpv4Anonymize(const uint8_t* data, size_t size)
62 {
63 if (data == nullptr || size < U32_AT_SIZE_ZERO) {
64 return;
65 }
66 size_t pos = 0;
67 uint32_t strLen = U32_AT(data);
68 pos += sizeof(uint32_t);
69 if (pos + strLen > size) {
70 return;
71 }
72 string str(reinterpret_cast<const char*>(data + pos), strLen);
73
74 Ipv4Anonymize(str);
75 }
76
TestUintIp4ToStr(const uint8_t * data,size_t size)77 void TestUintIp4ToStr(const uint8_t* data, size_t size)
78 {
79 if (data == nullptr || size < U32_AT_SIZE_ZERO) {
80 return;
81 }
82 uint32_t uIp = U32_AT(data);
83 // Check if the size is sufficient for the host flag
84 // If size is less than 5, we assume the host flag is false
85 bool bHost = (size >= SIZEOFHOST) ? (data[INDEX] != 0) : false;
86
87 UintIp4ToStr(uIp, bHost);
88 }
89
TestIntIpv4ToAnonymizeStr(const uint8_t * data,size_t size)90 void TestIntIpv4ToAnonymizeStr(const uint8_t* data, size_t size)
91 {
92 if (data == nullptr || size < U32_AT_SIZE_ZERO) {
93 return;
94 }
95 uint32_t ip = U32_AT(data);
96
97 IntIpv4ToAnonymizeStr(ip);
98 }
99
TestMacArray2Str(const uint8_t * data,size_t size)100 void TestMacArray2Str(const uint8_t* data, size_t size)
101 {
102 if (data == nullptr || size < U32_AT_SIZE_ZERO) {
103 return;
104 }
105 size_t pos = 0;
106 uint32_t macArrayLen = U32_AT(data);
107 pos += sizeof(uint32_t);
108 if (pos + macArrayLen > size) {
109 return;
110 }
111 uint8_t macArray[ETH_ALEN];
112 if (macArrayLen > 0) {
113 if (memcpy_s(macArray, ETH_ALEN, data + pos, macArrayLen) != 0) {
114 return;
115 }
116 }
117 int32_t len = static_cast<int32_t>(macArrayLen);
118 MacArray2Str(macArray, len);
119 }
120
TestCheckDataLegal(const uint8_t * data,size_t size)121 void TestCheckDataLegal(const uint8_t* data, size_t size)
122 {
123 if (size < U32_AT_SIZE_ZERO) {
124 return;
125 }
126 size_t pos = 0;
127 uint32_t dataLen = U32_AT(data);
128 pos += sizeof(uint32_t);
129 if (pos + dataLen > size) {
130 return;
131 }
132 string dataStr(reinterpret_cast<const char*>(data + pos), dataLen);
133 pos += dataLen;
134 int base = (size >= pos + U32_AT_SIZE_ZERO) ? static_cast<int>(U32_AT(data + pos)) : DECIMAL_NOTATION;
135
136 CheckDataLegal(dataStr, base);
137 }
138
TestCheckDataToUint(const uint8_t * data,size_t size)139 void TestCheckDataToUint(const uint8_t* data, size_t size)
140 {
141 if (size < U32_AT_SIZE_ZERO) {
142 return;
143 }
144 size_t pos = 0;
145 uint32_t dataLen = U32_AT(data);
146 pos += sizeof(uint32_t);
147 if (pos + dataLen > size) {
148 return;
149 }
150 string dataStr(reinterpret_cast<const char*>(data + pos), dataLen);
151 pos += dataLen;
152 int base = (size >= pos + U32_AT_SIZE_ZERO) ? static_cast<int>(U32_AT(data + pos)) : DECIMAL_NOTATION;
153
154 CheckDataToUint(dataStr, base);
155 }
156
TestCheckDataTolonglong(const uint8_t * data,size_t size)157 void TestCheckDataTolonglong(const uint8_t* data, size_t size)
158 {
159 if (size < U32_AT_SIZE_ZERO) {
160 return;
161 }
162 size_t pos = 0;
163 uint32_t dataLen = U32_AT(data);
164 pos += sizeof(uint32_t);
165 if (pos + dataLen > size) {
166 return;
167 }
168 string dataStr(reinterpret_cast<const char*>(data + pos), dataLen);
169 pos += dataLen;
170 int base = (size >= pos + U32_AT_SIZE_ZERO) ? static_cast<int>(U32_AT(data + pos)) : DECIMAL_NOTATION;
171
172 CheckDataTolonglong(dataStr, base);
173 }
174
TestCheckDataToUint64(const uint8_t * data,size_t size)175 void TestCheckDataToUint64(const uint8_t* data, size_t size)
176 {
177 if (size < U32_AT_SIZE_ZERO) {
178 return;
179 }
180 size_t pos = 0;
181 uint32_t dataLen = U32_AT(data);
182 pos += sizeof(uint32_t);
183 if (pos + dataLen > size) {
184 return;
185 }
186 string dataStr(reinterpret_cast<const char*>(data + pos), dataLen);
187 pos += dataLen;
188 int base = (size >= pos + U32_AT_SIZE_ZERO) ? static_cast<int>(U32_AT(data + pos)) : DECIMAL_NOTATION;
189
190 CheckDataToUint64(dataStr, base);
191 }
192
TestGetElapsedSecondsSinceBoot(const uint8_t * data,size_t size)193 void TestGetElapsedSecondsSinceBoot(const uint8_t* data, size_t size)
194 {
195 GetElapsedSecondsSinceBoot();
196 }
197
TestIp4IntConvertToStr(const uint8_t * data,size_t size)198 void TestIp4IntConvertToStr(const uint8_t* data, size_t size)
199 {
200 if (data == nullptr || size < U32_AT_SIZE_ZERO) {
201 return;
202 }
203 uint32_t uIp = U32_AT(data);
204 bool bHost = (size >= SIZEOFHOST) ? (data[INDEX] != 0) : false;
205
206 Ip4IntConvertToStr(uIp, bHost);
207 }
208
TestAddArpEntry(const uint8_t * data,size_t size)209 void TestAddArpEntry(const uint8_t* data, size_t size)
210 {
211 if (data == nullptr || size < U32_AT_SIZE_ZERO) {
212 return;
213 }
214 size_t pos = 0;
215
216 // Check if we have enough data for the first U32_AT call
217 if (pos + sizeof(uint32_t) > size) {
218 return;
219 }
220 uint32_t ifaceLen = U32_AT(data + pos);
221 pos += sizeof(uint32_t);
222 // Validate ifaceLen to prevent integer overflow and excessive memory allocation
223 if (ifaceLen > size || pos + ifaceLen > size) {
224 return;
225 }
226 string iface(reinterpret_cast<const char*>(data + pos), ifaceLen);
227 pos += ifaceLen;
228
229 // Check if we have enough data for the second U32_AT call
230 if (pos + sizeof(uint32_t) > size) {
231 return;
232 }
233 uint32_t ipAddrLen = U32_AT(data + pos);
234 pos += sizeof(uint32_t);
235
236 // Validate ipAddrLen to prevent integer overflow and excessive memory allocation
237 if (ipAddrLen > size || pos + ipAddrLen > size) {
238 return;
239 }
240 string ipAddr(reinterpret_cast<const char*>(data + pos), ipAddrLen);
241 pos += ipAddrLen;
242
243 // Check if we have enough data for the third U32_AT call
244 if (pos + sizeof(uint32_t) > size) {
245 return;
246 }
247 uint32_t macAddrLen = U32_AT(data + pos);
248 pos += sizeof(uint32_t);
249
250 // Validate macAddrLen to prevent integer overflow and excessive memory allocation
251 if (macAddrLen > size || pos + macAddrLen > size) {
252 return;
253 }
254 string macAddr(reinterpret_cast<const char*>(data + pos), macAddrLen);
255
256 AddArpEntry(iface, ipAddr, macAddr);
257 }
258
TestIsValidPath(const uint8_t * data,size_t size)259 void TestIsValidPath(const uint8_t* data, size_t size)
260 {
261 if (size < U32_AT_SIZE_ZERO) {
262 return;
263 }
264 size_t pos = 0;
265 uint32_t filePathLen = U32_AT(data);
266 pos += sizeof(uint32_t);
267 if (pos + filePathLen > size) {
268 return;
269 }
270 string filePath(reinterpret_cast<const char*>(data + pos), filePathLen);
271
272 IsValidPath(filePath);
273 }
274
275 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)276 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
277 {
278 if ((data == nullptr) || (size <= OHOS::DHCP::U32_AT_SIZE_ZERO)) {
279 return 0;
280 }
281
282 // 直接运行所有测试函数
283 TestIpv6Anonymize(data, size);
284 TestIpv4Anonymize(data, size);
285 TestUintIp4ToStr(data, size);
286 TestIntIpv4ToAnonymizeStr(data, size);
287 TestMacArray2Str(data, size);
288 TestCheckDataLegal(data, size);
289 TestCheckDataToUint(data, size);
290 TestCheckDataTolonglong(data, size);
291 TestCheckDataToUint64(data, size);
292 TestGetElapsedSecondsSinceBoot(data, size);
293 TestIp4IntConvertToStr(data, size);
294 TestAddArpEntry(data, size);
295 TestIsValidPath(data, size);
296 return 0;
297 }
298 } // namespace DHCP
299 } // namespace OHOS
300