• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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