Skip to content

Commit ffede29

Browse files
committed
Add fuzzing for standard compliance checks
1 parent 51e8672 commit ffede29

7 files changed

+70
-5
lines changed

fuzz/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ if(ENABLE_FUZZING)
3131
implement_fuzzer(fuzz_string_select)
3232
implement_fuzzer(fuzz_sort)
3333
implement_fuzzer(fuzz_string_sort)
34+
implement_fuzzer(fuzz_standard_compliance)
3435

3536
# to be able to get a list of all fuzzers from within a script
3637
add_custom_target(print_all_fuzzernames

fuzz/fuzz_select.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ void ChooseImplementation(uint8_t byte, std::vector<U>& working,
2020
...);
2121
}
2222

23-
// Use the first element as a position into the data
2423
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data,
2524
std::size_t size) {
2625
if (size <= 3) return 0;

fuzz/fuzz_sort.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ void ChooseImplementation(uint8_t byte, std::vector<U>& working,
2020
...);
2121
}
2222

23-
// Use the first element as a position into the data
2423
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data,
2524
std::size_t size) {
2625
if (size <= 3) return 0;

fuzz/fuzz_standard_compliance.cpp

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <algorithm>
2+
#include <cstddef>
3+
#include <cstdint>
4+
#include <vector>
5+
6+
#include "test_common.h"
7+
8+
template <class Iter, class... T>
9+
void ChooseImplementation(uint8_t byte, Iter beg, Iter end, Iter partition_iter,
10+
const ::testing::Types<T...>&) {
11+
static_assert(sizeof...(T) < 256);
12+
int i = 0;
13+
constexpr size_t size = sizeof...(T);
14+
(
15+
[&]() {
16+
if (byte % size == i++) {
17+
T::Select(beg, partition_iter, end);
18+
}
19+
}(),
20+
...);
21+
}
22+
23+
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data,
24+
std::size_t size) {
25+
if (size <= 3) return 0;
26+
uint8_t impl = data[0];
27+
uint8_t partition_point = data[1];
28+
size = std::min(std::size_t{129}, size) - 2;
29+
partition_point %= size;
30+
std::vector<char> working(data + 2, data + size + 2);
31+
miniselect::algorithms::IntegralCharIterator<char> beg(working.data());
32+
miniselect::algorithms::IntegralCharIterator<char> ending(working.data() +
33+
working.size());
34+
auto canonical = working;
35+
const auto partition_iter = beg + partition_point;
36+
ChooseImplementation(impl, beg, ending, partition_iter,
37+
miniselect::algorithms::All{});
38+
if (partition_iter != ending) {
39+
const auto& nth = *partition_iter;
40+
bool is_error = false;
41+
if (!std::all_of(beg, partition_iter,
42+
[&](const auto& v) { return v <= nth; })) {
43+
is_error = true;
44+
}
45+
if (!std::all_of(partition_iter, ending,
46+
[&](const auto& v) { return v >= nth; })) {
47+
is_error = true;
48+
}
49+
if (is_error) {
50+
fail:
51+
std::cerr << "FAILED!\nCanonical: ";
52+
for (const auto& s : canonical) {
53+
std::cerr << static_cast<int>(s) << ' ';
54+
}
55+
std::cerr << std::endl;
56+
std::cerr << "Got: ";
57+
for (const auto& s : working) {
58+
std::cerr << static_cast<int>(s) << ' ';
59+
}
60+
std::cerr << std::endl;
61+
std::cerr << "partition_iter = " << static_cast<int>(partition_iter - beg)
62+
<< std::endl;
63+
std::abort();
64+
}
65+
}
66+
67+
return 0;
68+
}

fuzz/fuzz_string_select.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ void ChooseImplementation(uint8_t byte, std::vector<U>& working,
2020
...);
2121
}
2222

23-
// Use the first element as a position into the data
2423
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data,
2524
std::size_t size) {
2625
if (size <= 3) return 0;

fuzz/fuzz_string_sort.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ void ChooseImplementation(uint8_t byte, std::vector<U>& working,
2020
...);
2121
}
2222

23-
// Use the first element as a position into the data
2423
extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data,
2524
std::size_t size) {
2625
if (size <= 3) return 0;

testing/test_common.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ struct IntegralCharIterator {
293293
return pos >= other.pos;
294294
}
295295

296-
char* pos;
296+
char* pos = nullptr;
297297
};
298298

299299
template <class Integral>

0 commit comments

Comments
 (0)