xref: /aosp_15_r20/system/nfc/src/fuzzers/fuzz_utils.cc (revision 7eba2f3b06c51ae21384f6a4f14577b668a869b3)
1*7eba2f3bSAndroid Build Coastguard Worker #include "fuzz_cmn.h"
2*7eba2f3bSAndroid Build Coastguard Worker 
BytesToHex(const uint8_t * data,size_t size)3*7eba2f3bSAndroid Build Coastguard Worker std::string BytesToHex(const uint8_t* data, size_t size) {
4*7eba2f3bSAndroid Build Coastguard Worker   std::string result = "{";
5*7eba2f3bSAndroid Build Coastguard Worker   if (data && size) {
6*7eba2f3bSAndroid Build Coastguard Worker     StringAppendF(&result, "0x%02X", data[0]);
7*7eba2f3bSAndroid Build Coastguard Worker     for (auto i = 1; i < size; i++) {
8*7eba2f3bSAndroid Build Coastguard Worker       StringAppendF(&result, ", 0x%02X", data[i]);
9*7eba2f3bSAndroid Build Coastguard Worker     }
10*7eba2f3bSAndroid Build Coastguard Worker   }
11*7eba2f3bSAndroid Build Coastguard Worker   result += "}";
12*7eba2f3bSAndroid Build Coastguard Worker 
13*7eba2f3bSAndroid Build Coastguard Worker   return result;
14*7eba2f3bSAndroid Build Coastguard Worker }
15*7eba2f3bSAndroid Build Coastguard Worker 
BytesToHex(const bytes_t & data)16*7eba2f3bSAndroid Build Coastguard Worker std::string BytesToHex(const bytes_t& data) {
17*7eba2f3bSAndroid Build Coastguard Worker   return BytesToHex(&data[0], data.size());
18*7eba2f3bSAndroid Build Coastguard Worker }
19*7eba2f3bSAndroid Build Coastguard Worker 
UnpackPackets(const uint8_t * Data,size_t Size)20*7eba2f3bSAndroid Build Coastguard Worker static std::vector<bytes_t> UnpackPackets(const uint8_t* Data, size_t Size) {
21*7eba2f3bSAndroid Build Coastguard Worker   std::vector<bytes_t> result;
22*7eba2f3bSAndroid Build Coastguard Worker   while (Size > 0) {
23*7eba2f3bSAndroid Build Coastguard Worker     auto s = *Data++;
24*7eba2f3bSAndroid Build Coastguard Worker     Size--;
25*7eba2f3bSAndroid Build Coastguard Worker 
26*7eba2f3bSAndroid Build Coastguard Worker     if (s > Size) {
27*7eba2f3bSAndroid Build Coastguard Worker       s = Size;
28*7eba2f3bSAndroid Build Coastguard Worker     }
29*7eba2f3bSAndroid Build Coastguard Worker 
30*7eba2f3bSAndroid Build Coastguard Worker     if (s > 0) {
31*7eba2f3bSAndroid Build Coastguard Worker       result.push_back(bytes_t(Data, Data + s));
32*7eba2f3bSAndroid Build Coastguard Worker     }
33*7eba2f3bSAndroid Build Coastguard Worker 
34*7eba2f3bSAndroid Build Coastguard Worker     Size -= s;
35*7eba2f3bSAndroid Build Coastguard Worker     Data += s;
36*7eba2f3bSAndroid Build Coastguard Worker   }
37*7eba2f3bSAndroid Build Coastguard Worker 
38*7eba2f3bSAndroid Build Coastguard Worker   return result;
39*7eba2f3bSAndroid Build Coastguard Worker }
40*7eba2f3bSAndroid Build Coastguard Worker 
PackPackets(const std::vector<bytes_t> & Packets,uint8_t * Data,size_t MaxSize)41*7eba2f3bSAndroid Build Coastguard Worker static size_t PackPackets(const std::vector<bytes_t>& Packets, uint8_t* Data,
42*7eba2f3bSAndroid Build Coastguard Worker                           size_t MaxSize) {
43*7eba2f3bSAndroid Build Coastguard Worker   size_t TotalSize = 0;
44*7eba2f3bSAndroid Build Coastguard Worker 
45*7eba2f3bSAndroid Build Coastguard Worker   for (auto it = Packets.cbegin(); MaxSize > 0 && it != Packets.cend(); ++it) {
46*7eba2f3bSAndroid Build Coastguard Worker     auto s = it->size();
47*7eba2f3bSAndroid Build Coastguard Worker     if (s == 0) {
48*7eba2f3bSAndroid Build Coastguard Worker       // skip empty packets
49*7eba2f3bSAndroid Build Coastguard Worker       continue;
50*7eba2f3bSAndroid Build Coastguard Worker     }
51*7eba2f3bSAndroid Build Coastguard Worker 
52*7eba2f3bSAndroid Build Coastguard Worker     if (s > MaxSize - 1) {
53*7eba2f3bSAndroid Build Coastguard Worker       s = MaxSize - 1;
54*7eba2f3bSAndroid Build Coastguard Worker     }
55*7eba2f3bSAndroid Build Coastguard Worker     *Data++ = (uint8_t)s;
56*7eba2f3bSAndroid Build Coastguard Worker     MaxSize--;
57*7eba2f3bSAndroid Build Coastguard Worker 
58*7eba2f3bSAndroid Build Coastguard Worker     memcpy(Data, it->data(), s);
59*7eba2f3bSAndroid Build Coastguard Worker     MaxSize -= s;
60*7eba2f3bSAndroid Build Coastguard Worker     Data += s;
61*7eba2f3bSAndroid Build Coastguard Worker 
62*7eba2f3bSAndroid Build Coastguard Worker     TotalSize += (s + 1);
63*7eba2f3bSAndroid Build Coastguard Worker   }
64*7eba2f3bSAndroid Build Coastguard Worker 
65*7eba2f3bSAndroid Build Coastguard Worker   return TotalSize;
66*7eba2f3bSAndroid Build Coastguard Worker }
67*7eba2f3bSAndroid Build Coastguard Worker 
LLVMFuzzerCustomMutator(uint8_t * Data,size_t Size,size_t MaxSize,uint Seed)68*7eba2f3bSAndroid Build Coastguard Worker extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* Data, size_t Size,
69*7eba2f3bSAndroid Build Coastguard Worker                                           size_t MaxSize, uint Seed) {
70*7eba2f3bSAndroid Build Coastguard Worker   const uint MAX_PACKET_SIZE = 255;
71*7eba2f3bSAndroid Build Coastguard Worker   auto Packets = UnpackPackets(Data, Size);
72*7eba2f3bSAndroid Build Coastguard Worker   auto odd = Seed % 100;
73*7eba2f3bSAndroid Build Coastguard Worker   if (odd < 10 || Packets.size() == 0) {
74*7eba2f3bSAndroid Build Coastguard Worker     // ~10% chance to insert a new packet
75*7eba2f3bSAndroid Build Coastguard Worker     auto len = (Seed >> 8) % MAX_PACKET_SIZE;
76*7eba2f3bSAndroid Build Coastguard Worker     if (Packets.size() > 0) {
77*7eba2f3bSAndroid Build Coastguard Worker       auto pos = (Seed >> 16) % Packets.size();
78*7eba2f3bSAndroid Build Coastguard Worker       Packets.insert(Packets.begin() + pos, bytes_t(len));
79*7eba2f3bSAndroid Build Coastguard Worker     } else {
80*7eba2f3bSAndroid Build Coastguard Worker       Packets.push_back(bytes_t(len));
81*7eba2f3bSAndroid Build Coastguard Worker     }
82*7eba2f3bSAndroid Build Coastguard Worker   } else if (odd < 20 && Packets.size() > 1) {
83*7eba2f3bSAndroid Build Coastguard Worker     // ~10% chance to drop a packet
84*7eba2f3bSAndroid Build Coastguard Worker     auto pos = (Seed >> 16) % Packets.size();
85*7eba2f3bSAndroid Build Coastguard Worker     Packets.erase(Packets.begin() + pos);
86*7eba2f3bSAndroid Build Coastguard Worker   } else if (Packets.size() > 0) {
87*7eba2f3bSAndroid Build Coastguard Worker     // ~80% chance to mutate a packet, maximium length 255
88*7eba2f3bSAndroid Build Coastguard Worker     auto pos = (Seed >> 16) % Packets.size();
89*7eba2f3bSAndroid Build Coastguard Worker     auto& p = Packets[pos];
90*7eba2f3bSAndroid Build Coastguard Worker 
91*7eba2f3bSAndroid Build Coastguard Worker     auto size = p.size();
92*7eba2f3bSAndroid Build Coastguard Worker     p.resize(MAX_PACKET_SIZE);
93*7eba2f3bSAndroid Build Coastguard Worker     size = LLVMFuzzerMutate(p.data(), size, MAX_PACKET_SIZE);
94*7eba2f3bSAndroid Build Coastguard Worker     p.resize(size);
95*7eba2f3bSAndroid Build Coastguard Worker   }
96*7eba2f3bSAndroid Build Coastguard Worker 
97*7eba2f3bSAndroid Build Coastguard Worker   Fuzz_FixPackets(Packets, Seed);
98*7eba2f3bSAndroid Build Coastguard Worker 
99*7eba2f3bSAndroid Build Coastguard Worker   Size = PackPackets(Packets, Data, MaxSize);
100*7eba2f3bSAndroid Build Coastguard Worker   FUZZLOG("Packet size:%zu, data=%s", Packets.size(),
101*7eba2f3bSAndroid Build Coastguard Worker           BytesToHex(Data, Size).c_str());
102*7eba2f3bSAndroid Build Coastguard Worker   return Size;
103*7eba2f3bSAndroid Build Coastguard Worker }
104*7eba2f3bSAndroid Build Coastguard Worker 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)105*7eba2f3bSAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
106*7eba2f3bSAndroid Build Coastguard Worker   android::base::SetDefaultTag(fuzzer_name);
107*7eba2f3bSAndroid Build Coastguard Worker 
108*7eba2f3bSAndroid Build Coastguard Worker   if (Size > 0) {
109*7eba2f3bSAndroid Build Coastguard Worker     auto Packets = UnpackPackets(Data, Size);
110*7eba2f3bSAndroid Build Coastguard Worker     Fuzz_RunPackets(Packets);
111*7eba2f3bSAndroid Build Coastguard Worker   }
112*7eba2f3bSAndroid Build Coastguard Worker 
113*7eba2f3bSAndroid Build Coastguard Worker   if (__gcov_flush) {
114*7eba2f3bSAndroid Build Coastguard Worker     __gcov_flush();
115*7eba2f3bSAndroid Build Coastguard Worker   }
116*7eba2f3bSAndroid Build Coastguard Worker 
117*7eba2f3bSAndroid Build Coastguard Worker   return 0;
118*7eba2f3bSAndroid Build Coastguard Worker }
119*7eba2f3bSAndroid Build Coastguard Worker 
LLVMFuzzerInitialize(int *,char ***)120*7eba2f3bSAndroid Build Coastguard Worker extern "C" int LLVMFuzzerInitialize(int* /*argc*/, char*** /*argv*/) {
121*7eba2f3bSAndroid Build Coastguard Worker   android::base::SetMinimumLogSeverity(android::base::DEBUG);
122*7eba2f3bSAndroid Build Coastguard Worker   FUZZLOG("Debugging output enabled");
123*7eba2f3bSAndroid Build Coastguard Worker 
124*7eba2f3bSAndroid Build Coastguard Worker   return 0;
125*7eba2f3bSAndroid Build Coastguard Worker }
126