| #include <cstdint> |
| #include <cstring> |
| #include <limits> |
| |
| #include "libdivide.h" |
| |
| constexpr const std::size_t Nmax = 8; |
| |
| template <typename Integer> |
| void applyOnScalars(const uint8_t* Data, size_t Size) { |
| const auto N = sizeof(Integer); |
| static_assert(N <= Nmax, ""); |
| if (Size < 2 * Nmax) return; |
| |
| Integer numerator, divisor; |
| std::memcpy(&numerator, Data, N); |
| Data += Nmax; |
| std::memcpy(&divisor, Data, N); |
| |
| // avoid division by zero |
| if (divisor == 0) { |
| return; |
| } |
| |
| // avoid signed integer overflow INT_MIN/-1 |
| if (std::is_signed_v<Integer> && |
| (numerator == std::numeric_limits<Integer>::min() && divisor == -1)) { |
| return; |
| } |
| |
| libdivide::divider<Integer, libdivide::BRANCHFULL> fast_d_branchfull(divisor); |
| const auto quotient_full = numerator / fast_d_branchfull; |
| |
| if (quotient_full != numerator / divisor) { |
| abort(); |
| } |
| |
| if (divisor != 1) { |
| libdivide::divider<Integer, libdivide::BRANCHFREE> fast_d_branchfree(divisor); |
| |
| const auto quotient_free = numerator / fast_d_branchfree; |
| |
| if (quotient_free != numerator / divisor) { |
| abort(); |
| } |
| } |
| } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { |
| if (Size < Nmax) return 0; |
| auto action = Data[0]; |
| ++Data; |
| --Size; |
| |
| switch (action) { |
| case 0: { |
| applyOnScalars<std::int64_t>(Data, Size); |
| } break; |
| case 1: { |
| applyOnScalars<std::int32_t>(Data, Size); |
| } break; |
| case 2: { |
| applyOnScalars<std::uint64_t>(Data, Size); |
| } break; |
| case 3: { |
| applyOnScalars<std::uint32_t>(Data, Size); |
| } break; |
| } |
| return 0; |
| } |