82 lines · cpp
1//===-- uint_fuzz.cpp -----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// Fuzzing test for llvm-libc unsigned integer utilities.10///11//===----------------------------------------------------------------------===//12#include "src/__support/CPP/bit.h"13#include "src/__support/big_int.h"14#include "src/string/memory_utils/inline_memcpy.h"15 16using namespace LIBC_NAMESPACE;17 18// Helper function when using gdb / lldb to set a breakpoint and inspect values.19template <typename T> void debug_and_trap(const char *msg, T a, T b) {20 __builtin_trap();21}22 23#define DEBUG_AND_TRAP()24 25#define TEST_BINOP(OP) \26 if ((a OP b) != (static_cast<T>(BigInt(a) OP BigInt(b)))) \27 debug_and_trap(#OP, a, b);28 29#define TEST_SHIFTOP(OP) \30 if ((a OP b) != (static_cast<T>(BigInt(a) OP b))) \31 debug_and_trap(#OP, a, b);32 33#define TEST_FUNCTION(FUN) \34 if (FUN(a) != FUN(BigInt(a))) \35 debug_and_trap(#FUN, a, b);36 37// Test that basic arithmetic operations of BigInt behave like their scalar38// counterparts.39template <typename T, typename BigInt> void run_tests(T a, T b) {40 TEST_BINOP(+)41 TEST_BINOP(-)42 TEST_BINOP(*)43 if (b != 0)44 TEST_BINOP(/)45 if (b >= 0 && b < cpp::numeric_limits<T>::digits) {46 TEST_SHIFTOP(<<)47 TEST_SHIFTOP(>>)48 }49 if constexpr (!BigInt::SIGNED) {50 TEST_FUNCTION(cpp::has_single_bit)51 TEST_FUNCTION(cpp::countr_zero)52 TEST_FUNCTION(cpp::countl_zero)53 TEST_FUNCTION(cpp::countl_one)54 TEST_FUNCTION(cpp::countr_one)55 }56}57 58// Reads a T from libfuzzer data.59template <typename T> T read(const uint8_t *data, size_t &remainder) {60 T out = 0;61 constexpr size_t T_SIZE = sizeof(T);62 const size_t copy_size = remainder < T_SIZE ? remainder : T_SIZE;63 inline_memcpy(&out, data, copy_size);64 remainder -= copy_size;65 return out;66}67 68template <typename T, typename BigInt>69void run_tests(const uint8_t *data, size_t size) {70 const auto a = read<T>(data, size);71 const auto b = read<T>(data, size);72 run_tests<T, BigInt>(a, b);73}74 75extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {76 // unsigned77 run_tests<uint64_t, BigInt<64, false, uint16_t>>(data, size);78 // signed79 run_tests<int64_t, BigInt<64, true, uint16_t>>(data, size);80 return 0;81}82