1*58b9f456SAndroid Build Coastguard Worker // -*- C++ -*-
2*58b9f456SAndroid Build Coastguard Worker //===------------------------- fuzzing.cpp -------------------------------===//
3*58b9f456SAndroid Build Coastguard Worker //
4*58b9f456SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
5*58b9f456SAndroid Build Coastguard Worker //
6*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
7*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
8*58b9f456SAndroid Build Coastguard Worker //
9*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
10*58b9f456SAndroid Build Coastguard Worker
11*58b9f456SAndroid Build Coastguard Worker // A set of routines to use when fuzzing the algorithms in libc++
12*58b9f456SAndroid Build Coastguard Worker // Each one tests a single algorithm.
13*58b9f456SAndroid Build Coastguard Worker //
14*58b9f456SAndroid Build Coastguard Worker // They all have the form of:
15*58b9f456SAndroid Build Coastguard Worker // int `algorithm`(const uint8_t *data, size_t size);
16*58b9f456SAndroid Build Coastguard Worker //
17*58b9f456SAndroid Build Coastguard Worker // They perform the operation, and then check to see if the results are correct.
18*58b9f456SAndroid Build Coastguard Worker // If so, they return zero, and non-zero otherwise.
19*58b9f456SAndroid Build Coastguard Worker //
20*58b9f456SAndroid Build Coastguard Worker // For example, sort calls std::sort, then checks two things:
21*58b9f456SAndroid Build Coastguard Worker // (1) The resulting vector is sorted
22*58b9f456SAndroid Build Coastguard Worker // (2) The resulting vector contains the same elements as the original data.
23*58b9f456SAndroid Build Coastguard Worker
24*58b9f456SAndroid Build Coastguard Worker
25*58b9f456SAndroid Build Coastguard Worker
26*58b9f456SAndroid Build Coastguard Worker #include "fuzzing.h"
27*58b9f456SAndroid Build Coastguard Worker #include <vector>
28*58b9f456SAndroid Build Coastguard Worker #include <algorithm>
29*58b9f456SAndroid Build Coastguard Worker #include <functional>
30*58b9f456SAndroid Build Coastguard Worker #include <regex>
31*58b9f456SAndroid Build Coastguard Worker #include <cassert>
32*58b9f456SAndroid Build Coastguard Worker
33*58b9f456SAndroid Build Coastguard Worker #include <iostream>
34*58b9f456SAndroid Build Coastguard Worker
35*58b9f456SAndroid Build Coastguard Worker // If we had C++14, we could use the four iterator version of is_permutation and equal
36*58b9f456SAndroid Build Coastguard Worker
37*58b9f456SAndroid Build Coastguard Worker namespace fuzzing {
38*58b9f456SAndroid Build Coastguard Worker
39*58b9f456SAndroid Build Coastguard Worker // This is a struct we can use to test the stable_XXX algorithms.
40*58b9f456SAndroid Build Coastguard Worker // perform the operation on the key, then check the order of the payload.
41*58b9f456SAndroid Build Coastguard Worker
42*58b9f456SAndroid Build Coastguard Worker struct stable_test {
43*58b9f456SAndroid Build Coastguard Worker uint8_t key;
44*58b9f456SAndroid Build Coastguard Worker size_t payload;
45*58b9f456SAndroid Build Coastguard Worker
stable_testfuzzing::stable_test46*58b9f456SAndroid Build Coastguard Worker stable_test(uint8_t k) : key(k), payload(0) {}
stable_testfuzzing::stable_test47*58b9f456SAndroid Build Coastguard Worker stable_test(uint8_t k, size_t p) : key(k), payload(p) {}
48*58b9f456SAndroid Build Coastguard Worker };
49*58b9f456SAndroid Build Coastguard Worker
swap(stable_test & lhs,stable_test & rhs)50*58b9f456SAndroid Build Coastguard Worker void swap(stable_test &lhs, stable_test &rhs)
51*58b9f456SAndroid Build Coastguard Worker {
52*58b9f456SAndroid Build Coastguard Worker using std::swap;
53*58b9f456SAndroid Build Coastguard Worker swap(lhs.key, rhs.key);
54*58b9f456SAndroid Build Coastguard Worker swap(lhs.payload, rhs.payload);
55*58b9f456SAndroid Build Coastguard Worker }
56*58b9f456SAndroid Build Coastguard Worker
57*58b9f456SAndroid Build Coastguard Worker struct key_less
58*58b9f456SAndroid Build Coastguard Worker {
operator ()fuzzing::key_less59*58b9f456SAndroid Build Coastguard Worker bool operator () (const stable_test &lhs, const stable_test &rhs) const
60*58b9f456SAndroid Build Coastguard Worker {
61*58b9f456SAndroid Build Coastguard Worker return lhs.key < rhs.key;
62*58b9f456SAndroid Build Coastguard Worker }
63*58b9f456SAndroid Build Coastguard Worker };
64*58b9f456SAndroid Build Coastguard Worker
65*58b9f456SAndroid Build Coastguard Worker struct payload_less
66*58b9f456SAndroid Build Coastguard Worker {
operator ()fuzzing::payload_less67*58b9f456SAndroid Build Coastguard Worker bool operator () (const stable_test &lhs, const stable_test &rhs) const
68*58b9f456SAndroid Build Coastguard Worker {
69*58b9f456SAndroid Build Coastguard Worker return lhs.payload < rhs.payload;
70*58b9f456SAndroid Build Coastguard Worker }
71*58b9f456SAndroid Build Coastguard Worker };
72*58b9f456SAndroid Build Coastguard Worker
73*58b9f456SAndroid Build Coastguard Worker struct total_less
74*58b9f456SAndroid Build Coastguard Worker {
operator ()fuzzing::total_less75*58b9f456SAndroid Build Coastguard Worker bool operator () (const stable_test &lhs, const stable_test &rhs) const
76*58b9f456SAndroid Build Coastguard Worker {
77*58b9f456SAndroid Build Coastguard Worker return lhs.key == rhs.key ? lhs.payload < rhs.payload : lhs.key < rhs.key;
78*58b9f456SAndroid Build Coastguard Worker }
79*58b9f456SAndroid Build Coastguard Worker };
80*58b9f456SAndroid Build Coastguard Worker
operator ==(const stable_test & lhs,const stable_test & rhs)81*58b9f456SAndroid Build Coastguard Worker bool operator==(const stable_test &lhs, const stable_test &rhs)
82*58b9f456SAndroid Build Coastguard Worker {
83*58b9f456SAndroid Build Coastguard Worker return lhs.key == rhs.key && lhs.payload == rhs.payload;
84*58b9f456SAndroid Build Coastguard Worker }
85*58b9f456SAndroid Build Coastguard Worker
86*58b9f456SAndroid Build Coastguard Worker
87*58b9f456SAndroid Build Coastguard Worker template<typename T>
88*58b9f456SAndroid Build Coastguard Worker struct is_even
89*58b9f456SAndroid Build Coastguard Worker {
operator ()fuzzing::is_even90*58b9f456SAndroid Build Coastguard Worker bool operator () (const T &t) const
91*58b9f456SAndroid Build Coastguard Worker {
92*58b9f456SAndroid Build Coastguard Worker return t % 2 == 0;
93*58b9f456SAndroid Build Coastguard Worker }
94*58b9f456SAndroid Build Coastguard Worker };
95*58b9f456SAndroid Build Coastguard Worker
96*58b9f456SAndroid Build Coastguard Worker
97*58b9f456SAndroid Build Coastguard Worker template<>
98*58b9f456SAndroid Build Coastguard Worker struct is_even<stable_test>
99*58b9f456SAndroid Build Coastguard Worker {
operator ()fuzzing::is_even100*58b9f456SAndroid Build Coastguard Worker bool operator () (const stable_test &t) const
101*58b9f456SAndroid Build Coastguard Worker {
102*58b9f456SAndroid Build Coastguard Worker return t.key % 2 == 0;
103*58b9f456SAndroid Build Coastguard Worker }
104*58b9f456SAndroid Build Coastguard Worker };
105*58b9f456SAndroid Build Coastguard Worker
106*58b9f456SAndroid Build Coastguard Worker typedef std::vector<uint8_t> Vec;
107*58b9f456SAndroid Build Coastguard Worker typedef std::vector<stable_test> StableVec;
108*58b9f456SAndroid Build Coastguard Worker typedef StableVec::const_iterator SVIter;
109*58b9f456SAndroid Build Coastguard Worker
110*58b9f456SAndroid Build Coastguard Worker // Cheap version of is_permutation
111*58b9f456SAndroid Build Coastguard Worker // Builds a set of buckets for each of the key values.
112*58b9f456SAndroid Build Coastguard Worker // Sums all the payloads.
113*58b9f456SAndroid Build Coastguard Worker // Not 100% perfect, but _way_ faster
is_permutation(SVIter first1,SVIter last1,SVIter first2)114*58b9f456SAndroid Build Coastguard Worker bool is_permutation(SVIter first1, SVIter last1, SVIter first2)
115*58b9f456SAndroid Build Coastguard Worker {
116*58b9f456SAndroid Build Coastguard Worker size_t xBuckets[256] = {0};
117*58b9f456SAndroid Build Coastguard Worker size_t xPayloads[256] = {0};
118*58b9f456SAndroid Build Coastguard Worker size_t yBuckets[256] = {0};
119*58b9f456SAndroid Build Coastguard Worker size_t yPayloads[256] = {0};
120*58b9f456SAndroid Build Coastguard Worker
121*58b9f456SAndroid Build Coastguard Worker for (; first1 != last1; ++first1, ++first2)
122*58b9f456SAndroid Build Coastguard Worker {
123*58b9f456SAndroid Build Coastguard Worker xBuckets [first1->key]++;
124*58b9f456SAndroid Build Coastguard Worker xPayloads[first1->key] += first1->payload;
125*58b9f456SAndroid Build Coastguard Worker
126*58b9f456SAndroid Build Coastguard Worker yBuckets [first2->key]++;
127*58b9f456SAndroid Build Coastguard Worker yPayloads[first2->key] += first2->payload;
128*58b9f456SAndroid Build Coastguard Worker }
129*58b9f456SAndroid Build Coastguard Worker
130*58b9f456SAndroid Build Coastguard Worker for (size_t i = 0; i < 256; ++i)
131*58b9f456SAndroid Build Coastguard Worker {
132*58b9f456SAndroid Build Coastguard Worker if (xBuckets[i] != yBuckets[i])
133*58b9f456SAndroid Build Coastguard Worker return false;
134*58b9f456SAndroid Build Coastguard Worker if (xPayloads[i] != yPayloads[i])
135*58b9f456SAndroid Build Coastguard Worker return false;
136*58b9f456SAndroid Build Coastguard Worker }
137*58b9f456SAndroid Build Coastguard Worker
138*58b9f456SAndroid Build Coastguard Worker return true;
139*58b9f456SAndroid Build Coastguard Worker }
140*58b9f456SAndroid Build Coastguard Worker
141*58b9f456SAndroid Build Coastguard Worker template <typename Iter1, typename Iter2>
is_permutation(Iter1 first1,Iter1 last1,Iter2 first2)142*58b9f456SAndroid Build Coastguard Worker bool is_permutation(Iter1 first1, Iter1 last1, Iter2 first2)
143*58b9f456SAndroid Build Coastguard Worker {
144*58b9f456SAndroid Build Coastguard Worker static_assert((std::is_same<typename std::iterator_traits<Iter1>::value_type, uint8_t>::value), "");
145*58b9f456SAndroid Build Coastguard Worker static_assert((std::is_same<typename std::iterator_traits<Iter2>::value_type, uint8_t>::value), "");
146*58b9f456SAndroid Build Coastguard Worker
147*58b9f456SAndroid Build Coastguard Worker size_t xBuckets[256] = {0};
148*58b9f456SAndroid Build Coastguard Worker size_t yBuckets[256] = {0};
149*58b9f456SAndroid Build Coastguard Worker
150*58b9f456SAndroid Build Coastguard Worker for (; first1 != last1; ++first1, ++first2)
151*58b9f456SAndroid Build Coastguard Worker {
152*58b9f456SAndroid Build Coastguard Worker xBuckets [*first1]++;
153*58b9f456SAndroid Build Coastguard Worker yBuckets [*first2]++;
154*58b9f456SAndroid Build Coastguard Worker }
155*58b9f456SAndroid Build Coastguard Worker
156*58b9f456SAndroid Build Coastguard Worker for (size_t i = 0; i < 256; ++i)
157*58b9f456SAndroid Build Coastguard Worker if (xBuckets[i] != yBuckets[i])
158*58b9f456SAndroid Build Coastguard Worker return false;
159*58b9f456SAndroid Build Coastguard Worker
160*58b9f456SAndroid Build Coastguard Worker return true;
161*58b9f456SAndroid Build Coastguard Worker }
162*58b9f456SAndroid Build Coastguard Worker
163*58b9f456SAndroid Build Coastguard Worker // == sort ==
sort(const uint8_t * data,size_t size)164*58b9f456SAndroid Build Coastguard Worker int sort(const uint8_t *data, size_t size)
165*58b9f456SAndroid Build Coastguard Worker {
166*58b9f456SAndroid Build Coastguard Worker Vec working(data, data + size);
167*58b9f456SAndroid Build Coastguard Worker std::sort(working.begin(), working.end());
168*58b9f456SAndroid Build Coastguard Worker
169*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(working.begin(), working.end())) return 1;
170*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
171*58b9f456SAndroid Build Coastguard Worker return 0;
172*58b9f456SAndroid Build Coastguard Worker }
173*58b9f456SAndroid Build Coastguard Worker
174*58b9f456SAndroid Build Coastguard Worker
175*58b9f456SAndroid Build Coastguard Worker // == stable_sort ==
stable_sort(const uint8_t * data,size_t size)176*58b9f456SAndroid Build Coastguard Worker int stable_sort(const uint8_t *data, size_t size)
177*58b9f456SAndroid Build Coastguard Worker {
178*58b9f456SAndroid Build Coastguard Worker StableVec input;
179*58b9f456SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i)
180*58b9f456SAndroid Build Coastguard Worker input.push_back(stable_test(data[i], i));
181*58b9f456SAndroid Build Coastguard Worker StableVec working = input;
182*58b9f456SAndroid Build Coastguard Worker std::stable_sort(working.begin(), working.end(), key_less());
183*58b9f456SAndroid Build Coastguard Worker
184*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(working.begin(), working.end(), key_less())) return 1;
185*58b9f456SAndroid Build Coastguard Worker auto iter = working.begin();
186*58b9f456SAndroid Build Coastguard Worker while (iter != working.end())
187*58b9f456SAndroid Build Coastguard Worker {
188*58b9f456SAndroid Build Coastguard Worker auto range = std::equal_range(iter, working.end(), *iter, key_less());
189*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(range.first, range.second, total_less())) return 2;
190*58b9f456SAndroid Build Coastguard Worker iter = range.second;
191*58b9f456SAndroid Build Coastguard Worker }
192*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(input.cbegin(), input.cend(), working.cbegin())) return 99;
193*58b9f456SAndroid Build Coastguard Worker return 0;
194*58b9f456SAndroid Build Coastguard Worker }
195*58b9f456SAndroid Build Coastguard Worker
196*58b9f456SAndroid Build Coastguard Worker // == partition ==
partition(const uint8_t * data,size_t size)197*58b9f456SAndroid Build Coastguard Worker int partition(const uint8_t *data, size_t size)
198*58b9f456SAndroid Build Coastguard Worker {
199*58b9f456SAndroid Build Coastguard Worker Vec working(data, data + size);
200*58b9f456SAndroid Build Coastguard Worker auto iter = std::partition(working.begin(), working.end(), is_even<uint8_t>());
201*58b9f456SAndroid Build Coastguard Worker
202*58b9f456SAndroid Build Coastguard Worker if (!std::all_of (working.begin(), iter, is_even<uint8_t>())) return 1;
203*58b9f456SAndroid Build Coastguard Worker if (!std::none_of(iter, working.end(), is_even<uint8_t>())) return 2;
204*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
205*58b9f456SAndroid Build Coastguard Worker return 0;
206*58b9f456SAndroid Build Coastguard Worker }
207*58b9f456SAndroid Build Coastguard Worker
208*58b9f456SAndroid Build Coastguard Worker
209*58b9f456SAndroid Build Coastguard Worker // == partition_copy ==
partition_copy(const uint8_t * data,size_t size)210*58b9f456SAndroid Build Coastguard Worker int partition_copy(const uint8_t *data, size_t size)
211*58b9f456SAndroid Build Coastguard Worker {
212*58b9f456SAndroid Build Coastguard Worker Vec v1, v2;
213*58b9f456SAndroid Build Coastguard Worker auto iter = std::partition_copy(data, data + size,
214*58b9f456SAndroid Build Coastguard Worker std::back_inserter<Vec>(v1), std::back_inserter<Vec>(v2),
215*58b9f456SAndroid Build Coastguard Worker is_even<uint8_t>());
216*58b9f456SAndroid Build Coastguard Worker
217*58b9f456SAndroid Build Coastguard Worker // The two vectors should add up to the original size
218*58b9f456SAndroid Build Coastguard Worker if (v1.size() + v2.size() != size) return 1;
219*58b9f456SAndroid Build Coastguard Worker
220*58b9f456SAndroid Build Coastguard Worker // All of the even values should be in the first vector, and none in the second
221*58b9f456SAndroid Build Coastguard Worker if (!std::all_of (v1.begin(), v1.end(), is_even<uint8_t>())) return 2;
222*58b9f456SAndroid Build Coastguard Worker if (!std::none_of(v2.begin(), v2.end(), is_even<uint8_t>())) return 3;
223*58b9f456SAndroid Build Coastguard Worker
224*58b9f456SAndroid Build Coastguard Worker // Every value in both vectors has to be in the original
225*58b9f456SAndroid Build Coastguard Worker
226*58b9f456SAndroid Build Coastguard Worker // Make a copy of the input, and sort it
227*58b9f456SAndroid Build Coastguard Worker Vec v0{data, data + size};
228*58b9f456SAndroid Build Coastguard Worker std::sort(v0.begin(), v0.end());
229*58b9f456SAndroid Build Coastguard Worker
230*58b9f456SAndroid Build Coastguard Worker // Sort each vector and ensure that all of the elements appear in the original input
231*58b9f456SAndroid Build Coastguard Worker std::sort(v1.begin(), v1.end());
232*58b9f456SAndroid Build Coastguard Worker if (!std::includes(v0.begin(), v0.end(), v1.begin(), v1.end())) return 4;
233*58b9f456SAndroid Build Coastguard Worker
234*58b9f456SAndroid Build Coastguard Worker std::sort(v2.begin(), v2.end());
235*58b9f456SAndroid Build Coastguard Worker if (!std::includes(v0.begin(), v0.end(), v2.begin(), v2.end())) return 5;
236*58b9f456SAndroid Build Coastguard Worker
237*58b9f456SAndroid Build Coastguard Worker // This, while simple, is really slow - 20 seconds on a 500K element input.
238*58b9f456SAndroid Build Coastguard Worker // for (auto v: v1)
239*58b9f456SAndroid Build Coastguard Worker // if (std::find(data, data + size, v) == data + size) return 4;
240*58b9f456SAndroid Build Coastguard Worker //
241*58b9f456SAndroid Build Coastguard Worker // for (auto v: v2)
242*58b9f456SAndroid Build Coastguard Worker // if (std::find(data, data + size, v) == data + size) return 5;
243*58b9f456SAndroid Build Coastguard Worker
244*58b9f456SAndroid Build Coastguard Worker return 0;
245*58b9f456SAndroid Build Coastguard Worker }
246*58b9f456SAndroid Build Coastguard Worker
247*58b9f456SAndroid Build Coastguard Worker // == stable_partition ==
stable_partition(const uint8_t * data,size_t size)248*58b9f456SAndroid Build Coastguard Worker int stable_partition (const uint8_t *data, size_t size)
249*58b9f456SAndroid Build Coastguard Worker {
250*58b9f456SAndroid Build Coastguard Worker StableVec input;
251*58b9f456SAndroid Build Coastguard Worker for (size_t i = 0; i < size; ++i)
252*58b9f456SAndroid Build Coastguard Worker input.push_back(stable_test(data[i], i));
253*58b9f456SAndroid Build Coastguard Worker StableVec working = input;
254*58b9f456SAndroid Build Coastguard Worker auto iter = std::stable_partition(working.begin(), working.end(), is_even<stable_test>());
255*58b9f456SAndroid Build Coastguard Worker
256*58b9f456SAndroid Build Coastguard Worker if (!std::all_of (working.begin(), iter, is_even<stable_test>())) return 1;
257*58b9f456SAndroid Build Coastguard Worker if (!std::none_of(iter, working.end(), is_even<stable_test>())) return 2;
258*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(working.begin(), iter, payload_less())) return 3;
259*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(iter, working.end(), payload_less())) return 4;
260*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(input.cbegin(), input.cend(), working.cbegin())) return 99;
261*58b9f456SAndroid Build Coastguard Worker return 0;
262*58b9f456SAndroid Build Coastguard Worker }
263*58b9f456SAndroid Build Coastguard Worker
264*58b9f456SAndroid Build Coastguard Worker // == nth_element ==
265*58b9f456SAndroid Build Coastguard Worker // use the first element as a position into the data
nth_element(const uint8_t * data,size_t size)266*58b9f456SAndroid Build Coastguard Worker int nth_element (const uint8_t *data, size_t size)
267*58b9f456SAndroid Build Coastguard Worker {
268*58b9f456SAndroid Build Coastguard Worker if (size <= 1) return 0;
269*58b9f456SAndroid Build Coastguard Worker const size_t partition_point = data[0] % size;
270*58b9f456SAndroid Build Coastguard Worker Vec working(data + 1, data + size);
271*58b9f456SAndroid Build Coastguard Worker const auto partition_iter = working.begin() + partition_point;
272*58b9f456SAndroid Build Coastguard Worker std::nth_element(working.begin(), partition_iter, working.end());
273*58b9f456SAndroid Build Coastguard Worker
274*58b9f456SAndroid Build Coastguard Worker // nth may be the end iterator, in this case nth_element has no effect.
275*58b9f456SAndroid Build Coastguard Worker if (partition_iter == working.end())
276*58b9f456SAndroid Build Coastguard Worker {
277*58b9f456SAndroid Build Coastguard Worker if (!std::equal(data + 1, data + size, working.begin())) return 98;
278*58b9f456SAndroid Build Coastguard Worker }
279*58b9f456SAndroid Build Coastguard Worker else
280*58b9f456SAndroid Build Coastguard Worker {
281*58b9f456SAndroid Build Coastguard Worker const uint8_t nth = *partition_iter;
282*58b9f456SAndroid Build Coastguard Worker if (!std::all_of(working.begin(), partition_iter, [=](uint8_t v) { return v <= nth; }))
283*58b9f456SAndroid Build Coastguard Worker return 1;
284*58b9f456SAndroid Build Coastguard Worker if (!std::all_of(partition_iter, working.end(), [=](uint8_t v) { return v >= nth; }))
285*58b9f456SAndroid Build Coastguard Worker return 2;
286*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(data + 1, data + size, working.cbegin())) return 99;
287*58b9f456SAndroid Build Coastguard Worker }
288*58b9f456SAndroid Build Coastguard Worker
289*58b9f456SAndroid Build Coastguard Worker return 0;
290*58b9f456SAndroid Build Coastguard Worker }
291*58b9f456SAndroid Build Coastguard Worker
292*58b9f456SAndroid Build Coastguard Worker // == partial_sort ==
293*58b9f456SAndroid Build Coastguard Worker // use the first element as a position into the data
partial_sort(const uint8_t * data,size_t size)294*58b9f456SAndroid Build Coastguard Worker int partial_sort (const uint8_t *data, size_t size)
295*58b9f456SAndroid Build Coastguard Worker {
296*58b9f456SAndroid Build Coastguard Worker if (size <= 1) return 0;
297*58b9f456SAndroid Build Coastguard Worker const size_t sort_point = data[0] % size;
298*58b9f456SAndroid Build Coastguard Worker Vec working(data + 1, data + size);
299*58b9f456SAndroid Build Coastguard Worker const auto sort_iter = working.begin() + sort_point;
300*58b9f456SAndroid Build Coastguard Worker std::partial_sort(working.begin(), sort_iter, working.end());
301*58b9f456SAndroid Build Coastguard Worker
302*58b9f456SAndroid Build Coastguard Worker if (sort_iter != working.end())
303*58b9f456SAndroid Build Coastguard Worker {
304*58b9f456SAndroid Build Coastguard Worker const uint8_t nth = *std::min_element(sort_iter, working.end());
305*58b9f456SAndroid Build Coastguard Worker if (!std::all_of(working.begin(), sort_iter, [=](uint8_t v) { return v <= nth; }))
306*58b9f456SAndroid Build Coastguard Worker return 1;
307*58b9f456SAndroid Build Coastguard Worker if (!std::all_of(sort_iter, working.end(), [=](uint8_t v) { return v >= nth; }))
308*58b9f456SAndroid Build Coastguard Worker return 2;
309*58b9f456SAndroid Build Coastguard Worker }
310*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(working.begin(), sort_iter)) return 3;
311*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(data + 1, data + size, working.cbegin())) return 99;
312*58b9f456SAndroid Build Coastguard Worker
313*58b9f456SAndroid Build Coastguard Worker return 0;
314*58b9f456SAndroid Build Coastguard Worker }
315*58b9f456SAndroid Build Coastguard Worker
316*58b9f456SAndroid Build Coastguard Worker
317*58b9f456SAndroid Build Coastguard Worker // == partial_sort_copy ==
318*58b9f456SAndroid Build Coastguard Worker // use the first element as a count
partial_sort_copy(const uint8_t * data,size_t size)319*58b9f456SAndroid Build Coastguard Worker int partial_sort_copy (const uint8_t *data, size_t size)
320*58b9f456SAndroid Build Coastguard Worker {
321*58b9f456SAndroid Build Coastguard Worker if (size <= 1) return 0;
322*58b9f456SAndroid Build Coastguard Worker const size_t num_results = data[0] % size;
323*58b9f456SAndroid Build Coastguard Worker Vec results(num_results);
324*58b9f456SAndroid Build Coastguard Worker (void) std::partial_sort_copy(data + 1, data + size, results.begin(), results.end());
325*58b9f456SAndroid Build Coastguard Worker
326*58b9f456SAndroid Build Coastguard Worker // The results have to be sorted
327*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(results.begin(), results.end())) return 1;
328*58b9f456SAndroid Build Coastguard Worker // All the values in results have to be in the original data
329*58b9f456SAndroid Build Coastguard Worker for (auto v: results)
330*58b9f456SAndroid Build Coastguard Worker if (std::find(data + 1, data + size, v) == data + size) return 2;
331*58b9f456SAndroid Build Coastguard Worker
332*58b9f456SAndroid Build Coastguard Worker // The things in results have to be the smallest N in the original data
333*58b9f456SAndroid Build Coastguard Worker Vec sorted(data + 1, data + size);
334*58b9f456SAndroid Build Coastguard Worker std::sort(sorted.begin(), sorted.end());
335*58b9f456SAndroid Build Coastguard Worker if (!std::equal(results.begin(), results.end(), sorted.begin())) return 3;
336*58b9f456SAndroid Build Coastguard Worker return 0;
337*58b9f456SAndroid Build Coastguard Worker }
338*58b9f456SAndroid Build Coastguard Worker
339*58b9f456SAndroid Build Coastguard Worker // The second sequence has been "uniqued"
340*58b9f456SAndroid Build Coastguard Worker template <typename Iter1, typename Iter2>
compare_unique(Iter1 first1,Iter1 last1,Iter2 first2,Iter2 last2)341*58b9f456SAndroid Build Coastguard Worker static bool compare_unique(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2)
342*58b9f456SAndroid Build Coastguard Worker {
343*58b9f456SAndroid Build Coastguard Worker assert(first1 != last1 && first2 != last2);
344*58b9f456SAndroid Build Coastguard Worker if (*first1 != *first2) return false;
345*58b9f456SAndroid Build Coastguard Worker
346*58b9f456SAndroid Build Coastguard Worker uint8_t last_value = *first1;
347*58b9f456SAndroid Build Coastguard Worker ++first1; ++first2;
348*58b9f456SAndroid Build Coastguard Worker while(first1 != last1 && first2 != last2)
349*58b9f456SAndroid Build Coastguard Worker {
350*58b9f456SAndroid Build Coastguard Worker // Skip over dups in the first sequence
351*58b9f456SAndroid Build Coastguard Worker while (*first1 == last_value)
352*58b9f456SAndroid Build Coastguard Worker if (++first1 == last1) return false;
353*58b9f456SAndroid Build Coastguard Worker if (*first1 != *first2) return false;
354*58b9f456SAndroid Build Coastguard Worker last_value = *first1;
355*58b9f456SAndroid Build Coastguard Worker ++first1; ++first2;
356*58b9f456SAndroid Build Coastguard Worker }
357*58b9f456SAndroid Build Coastguard Worker
358*58b9f456SAndroid Build Coastguard Worker // Still stuff left in the 'uniqued' sequence - oops
359*58b9f456SAndroid Build Coastguard Worker if (first1 == last1 && first2 != last2) return false;
360*58b9f456SAndroid Build Coastguard Worker
361*58b9f456SAndroid Build Coastguard Worker // Still stuff left in the original sequence - better be all the same
362*58b9f456SAndroid Build Coastguard Worker while (first1 != last1)
363*58b9f456SAndroid Build Coastguard Worker {
364*58b9f456SAndroid Build Coastguard Worker if (*first1 != last_value) return false;
365*58b9f456SAndroid Build Coastguard Worker ++first1;
366*58b9f456SAndroid Build Coastguard Worker }
367*58b9f456SAndroid Build Coastguard Worker return true;
368*58b9f456SAndroid Build Coastguard Worker }
369*58b9f456SAndroid Build Coastguard Worker
370*58b9f456SAndroid Build Coastguard Worker // == unique ==
unique(const uint8_t * data,size_t size)371*58b9f456SAndroid Build Coastguard Worker int unique (const uint8_t *data, size_t size)
372*58b9f456SAndroid Build Coastguard Worker {
373*58b9f456SAndroid Build Coastguard Worker Vec working(data, data + size);
374*58b9f456SAndroid Build Coastguard Worker std::sort(working.begin(), working.end());
375*58b9f456SAndroid Build Coastguard Worker Vec results = working;
376*58b9f456SAndroid Build Coastguard Worker Vec::iterator new_end = std::unique(results.begin(), results.end());
377*58b9f456SAndroid Build Coastguard Worker Vec::iterator it; // scratch iterator
378*58b9f456SAndroid Build Coastguard Worker
379*58b9f456SAndroid Build Coastguard Worker // Check the size of the unique'd sequence.
380*58b9f456SAndroid Build Coastguard Worker // it should only be zero if the input sequence was empty.
381*58b9f456SAndroid Build Coastguard Worker if (results.begin() == new_end)
382*58b9f456SAndroid Build Coastguard Worker return working.size() == 0 ? 0 : 1;
383*58b9f456SAndroid Build Coastguard Worker
384*58b9f456SAndroid Build Coastguard Worker // 'results' is sorted
385*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(results.begin(), new_end)) return 2;
386*58b9f456SAndroid Build Coastguard Worker
387*58b9f456SAndroid Build Coastguard Worker // All the elements in 'results' must be different
388*58b9f456SAndroid Build Coastguard Worker it = results.begin();
389*58b9f456SAndroid Build Coastguard Worker uint8_t prev_value = *it++;
390*58b9f456SAndroid Build Coastguard Worker for (; it != new_end; ++it)
391*58b9f456SAndroid Build Coastguard Worker {
392*58b9f456SAndroid Build Coastguard Worker if (*it == prev_value) return 3;
393*58b9f456SAndroid Build Coastguard Worker prev_value = *it;
394*58b9f456SAndroid Build Coastguard Worker }
395*58b9f456SAndroid Build Coastguard Worker
396*58b9f456SAndroid Build Coastguard Worker // Every element in 'results' must be in 'working'
397*58b9f456SAndroid Build Coastguard Worker for (it = results.begin(); it != new_end; ++it)
398*58b9f456SAndroid Build Coastguard Worker if (std::find(working.begin(), working.end(), *it) == working.end())
399*58b9f456SAndroid Build Coastguard Worker return 4;
400*58b9f456SAndroid Build Coastguard Worker
401*58b9f456SAndroid Build Coastguard Worker // Every element in 'working' must be in 'results'
402*58b9f456SAndroid Build Coastguard Worker for (auto v : working)
403*58b9f456SAndroid Build Coastguard Worker if (std::find(results.begin(), new_end, v) == new_end)
404*58b9f456SAndroid Build Coastguard Worker return 5;
405*58b9f456SAndroid Build Coastguard Worker
406*58b9f456SAndroid Build Coastguard Worker return 0;
407*58b9f456SAndroid Build Coastguard Worker }
408*58b9f456SAndroid Build Coastguard Worker
409*58b9f456SAndroid Build Coastguard Worker // == unique_copy ==
unique_copy(const uint8_t * data,size_t size)410*58b9f456SAndroid Build Coastguard Worker int unique_copy (const uint8_t *data, size_t size)
411*58b9f456SAndroid Build Coastguard Worker {
412*58b9f456SAndroid Build Coastguard Worker Vec working(data, data + size);
413*58b9f456SAndroid Build Coastguard Worker std::sort(working.begin(), working.end());
414*58b9f456SAndroid Build Coastguard Worker Vec results;
415*58b9f456SAndroid Build Coastguard Worker (void) std::unique_copy(working.begin(), working.end(),
416*58b9f456SAndroid Build Coastguard Worker std::back_inserter<Vec>(results));
417*58b9f456SAndroid Build Coastguard Worker Vec::iterator it; // scratch iterator
418*58b9f456SAndroid Build Coastguard Worker
419*58b9f456SAndroid Build Coastguard Worker // Check the size of the unique'd sequence.
420*58b9f456SAndroid Build Coastguard Worker // it should only be zero if the input sequence was empty.
421*58b9f456SAndroid Build Coastguard Worker if (results.size() == 0)
422*58b9f456SAndroid Build Coastguard Worker return working.size() == 0 ? 0 : 1;
423*58b9f456SAndroid Build Coastguard Worker
424*58b9f456SAndroid Build Coastguard Worker // 'results' is sorted
425*58b9f456SAndroid Build Coastguard Worker if (!std::is_sorted(results.begin(), results.end())) return 2;
426*58b9f456SAndroid Build Coastguard Worker
427*58b9f456SAndroid Build Coastguard Worker // All the elements in 'results' must be different
428*58b9f456SAndroid Build Coastguard Worker it = results.begin();
429*58b9f456SAndroid Build Coastguard Worker uint8_t prev_value = *it++;
430*58b9f456SAndroid Build Coastguard Worker for (; it != results.end(); ++it)
431*58b9f456SAndroid Build Coastguard Worker {
432*58b9f456SAndroid Build Coastguard Worker if (*it == prev_value) return 3;
433*58b9f456SAndroid Build Coastguard Worker prev_value = *it;
434*58b9f456SAndroid Build Coastguard Worker }
435*58b9f456SAndroid Build Coastguard Worker
436*58b9f456SAndroid Build Coastguard Worker // Every element in 'results' must be in 'working'
437*58b9f456SAndroid Build Coastguard Worker for (auto v : results)
438*58b9f456SAndroid Build Coastguard Worker if (std::find(working.begin(), working.end(), v) == working.end())
439*58b9f456SAndroid Build Coastguard Worker return 4;
440*58b9f456SAndroid Build Coastguard Worker
441*58b9f456SAndroid Build Coastguard Worker // Every element in 'working' must be in 'results'
442*58b9f456SAndroid Build Coastguard Worker for (auto v : working)
443*58b9f456SAndroid Build Coastguard Worker if (std::find(results.begin(), results.end(), v) == results.end())
444*58b9f456SAndroid Build Coastguard Worker return 5;
445*58b9f456SAndroid Build Coastguard Worker
446*58b9f456SAndroid Build Coastguard Worker return 0;
447*58b9f456SAndroid Build Coastguard Worker }
448*58b9f456SAndroid Build Coastguard Worker
449*58b9f456SAndroid Build Coastguard Worker
450*58b9f456SAndroid Build Coastguard Worker // -- regex fuzzers
regex_helper(const uint8_t * data,size_t size,std::regex::flag_type flag)451*58b9f456SAndroid Build Coastguard Worker static int regex_helper(const uint8_t *data, size_t size, std::regex::flag_type flag)
452*58b9f456SAndroid Build Coastguard Worker {
453*58b9f456SAndroid Build Coastguard Worker if (size > 0)
454*58b9f456SAndroid Build Coastguard Worker {
455*58b9f456SAndroid Build Coastguard Worker try
456*58b9f456SAndroid Build Coastguard Worker {
457*58b9f456SAndroid Build Coastguard Worker std::string s((const char *)data, size);
458*58b9f456SAndroid Build Coastguard Worker std::regex re(s, flag);
459*58b9f456SAndroid Build Coastguard Worker return std::regex_match(s, re) ? 1 : 0;
460*58b9f456SAndroid Build Coastguard Worker }
461*58b9f456SAndroid Build Coastguard Worker catch (std::regex_error &ex) {}
462*58b9f456SAndroid Build Coastguard Worker }
463*58b9f456SAndroid Build Coastguard Worker return 0;
464*58b9f456SAndroid Build Coastguard Worker }
465*58b9f456SAndroid Build Coastguard Worker
466*58b9f456SAndroid Build Coastguard Worker
regex_ECMAScript(const uint8_t * data,size_t size)467*58b9f456SAndroid Build Coastguard Worker int regex_ECMAScript (const uint8_t *data, size_t size)
468*58b9f456SAndroid Build Coastguard Worker {
469*58b9f456SAndroid Build Coastguard Worker (void) regex_helper(data, size, std::regex_constants::ECMAScript);
470*58b9f456SAndroid Build Coastguard Worker return 0;
471*58b9f456SAndroid Build Coastguard Worker }
472*58b9f456SAndroid Build Coastguard Worker
regex_POSIX(const uint8_t * data,size_t size)473*58b9f456SAndroid Build Coastguard Worker int regex_POSIX (const uint8_t *data, size_t size)
474*58b9f456SAndroid Build Coastguard Worker {
475*58b9f456SAndroid Build Coastguard Worker (void) regex_helper(data, size, std::regex_constants::basic);
476*58b9f456SAndroid Build Coastguard Worker return 0;
477*58b9f456SAndroid Build Coastguard Worker }
478*58b9f456SAndroid Build Coastguard Worker
regex_extended(const uint8_t * data,size_t size)479*58b9f456SAndroid Build Coastguard Worker int regex_extended (const uint8_t *data, size_t size)
480*58b9f456SAndroid Build Coastguard Worker {
481*58b9f456SAndroid Build Coastguard Worker (void) regex_helper(data, size, std::regex_constants::extended);
482*58b9f456SAndroid Build Coastguard Worker return 0;
483*58b9f456SAndroid Build Coastguard Worker }
484*58b9f456SAndroid Build Coastguard Worker
regex_awk(const uint8_t * data,size_t size)485*58b9f456SAndroid Build Coastguard Worker int regex_awk (const uint8_t *data, size_t size)
486*58b9f456SAndroid Build Coastguard Worker {
487*58b9f456SAndroid Build Coastguard Worker (void) regex_helper(data, size, std::regex_constants::awk);
488*58b9f456SAndroid Build Coastguard Worker return 0;
489*58b9f456SAndroid Build Coastguard Worker }
490*58b9f456SAndroid Build Coastguard Worker
regex_grep(const uint8_t * data,size_t size)491*58b9f456SAndroid Build Coastguard Worker int regex_grep (const uint8_t *data, size_t size)
492*58b9f456SAndroid Build Coastguard Worker {
493*58b9f456SAndroid Build Coastguard Worker (void) regex_helper(data, size, std::regex_constants::grep);
494*58b9f456SAndroid Build Coastguard Worker return 0;
495*58b9f456SAndroid Build Coastguard Worker }
496*58b9f456SAndroid Build Coastguard Worker
regex_egrep(const uint8_t * data,size_t size)497*58b9f456SAndroid Build Coastguard Worker int regex_egrep (const uint8_t *data, size_t size)
498*58b9f456SAndroid Build Coastguard Worker {
499*58b9f456SAndroid Build Coastguard Worker (void) regex_helper(data, size, std::regex_constants::egrep);
500*58b9f456SAndroid Build Coastguard Worker return 0;
501*58b9f456SAndroid Build Coastguard Worker }
502*58b9f456SAndroid Build Coastguard Worker
503*58b9f456SAndroid Build Coastguard Worker // -- heap fuzzers
make_heap(const uint8_t * data,size_t size)504*58b9f456SAndroid Build Coastguard Worker int make_heap (const uint8_t *data, size_t size)
505*58b9f456SAndroid Build Coastguard Worker {
506*58b9f456SAndroid Build Coastguard Worker Vec working(data, data + size);
507*58b9f456SAndroid Build Coastguard Worker std::make_heap(working.begin(), working.end());
508*58b9f456SAndroid Build Coastguard Worker
509*58b9f456SAndroid Build Coastguard Worker if (!std::is_heap(working.begin(), working.end())) return 1;
510*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
511*58b9f456SAndroid Build Coastguard Worker return 0;
512*58b9f456SAndroid Build Coastguard Worker }
513*58b9f456SAndroid Build Coastguard Worker
push_heap(const uint8_t * data,size_t size)514*58b9f456SAndroid Build Coastguard Worker int push_heap (const uint8_t *data, size_t size)
515*58b9f456SAndroid Build Coastguard Worker {
516*58b9f456SAndroid Build Coastguard Worker if (size < 2) return 0;
517*58b9f456SAndroid Build Coastguard Worker
518*58b9f456SAndroid Build Coastguard Worker // Make a heap from the first half of the data
519*58b9f456SAndroid Build Coastguard Worker Vec working(data, data + size);
520*58b9f456SAndroid Build Coastguard Worker auto iter = working.begin() + (size / 2);
521*58b9f456SAndroid Build Coastguard Worker std::make_heap(working.begin(), iter);
522*58b9f456SAndroid Build Coastguard Worker if (!std::is_heap(working.begin(), iter)) return 1;
523*58b9f456SAndroid Build Coastguard Worker
524*58b9f456SAndroid Build Coastguard Worker // Now push the rest onto the heap, one at a time
525*58b9f456SAndroid Build Coastguard Worker ++iter;
526*58b9f456SAndroid Build Coastguard Worker for (; iter != working.end(); ++iter) {
527*58b9f456SAndroid Build Coastguard Worker std::push_heap(working.begin(), iter);
528*58b9f456SAndroid Build Coastguard Worker if (!std::is_heap(working.begin(), iter)) return 2;
529*58b9f456SAndroid Build Coastguard Worker }
530*58b9f456SAndroid Build Coastguard Worker
531*58b9f456SAndroid Build Coastguard Worker if (!fuzzing::is_permutation(data, data + size, working.cbegin())) return 99;
532*58b9f456SAndroid Build Coastguard Worker return 0;
533*58b9f456SAndroid Build Coastguard Worker }
534*58b9f456SAndroid Build Coastguard Worker
pop_heap(const uint8_t * data,size_t size)535*58b9f456SAndroid Build Coastguard Worker int pop_heap (const uint8_t *data, size_t size)
536*58b9f456SAndroid Build Coastguard Worker {
537*58b9f456SAndroid Build Coastguard Worker if (size < 2) return 0;
538*58b9f456SAndroid Build Coastguard Worker Vec working(data, data + size);
539*58b9f456SAndroid Build Coastguard Worker std::make_heap(working.begin(), working.end());
540*58b9f456SAndroid Build Coastguard Worker
541*58b9f456SAndroid Build Coastguard Worker // Pop things off, one at a time
542*58b9f456SAndroid Build Coastguard Worker auto iter = --working.end();
543*58b9f456SAndroid Build Coastguard Worker while (iter != working.begin()) {
544*58b9f456SAndroid Build Coastguard Worker std::pop_heap(working.begin(), iter);
545*58b9f456SAndroid Build Coastguard Worker if (!std::is_heap(working.begin(), --iter)) return 2;
546*58b9f456SAndroid Build Coastguard Worker }
547*58b9f456SAndroid Build Coastguard Worker
548*58b9f456SAndroid Build Coastguard Worker return 0;
549*58b9f456SAndroid Build Coastguard Worker }
550*58b9f456SAndroid Build Coastguard Worker
551*58b9f456SAndroid Build Coastguard Worker
552*58b9f456SAndroid Build Coastguard Worker // -- search fuzzers
search(const uint8_t * data,size_t size)553*58b9f456SAndroid Build Coastguard Worker int search (const uint8_t *data, size_t size)
554*58b9f456SAndroid Build Coastguard Worker {
555*58b9f456SAndroid Build Coastguard Worker if (size < 2) return 0;
556*58b9f456SAndroid Build Coastguard Worker
557*58b9f456SAndroid Build Coastguard Worker const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
558*58b9f456SAndroid Build Coastguard Worker assert(pat_size <= size - 1);
559*58b9f456SAndroid Build Coastguard Worker const uint8_t *pat_begin = data + 1;
560*58b9f456SAndroid Build Coastguard Worker const uint8_t *pat_end = pat_begin + pat_size;
561*58b9f456SAndroid Build Coastguard Worker const uint8_t *data_end = data + size;
562*58b9f456SAndroid Build Coastguard Worker assert(pat_end <= data_end);
563*58b9f456SAndroid Build Coastguard Worker // std::cerr << "data[0] = " << size_t(data[0]) << " ";
564*58b9f456SAndroid Build Coastguard Worker // std::cerr << "Pattern size = " << pat_size << "; corpus is " << size - 1 << std::endl;
565*58b9f456SAndroid Build Coastguard Worker auto it = std::search(pat_end, data_end, pat_begin, pat_end);
566*58b9f456SAndroid Build Coastguard Worker if (it != data_end) // not found
567*58b9f456SAndroid Build Coastguard Worker if (!std::equal(pat_begin, pat_end, it))
568*58b9f456SAndroid Build Coastguard Worker return 1;
569*58b9f456SAndroid Build Coastguard Worker return 0;
570*58b9f456SAndroid Build Coastguard Worker }
571*58b9f456SAndroid Build Coastguard Worker
572*58b9f456SAndroid Build Coastguard Worker template <typename S>
search_helper(const uint8_t * data,size_t size)573*58b9f456SAndroid Build Coastguard Worker static int search_helper (const uint8_t *data, size_t size)
574*58b9f456SAndroid Build Coastguard Worker {
575*58b9f456SAndroid Build Coastguard Worker if (size < 2) return 0;
576*58b9f456SAndroid Build Coastguard Worker
577*58b9f456SAndroid Build Coastguard Worker const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
578*58b9f456SAndroid Build Coastguard Worker const uint8_t *pat_begin = data + 1;
579*58b9f456SAndroid Build Coastguard Worker const uint8_t *pat_end = pat_begin + pat_size;
580*58b9f456SAndroid Build Coastguard Worker const uint8_t *data_end = data + size;
581*58b9f456SAndroid Build Coastguard Worker
582*58b9f456SAndroid Build Coastguard Worker auto it = std::search(pat_end, data_end, S(pat_begin, pat_end));
583*58b9f456SAndroid Build Coastguard Worker if (it != data_end) // not found
584*58b9f456SAndroid Build Coastguard Worker if (!std::equal(pat_begin, pat_end, it))
585*58b9f456SAndroid Build Coastguard Worker return 1;
586*58b9f456SAndroid Build Coastguard Worker return 0;
587*58b9f456SAndroid Build Coastguard Worker }
588*58b9f456SAndroid Build Coastguard Worker
589*58b9f456SAndroid Build Coastguard Worker // These are still in std::experimental
590*58b9f456SAndroid Build Coastguard Worker // int search_boyer_moore (const uint8_t *data, size_t size)
591*58b9f456SAndroid Build Coastguard Worker // {
592*58b9f456SAndroid Build Coastguard Worker // return search_helper<std::boyer_moore_searcher<const uint8_t *>>(data, size);
593*58b9f456SAndroid Build Coastguard Worker // }
594*58b9f456SAndroid Build Coastguard Worker //
595*58b9f456SAndroid Build Coastguard Worker // int search_boyer_moore_horspool (const uint8_t *data, size_t size)
596*58b9f456SAndroid Build Coastguard Worker // {
597*58b9f456SAndroid Build Coastguard Worker // return search_helper<std::boyer_moore_horspool_searcher<const uint8_t *>>(data, size);
598*58b9f456SAndroid Build Coastguard Worker // }
599*58b9f456SAndroid Build Coastguard Worker
600*58b9f456SAndroid Build Coastguard Worker
601*58b9f456SAndroid Build Coastguard Worker // -- set operation fuzzers
602*58b9f456SAndroid Build Coastguard Worker template <typename S>
set_helper(const uint8_t * data,size_t size,Vec & v1,Vec & v2)603*58b9f456SAndroid Build Coastguard Worker static void set_helper (const uint8_t *data, size_t size, Vec &v1, Vec &v2)
604*58b9f456SAndroid Build Coastguard Worker {
605*58b9f456SAndroid Build Coastguard Worker assert(size > 1);
606*58b9f456SAndroid Build Coastguard Worker
607*58b9f456SAndroid Build Coastguard Worker const size_t pat_size = data[0] * (size - 1) / std::numeric_limits<uint8_t>::max();
608*58b9f456SAndroid Build Coastguard Worker const uint8_t *pat_begin = data + 1;
609*58b9f456SAndroid Build Coastguard Worker const uint8_t *pat_end = pat_begin + pat_size;
610*58b9f456SAndroid Build Coastguard Worker const uint8_t *data_end = data + size;
611*58b9f456SAndroid Build Coastguard Worker v1.assign(pat_begin, pat_end);
612*58b9f456SAndroid Build Coastguard Worker v2.assign(pat_end, data_end);
613*58b9f456SAndroid Build Coastguard Worker
614*58b9f456SAndroid Build Coastguard Worker std::sort(v1.begin(), v1.end());
615*58b9f456SAndroid Build Coastguard Worker std::sort(v2.begin(), v2.end());
616*58b9f456SAndroid Build Coastguard Worker }
617*58b9f456SAndroid Build Coastguard Worker
618*58b9f456SAndroid Build Coastguard Worker } // namespace fuzzing
619