This repository has been archived by the owner on Jun 15, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfuzz_sprintf.cpp
128 lines (118 loc) · 2.63 KB
/
fuzz_sprintf.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <cstdint>
#include <fmt/core.h>
#include <fmt/printf.h>
#include <fmt/chrono.h>
#include <iostream>
#include <stdexcept>
#include <type_traits>
#include <vector>
template<typename Item1, typename Item2>
void
doit(const uint8_t* Data, std::size_t Size)
{
const auto N1 = sizeof(Item1);
const auto N2 = sizeof(Item2);
if (Size <= N1 + N2) {
return;
}
Item1 item1{};
if constexpr (std::is_same<Item1, bool>::value) {
item1 = !!Data[0];
} else {
std::memcpy(&item1, Data, N1);
}
Data += N1;
Size -= N1;
Item2 item2{};
if constexpr (std::is_same<Item2, bool>::value) {
item2 = !!Data[0];
} else {
std::memcpy(&item2, Data, N2);
}
Data += N2;
Size -= N2;
// allocates as tight as possible, making it easier to catch buffer overruns.
// also, make it null terminated.
std::vector<char> buf(Size + 1);
std::memcpy(buf.data(), Data, Size);
std::string message = fmt::sprintf(buf.data(), item1, item2);
}
// for dynamic dispatching to an explicit instantiation
template<typename Callback>
void
invoke(int index, Callback callback)
{
switch (index) {
case 0:
callback(bool{});
break;
case 1:
callback(char{});
break;
case 2:
callback(short{});
break;
case 3:
callback(int{});
break;
case 4:
callback(long{});
break;
case 5:
callback(float{});
break;
case 6:
callback(double{});
break;
case 7:
using LD = long double;
callback(LD{});
break;
}
}
extern "C" int
LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size)
{
if (Size <= 3) {
return 0;
}
// switch types depending on the first byte of the input
const auto first = Data[0] & 0x0F;
const auto second = (Data[0] & 0xF0) >> 4;
Data++;
Size--;
auto outer = [=](auto param1) {
auto inner = [=](auto param2) {
// std::cout<<"invoked with param1="<<sizeof(param1)<<"
// param2="<<sizeof(param2)<<'\n';
doit<decltype(param1), decltype(param2)>(Data, Size);
};
invoke(second, inner);
};
try {
invoke(first, outer);
} catch (std::exception& e) {
}
return 0;
}
#ifdef IMPLEMENT_MAIN
#include <cassert>
#include <fstream>
#include <sstream>
#include <vector>
int
main(int argc, char* argv[])
{
for (int i = 1; i < argc; ++i) {
std::ifstream in(argv[i]);
assert(in);
in.seekg(0, std::ios_base::end);
const auto pos = in.tellg();
in.seekg(0, std::ios_base::beg);
std::vector<char> buf(pos);
in.read(buf.data(), buf.size());
assert(in.gcount() == pos);
LLVMFuzzerTestOneInput((const uint8_t*)buf.data(), buf.size());
}
}
#endif