xref: /aosp_15_r20/external/libcxx/fuzzing/fuzzing.cpp (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
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