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 const char* argv[] = {fuzzer_name};
107 base::CommandLine::Init(1, argv);
108 logging::SetLogItems(false, false, false, false);
109
110 if (Size > 0) {
111 auto Packets = UnpackPackets(Data, Size);
112 Fuzz_RunPackets(Packets);
113 }
114
115 if (__gcov_flush) {
116 __gcov_flush();
117 }
118
119 return 0;
120 }
121
LLVMFuzzerInitialize(int * argc,char *** argv)122 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
123 base::CommandLine args(*argc, *argv);
124 if (args.HasSwitch("v") || args.HasSwitch("verbose")) {
125 nfc_debug_enabled = true;
126 FUZZLOG("Debugging output enabled");
127 } else {
128 nfc_debug_enabled = false;
129 }
130
131 return 0;
132 }
133