//===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // This test fails because Clang no longer enables -fdelayed-template-parsing // by default on Windows with C++20 (#69431). // XFAIL: msvc && (clang-18 || clang-19 || clang-20) // UNSUPPORTED: c++03, c++11 #include #include #include #include #include #include #include #include #include "fuzz.h" template std::vector GetValues(const std::uint8_t *data, std::size_t size) { std::vector result; while (size >= sizeof(IntT)) { IntT tmp; std::memcpy(&tmp, data, sizeof(IntT)); size -= sizeof(IntT); data += sizeof(IntT); result.push_back(tmp); } return result; } template struct ParamTypeHelper { using ParamT = typename Dist::param_type; using ResultT = typename Dist::result_type; static_assert(std::is_same::value, ""); static ParamT Create(const std::uint8_t* data, std::size_t size, bool &OK) { constexpr bool select_vector_result = std::is_constructible::value; constexpr bool select_vector_double = std::is_constructible::value; constexpr int selector = select_vector_result ? 0 : (select_vector_double ? 1 : 2); return DispatchAndCreate(std::integral_constant{}, data, size, OK); } // Vector result static ParamT DispatchAndCreate(std::integral_constant, const std::uint8_t *data, std::size_t size, bool &OK) { auto Input = GetValues(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; } // Vector double static ParamT DispatchAndCreate(std::integral_constant, const std::uint8_t *data, std::size_t size, bool &OK) { auto Input = GetValues(data, size); OK = true; auto Beg = Input.begin(); auto End = Input.end(); ParamT p(Beg, End); return p; } // Default static ParamT DispatchAndCreate(std::integral_constant, const std::uint8_t *data, std::size_t size, bool &OK) { OK = false; if (size < sizeof(ParamT)) return ParamT{}; OK = true; ParamT input; std::memcpy(&input, data, sizeof(ParamT)); return input; } }; template struct ParamTypeHelper> { using Dist = std::poisson_distribution; using ParamT = typename Dist::param_type; using ResultT = typename Dist::result_type; static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) { OK = false; auto vals = GetValues(data, size); if (vals.empty() || std::isnan(vals[0]) || std::isnan(std::abs(vals[0])) || vals[0] < 0) return ParamT{}; OK = true; return ParamT{vals[0]}; } }; template struct ParamTypeHelper> { using Dist = std::geometric_distribution; using ParamT = typename Dist::param_type; using ResultT = typename Dist::result_type; static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) { OK = false; auto vals = GetValues(data, size); if (vals.empty() || std::isnan(vals[0]) || vals[0] < 0 ) return ParamT{}; OK = true; return ParamT{vals[0]}; } }; template struct ParamTypeHelper> { using Dist = std::lognormal_distribution; using ParamT = typename Dist::param_type; using ResultT = typename Dist::result_type; static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) { OK = false; auto vals = GetValues(data, size); if (vals.size() < 2 ) return ParamT{}; OK = true; return ParamT{vals[0], vals[1]}; } }; template <> struct ParamTypeHelper { using Dist = std::bernoulli_distribution; using ParamT = Dist::param_type; using ResultT = Dist::result_type; static ParamT Create(const std::uint8_t *data, std::size_t size, bool& OK) { OK = false; auto vals = GetValues(data, size); if (vals.empty()) return ParamT{}; OK = true; return ParamT{vals[0]}; } }; template int helper(const std::uint8_t *data, std::size_t size) { std::mt19937 engine; using ParamT = typename Distribution::param_type; bool OK; ParamT p = ParamTypeHelper::Create(data, size, OK); if (!OK) return 0; Distribution d(p); volatile auto res = d(engine); if (std::isnan(res)) { // FIXME(llvm.org/PR44289): // Investigate why these distributions are returning NaN and decide // if that's what we want them to be doing. // // Make this assert false (or return non-zero). return 0; } return 0; } extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t *data, std::size_t size) { return helper>(data, size) || helper>(data, size) || helper(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size) || helper>(data, size); }