blob: a045e264bec2a478474e2557f4e6927443fe6ee6 [file] [log] [blame]
#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;
}