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