• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  (C) Copyright Marshall Clow 2018
2 //  Use, modification and distribution are subject to the
3 //  Boost Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <iterator> // for std::distance
7 #include <cassert>  // for assert
8 
9 #include <boost/algorithm/minmax_element.hpp>
10 #include <boost/algorithm/cxx11/none_of.hpp>
11 
12 //	Fuzzing tests for:
13 //
14 //		template <class ForwardIterator>
15 //		std::pair<ForwardIterator,ForwardIterator>
16 //		first_min_first_max_element(ForwardIterator first, ForwardIterator last);
17 //
18 //		template <class ForwardIterator, class BinaryPredicate>
19 //		std::pair<ForwardIterator,ForwardIterator>
20 //		first_min_first_max_element(ForwardIterator first, ForwardIterator last,
21 //	               		BinaryPredicate comp);
22 //
23 //	identical signatures for:
24 //		first_min_last_max_element
25 //		last_min_first_max_element
26 //		last_min_last_max_element
27 
greater(uint8_t lhs,uint8_t rhs)28 bool greater(uint8_t lhs, uint8_t rhs) { return lhs > rhs; }
29 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t sz)30 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) {
31 	typedef std::pair<const uint8_t *, const uint8_t *> result_t;
32 	const uint8_t * const dend = data + sz;
33 	if (sz == 0) return 0; // we need at least one element
34 
35 	{
36 //	Find the min and max
37 	result_t resultff = boost::first_min_first_max_element(data, dend);
38 	result_t resultfl = boost::first_min_last_max_element (data, dend);
39 	result_t resultlf = boost::last_min_first_max_element (data, dend);
40 	result_t resultll = boost::last_min_last_max_element  (data, dend);
41 
42 //	The iterators have to be in the sequence - and not at the end!
43 	assert(std::distance(data, resultff.first)  < sz);
44 	assert(std::distance(data, resultff.second) < sz);
45 	assert(std::distance(data, resultfl.first)  < sz);
46 	assert(std::distance(data, resultfl.second) < sz);
47 	assert(std::distance(data, resultlf.first)  < sz);
48 	assert(std::distance(data, resultlf.second) < sz);
49 	assert(std::distance(data, resultll.first)  < sz);
50 	assert(std::distance(data, resultll.second) < sz);
51 
52 //	the minimum element can't be bigger than the max element
53 
54 //	Did we find the same min value and max value?
55 	uint8_t min_value = *resultff.first;
56 	uint8_t max_value = *resultff.second;
57 	assert(min_value <= max_value);
58 
59 //	Each variant should have found the same min/max values
60 	assert(*resultff.first  == min_value);
61 	assert(*resultfl.first  == min_value);
62 	assert(*resultlf.first  == min_value);
63 	assert(*resultll.first  == min_value);
64 
65 	assert(*resultff.second == max_value);
66 	assert(*resultfl.second == max_value);
67 	assert(*resultlf.second == max_value);
68 	assert(*resultll.second == max_value);
69 
70 //	None of the elements in the sequence can be less than the min, nor greater than the max
71 	for (size_t i = 0; i < sz; ++i) {
72 		assert(min_value <= data[i]);
73 		assert(data[i] <= max_value);
74 		}
75 
76 //	Make sure we returned the "right" first and last element
77 	assert(boost::algorithm::none_of_equal(data, resultff.first,     min_value));
78 	assert(boost::algorithm::none_of_equal(data, resultfl.first,     min_value));
79 	assert(boost::algorithm::none_of_equal(resultlf.first + 1, dend, min_value));
80 	assert(boost::algorithm::none_of_equal(resultll.first + 1, dend, min_value));
81 
82 	assert(boost::algorithm::none_of_equal(data, resultff.second,     max_value));
83 	assert(boost::algorithm::none_of_equal(resultfl.second + 1, dend, max_value));
84 	assert(boost::algorithm::none_of_equal(data, resultlf.second,     max_value));
85 	assert(boost::algorithm::none_of_equal(resultll.second + 1, dend, max_value));
86 	}
87 
88 	{
89 //	Find the min and max
90 	result_t resultff = boost::first_min_first_max_element(data, dend, greater);
91 	result_t resultfl = boost::first_min_last_max_element (data, dend, greater);
92 	result_t resultlf = boost::last_min_first_max_element (data, dend, greater);
93 	result_t resultll = boost::last_min_last_max_element  (data, dend, greater);
94 
95 //	The iterators have to be in the sequence - and not at the end!
96 	assert(std::distance(data, resultff.first)  < sz);
97 	assert(std::distance(data, resultff.second) < sz);
98 	assert(std::distance(data, resultfl.first)  < sz);
99 	assert(std::distance(data, resultfl.second) < sz);
100 	assert(std::distance(data, resultlf.first)  < sz);
101 	assert(std::distance(data, resultlf.second) < sz);
102 	assert(std::distance(data, resultll.first)  < sz);
103 	assert(std::distance(data, resultll.second) < sz);
104 
105 //	the minimum element can't be bigger than the max element
106 	uint8_t min_value = *resultff.first;
107 	uint8_t max_value = *resultff.second;
108 
109 	assert (!greater(max_value, min_value));
110 
111 //	Each variant should have found the same min/max values
112 	assert(*resultff.first  == min_value);
113 	assert(*resultfl.first  == min_value);
114 	assert(*resultlf.first  == min_value);
115 	assert(*resultll.first  == min_value);
116 
117 	assert(*resultff.second == max_value);
118 	assert(*resultfl.second == max_value);
119 	assert(*resultlf.second == max_value);
120 	assert(*resultll.second == max_value);
121 
122 //	None of the elements in the sequence can be less than the min, nor greater than the max
123 	for (size_t i = 0; i < sz; ++i) {
124 		assert(!greater(data[i], min_value));
125 		assert(!greater(max_value, data[i]));
126 		}
127 
128 //	We returned the first min element, and the first max element
129 	assert(boost::algorithm::none_of_equal(data, resultff.first,     min_value));
130 	assert(boost::algorithm::none_of_equal(data, resultfl.first,     min_value));
131 	assert(boost::algorithm::none_of_equal(resultlf.first + 1, dend, min_value));
132 	assert(boost::algorithm::none_of_equal(resultll.first + 1, dend, min_value));
133 
134 	assert(boost::algorithm::none_of_equal(data, resultff.second,     max_value));
135 	assert(boost::algorithm::none_of_equal(resultfl.second + 1, dend, max_value));
136 	assert(boost::algorithm::none_of_equal(data, resultlf.second,     max_value));
137 	assert(boost::algorithm::none_of_equal(resultll.second + 1, dend, max_value));
138 	}
139 
140   return 0;
141 }
142