summaryrefslogtreecommitdiffstats
path: root/libcxx/fuzzing
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/fuzzing')
-rw-r--r--libcxx/fuzzing/RoutineNames.txt20
-rw-r--r--libcxx/fuzzing/fuzz_test_template.cpp22
-rw-r--r--libcxx/fuzzing/fuzzing.cpp205
-rw-r--r--libcxx/fuzzing/fuzzing.h22
4 files changed, 268 insertions, 1 deletions
diff --git a/libcxx/fuzzing/RoutineNames.txt b/libcxx/fuzzing/RoutineNames.txt
index 06ef70ed649..a853c87e1f7 100644
--- a/libcxx/fuzzing/RoutineNames.txt
+++ b/libcxx/fuzzing/RoutineNames.txt
@@ -18,3 +18,23 @@ regex_awk
regex_grep
regex_egrep
search
+uniform_int_distribution
+uniform_real_distribution
+bernoulli_distribution
+poisson_distribution
+geometric_distribution
+binomial_distribution
+negative_binomial_distribution
+exponential_distribution
+gamma_distribution
+weibull_distribution
+extreme_value_distribution
+normal_distribution
+lognormal_distribution
+chi_squared_distribution
+cauchy_distribution
+fisher_f_distribution
+student_t_distribution
+discrete_distribution
+piecewise_constant_distribution
+piecewise_linear_distribution
diff --git a/libcxx/fuzzing/fuzz_test_template.cpp b/libcxx/fuzzing/fuzz_test_template.cpp
new file mode 100644
index 00000000000..ba44eef7891
--- /dev/null
+++ b/libcxx/fuzzing/fuzz_test_template.cpp
@@ -0,0 +1,22 @@
+//===------------------------- fuzz_test.cpp ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "fuzzing/fuzzing.h"
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+#include <cassert>
+
+#ifndef TEST_FUNCTION
+#error TEST_FUNCTION must be defined
+#endif
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ int result = fuzzing::TEST_FUNCTION(data, size);
+ assert(result == 0); return 0;
+}
diff --git a/libcxx/fuzzing/fuzzing.cpp b/libcxx/fuzzing/fuzzing.cpp
index 5c32f28a3ad..284993918aa 100644
--- a/libcxx/fuzzing/fuzzing.cpp
+++ b/libcxx/fuzzing/fuzzing.cpp
@@ -27,10 +27,16 @@
#include <algorithm>
#include <functional>
#include <regex>
+#include <random>
#include <cassert>
+#include <cmath>
#include <iostream>
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+#include <cassert>
// If we had C++14, we could use the four iterator version of is_permutation and equal
namespace fuzzing {
@@ -212,7 +218,7 @@ int partition_copy(const uint8_t *data, size_t size)
auto iter = std::partition_copy(data, data + size,
std::back_inserter<Vec>(v1), std::back_inserter<Vec>(v2),
is_even<uint8_t>());
-
+ ((void)iter);
// The two vectors should add up to the original size
if (v1.size() + v2.size() != size) return 1;
@@ -614,4 +620,201 @@ static void set_helper (const uint8_t *data, size_t size, Vec &v1, Vec &v2)
std::sort(v2.begin(), v2.end());
}
+enum class ParamKind {
+ OneValue,
+ TwoValues,
+ PointerRange
+};
+
+template <class IntT>
+std::vector<IntT> GetValues(const uint8_t *data, size_t size) {
+ std::vector<IntT> result;
+ while (size >= sizeof(IntT)) {
+ IntT tmp;
+ memcpy(&tmp, data, sizeof(IntT));
+ size -= sizeof(IntT);
+ data += sizeof(IntT);
+ result.push_back(tmp);
+ }
+ return result;
+}
+
+enum InitKind {
+ Default,
+ DoubleOnly,
+ VectorDouble,
+ VectorResultType
+};
+
+template <class Dist>
+struct ParamTypeHelper {
+ using ParamT = typename Dist::param_type;
+ using ResultT = typename Dist::result_type;
+ static_assert(std::is_same<ResultT, typename ParamT::distribution_type::result_type>::value, "");
+ static ParamT Create(const uint8_t* data, size_t size, bool &OK) {
+
+ if constexpr (std::is_constructible<ParamT, ResultT*, ResultT*, ResultT*>::value)
+ return CreateVectorResult(data, size, OK);
+ else if constexpr (std::is_constructible<ParamT, double*, double*>::value)
+ return CreateVectorDouble(data, size, OK);
+ else
+ return CreateDefault(data, size, OK);
+ }
+
+
+static ParamT
+CreateVectorResult(const uint8_t *data, size_t size, bool &OK) {
+ auto Input = GetValues<ResultT>(data, size);
+ OK = false;
+ if (Input.size() < 10)
+ return ParamT{};
+ OK = true;
+ auto Beg = Input.begin();
+ auto End = Input.end();
+ auto Mid = Beg + ((End - Beg) / 2);
+
+ assert(Mid - Beg <= (End - Mid));
+ ParamT p(Beg, Mid, Mid);
+ return p;
+}
+
+ static ParamT
+ CreateVectorDouble(const uint8_t *data, size_t size, bool &OK) {
+ auto Input = GetValues<double>(data, size);
+
+ OK = true;
+ auto Beg = Input.begin();
+ auto End = Input.end();
+
+ ParamT p(Beg, End);
+ return p;
+ }
+
+
+ static ParamT
+ CreateDefault(const uint8_t *data, size_t size, bool &OK) {
+ OK = false;
+ if (size < sizeof(ParamT))
+ return ParamT{};
+ OK = true;
+ ParamT input;
+ memcpy(&input, data, sizeof(ParamT));
+ return input;
+ }
+
+};
+
+
+
+
+template <class IntT>
+struct ParamTypeHelper<std::poisson_distribution<IntT>> {
+ using Dist = std::poisson_distribution<IntT>;
+ using ParamT = typename Dist::param_type;
+ using ResultT = typename Dist::result_type;
+
+ static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
+ OK = false;
+ auto vals = GetValues<double>(data, size);
+ if (vals.empty() || std::isnan(vals[0]) || std::isnan(std::abs(vals[0])) || vals[0] < 0 )
+ return ParamT{};
+ OK = true;
+ //std::cerr << "Value: " << vals[0] << std::endl;
+ return ParamT{vals[0]};
+ }
+};
+
+
+template <class IntT>
+struct ParamTypeHelper<std::geometric_distribution<IntT>> {
+ using Dist = std::geometric_distribution<IntT>;
+ using ParamT = typename Dist::param_type;
+ using ResultT = typename Dist::result_type;
+
+ static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
+ OK = false;
+ auto vals = GetValues<double>(data, size);
+ if (vals.empty() || std::isnan(vals[0]) || vals[0] < 0 )
+ return ParamT{};
+ OK = true;
+ // std::cerr << "Value: " << vals[0] << std::endl;
+ return ParamT{vals[0]};
+ }
+};
+
+
+template <class IntT>
+struct ParamTypeHelper<std::lognormal_distribution<IntT>> {
+ using Dist = std::lognormal_distribution<IntT>;
+ using ParamT = typename Dist::param_type;
+ using ResultT = typename Dist::result_type;
+
+ static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
+ OK = false;
+ auto vals = GetValues<ResultT>(data, size);
+ if (vals.size() < 2 )
+ return ParamT{};
+ OK = true;
+ return ParamT{vals[0], vals[1]};
+ }
+};
+
+
+template <>
+struct ParamTypeHelper<std::bernoulli_distribution> {
+ using Dist = std::bernoulli_distribution;
+ using ParamT = typename Dist::param_type;
+ using ResultT = typename Dist::result_type;
+
+ static ParamT Create(const uint8_t *data, size_t size, bool& OK) {
+ OK = false;
+ auto vals = GetValues<double>(data, size);
+ if (vals.empty())
+ return ParamT{};
+ OK = true;
+ return ParamT{vals[0]};
+ }
+};
+
+template <class Distribution>
+int random_distribution_helper(const uint8_t *data, size_t size) {
+
+ std::mt19937 engine;
+ using ParamT = typename Distribution::param_type;
+ bool OK;
+ ParamT p = ParamTypeHelper<Distribution>::Create(data, size, OK);
+ if (!OK)
+ return 0;
+ Distribution d(p);
+ volatile auto res = d(engine);
+ if (std::isnan(res))
+ return 1;
+ return 0;
+}
+
+#define DEFINE_RANDOM_TEST(name, ...) \
+int name(const uint8_t *data, size_t size) { \
+ return random_distribution_helper< std::name __VA_ARGS__ >(data, size); \
+}
+DEFINE_RANDOM_TEST(uniform_int_distribution,<std::int16_t>)
+DEFINE_RANDOM_TEST(uniform_real_distribution,<float>)
+DEFINE_RANDOM_TEST(bernoulli_distribution)
+DEFINE_RANDOM_TEST(poisson_distribution,<std::int16_t>)
+DEFINE_RANDOM_TEST(geometric_distribution,<std::int16_t>)
+DEFINE_RANDOM_TEST(binomial_distribution, <std::int16_t>)
+DEFINE_RANDOM_TEST(negative_binomial_distribution, <std::int16_t>)
+DEFINE_RANDOM_TEST(exponential_distribution, <float>)
+DEFINE_RANDOM_TEST(gamma_distribution, <float>)
+DEFINE_RANDOM_TEST(weibull_distribution, <float>)
+DEFINE_RANDOM_TEST(extreme_value_distribution, <float>)
+DEFINE_RANDOM_TEST(normal_distribution, <float>)
+DEFINE_RANDOM_TEST(lognormal_distribution, <float>)
+DEFINE_RANDOM_TEST(chi_squared_distribution, <float>)
+DEFINE_RANDOM_TEST(cauchy_distribution, <float>)
+DEFINE_RANDOM_TEST(fisher_f_distribution, <float>)
+DEFINE_RANDOM_TEST(student_t_distribution, <float>)
+DEFINE_RANDOM_TEST(discrete_distribution, <std::int16_t>)
+DEFINE_RANDOM_TEST(piecewise_constant_distribution, <float>)
+DEFINE_RANDOM_TEST(piecewise_linear_distribution, <float>)
+
} // namespace fuzzing
diff --git a/libcxx/fuzzing/fuzzing.h b/libcxx/fuzzing/fuzzing.h
index 64103e59007..99a3aa14a77 100644
--- a/libcxx/fuzzing/fuzzing.h
+++ b/libcxx/fuzzing/fuzzing.h
@@ -56,6 +56,28 @@ namespace fuzzing {
// int set_symmetric_difference (const uint8_t *data, size_t size);
// int merge (const uint8_t *data, size_t size);
+// Random numbers
+ int uniform_int_distribution(const uint8_t*, size_t);
+ int uniform_real_distribution(const uint8_t*, size_t);
+ int bernoulli_distribution(const uint8_t*, size_t);
+ int poisson_distribution(const uint8_t*, size_t);
+ int geometric_distribution(const uint8_t*, size_t);
+ int binomial_distribution(const uint8_t*, size_t);
+ int negative_binomial_distribution(const uint8_t*, size_t);
+ int exponential_distribution(const uint8_t*, size_t);
+ int gamma_distribution(const uint8_t*, size_t);
+ int weibull_distribution(const uint8_t*, size_t);
+ int extreme_value_distribution(const uint8_t*, size_t);
+ int normal_distribution(const uint8_t*, size_t);
+ int lognormal_distribution(const uint8_t*, size_t);
+ int chi_squared_distribution(const uint8_t*, size_t);
+ int cauchy_distribution(const uint8_t*, size_t);
+ int fisher_f_distribution(const uint8_t*, size_t);
+ int student_t_distribution(const uint8_t*, size_t);
+ int discrete_distribution(const uint8_t*, size_t);
+ int piecewise_constant_distribution(const uint8_t*, size_t);
+ int piecewise_linear_distribution(const uint8_t*, size_t);
+
} // namespace fuzzing
#endif // _LIBCPP_FUZZING
OpenPOWER on IntegriCloud