diff --git a/libc/fuzzing/CMakeLists.txt b/libc/fuzzing/CMakeLists.txt index 1b950ad9b721c..5d8922bcc22b0 100644 --- a/libc/fuzzing/CMakeLists.txt +++ b/libc/fuzzing/CMakeLists.txt @@ -2,4 +2,5 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer") add_custom_target(libc-fuzzer) add_dependencies(check-libc libc-fuzzer) +add_subdirectory(math) add_subdirectory(string) diff --git a/libc/fuzzing/math/CMakeLists.txt b/libc/fuzzing/math/CMakeLists.txt new file mode 100644 index 0000000000000..147e2c70733dd --- /dev/null +++ b/libc/fuzzing/math/CMakeLists.txt @@ -0,0 +1,65 @@ +add_libc_fuzzer( + ldexp_differential_fuzz + SRCS + ldexp_differential_fuzz.cpp + HDRS + LdExpDiff.h + DEPENDS + libc.src.math.ldexp + libc.utils.FPUtil.fputil +) + +add_libc_fuzzer( + ldexpf_differential_fuzz + SRCS + ldexpf_differential_fuzz.cpp + HDRS + LdExpDiff.h + DEPENDS + libc.src.math.ldexpf + libc.utils.FPUtil.fputil +) + +add_libc_fuzzer( + ldexpl_differential_fuzz + SRCS + ldexpl_differential_fuzz.cpp + HDRS + LdExpDiff.h + DEPENDS + libc.src.math.ldexpl + libc.utils.FPUtil.fputil +) + +add_libc_fuzzer( + remquo_differential_fuzz + SRCS + remquo_differential_fuzz.cpp + HDRS + RemQuoDiff.h + DEPENDS + libc.src.math.remquo + libc.utils.FPUtil.fputil +) + +add_libc_fuzzer( + remquof_differential_fuzz + SRCS + remquof_differential_fuzz.cpp + HDRS + RemQuoDiff.h + DEPENDS + libc.src.math.remquof + libc.utils.FPUtil.fputil +) + +add_libc_fuzzer( + remquol_differential_fuzz + SRCS + remquol_differential_fuzz.cpp + HDRS + RemQuoDiff.h + DEPENDS + libc.src.math.remquol + libc.utils.FPUtil.fputil +) diff --git a/libc/fuzzing/math/LdExpDiff.h b/libc/fuzzing/math/LdExpDiff.h new file mode 100644 index 0000000000000..403429ff5c717 --- /dev/null +++ b/libc/fuzzing/math/LdExpDiff.h @@ -0,0 +1,44 @@ +//===-- Template for diffing ldexp results ----------------------*- C++ -*-===// +// +// 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 "utils/FPUtil/FPBits.h" + +#include +#include +#include + +template using LdExpFunc = T (*)(T, int); + +template +void LdExpDiff(LdExpFunc func1, LdExpFunc func2, const uint8_t *data, + size_t size) { + constexpr size_t typeSize = sizeof(T); + if (size < typeSize + sizeof(int)) + return; + + T x = *reinterpret_cast(data); + T i = *reinterpret_cast(data + typeSize); + + T result1 = func1(x, i); + T result2 = func2(x, i); + if (isnan(result1)) { + if (!isnan(result2)) + __builtin_trap(); + return; + } + if (isinf(result1)) { + if (isinf(result2) != isinf(result1)) + __builtin_trap(); + return; + } + + __llvm_libc::fputil::FPBits bits1(result1); + __llvm_libc::fputil::FPBits bits2(result2); + if (bits1.bitsAsUInt() != bits2.bitsAsUInt()) + __builtin_trap(); +} diff --git a/libc/fuzzing/math/RemQuoDiff.h b/libc/fuzzing/math/RemQuoDiff.h new file mode 100644 index 0000000000000..c0091a4f65dea --- /dev/null +++ b/libc/fuzzing/math/RemQuoDiff.h @@ -0,0 +1,50 @@ +//===-- Template for diffing remquo results ---------------------*- C++ -*-===// +// +// 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 "utils/FPUtil/FPBits.h" + +#include +#include +#include + +template using RemQuoFunc = T (*)(T, T, int *); + +template +void RemQuoDiff(RemQuoFunc func1, RemQuoFunc func2, const uint8_t *data, + size_t size) { + constexpr size_t typeSize = sizeof(T); + if (size < 2 * typeSize) + return; + + T x = *reinterpret_cast(data); + T y = *reinterpret_cast(data + typeSize); + + int q1, q2; + T remainder1 = func1(x, y, &q1); + T remainder2 = func2(x, y, &q2); + + if (isnan(remainder1)) { + if (!isnan(remainder2)) + __builtin_trap(); + return; + } + if (isinf(remainder1)) { + if (isinf(remainder2) != isinf(remainder1)) + __builtin_trap(); + return; + } + + // Compare only the 3 LS bits of the quotient. + if ((q1 & 0x7) != (q2 & 0x7)) + __builtin_trap(); + + __llvm_libc::fputil::FPBits bits1(remainder1); + __llvm_libc::fputil::FPBits bits2(remainder2); + if (bits1.bitsAsUInt() != bits2.bitsAsUInt()) + __builtin_trap(); +} diff --git a/libc/fuzzing/math/ldexp_differential_fuzz.cpp b/libc/fuzzing/math/ldexp_differential_fuzz.cpp new file mode 100644 index 0000000000000..573625f21481b --- /dev/null +++ b/libc/fuzzing/math/ldexp_differential_fuzz.cpp @@ -0,0 +1,23 @@ +//===-- ldexp_differential_fuzz.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 +// +//===----------------------------------------------------------------------===// +/// +/// Differential fuzz test for llvm-libc ldexp implementation. +/// +//===----------------------------------------------------------------------===// + +#include "fuzzing/math/LdExpDiff.h" +#include "src/math/ldexp.h" + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + LdExpDiff(&__llvm_libc::ldexp, &::ldexp, data, size); + return 0; +} diff --git a/libc/fuzzing/math/ldexpf_differential_fuzz.cpp b/libc/fuzzing/math/ldexpf_differential_fuzz.cpp new file mode 100644 index 0000000000000..fc8d5c96a5704 --- /dev/null +++ b/libc/fuzzing/math/ldexpf_differential_fuzz.cpp @@ -0,0 +1,23 @@ +//===-- ldexpf_differential_fuzz.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 +// +//===----------------------------------------------------------------------===// +/// +/// Differential fuzz test for llvm-libc ldexpf implementation. +/// +//===----------------------------------------------------------------------===// + +#include "fuzzing/math/LdExpDiff.h" +#include "src/math/ldexpf.h" + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + LdExpDiff(&__llvm_libc::ldexpf, &::ldexpf, data, size); + return 0; +} diff --git a/libc/fuzzing/math/ldexpl_differential_fuzz.cpp b/libc/fuzzing/math/ldexpl_differential_fuzz.cpp new file mode 100644 index 0000000000000..e042fa9728843 --- /dev/null +++ b/libc/fuzzing/math/ldexpl_differential_fuzz.cpp @@ -0,0 +1,23 @@ +//===-- ldexpl_differential_fuzz.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 +// +//===----------------------------------------------------------------------===// +/// +/// Differential fuzz test for llvm-libc ldexpl implementation. +/// +//===----------------------------------------------------------------------===// + +#include "fuzzing/math/LdExpDiff.h" +#include "src/math/ldexpl.h" + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + LdExpDiff(&__llvm_libc::ldexpl, &::ldexpl, data, size); + return 0; +} diff --git a/libc/fuzzing/math/remquo_differential_fuzz.cpp b/libc/fuzzing/math/remquo_differential_fuzz.cpp new file mode 100644 index 0000000000000..a64c30db5d3d5 --- /dev/null +++ b/libc/fuzzing/math/remquo_differential_fuzz.cpp @@ -0,0 +1,23 @@ +//===-- remquo_differential_fuzz.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 +// +//===----------------------------------------------------------------------===// +/// +/// Differential fuzz test for llvm-libc remquo implementation. +/// +//===----------------------------------------------------------------------===// + +#include "fuzzing/math/RemQuoDiff.h" +#include "src/math/remquo.h" + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + RemQuoDiff(&__llvm_libc::remquo, &::remquo, data, size); + return 0; +} diff --git a/libc/fuzzing/math/remquof_differential_fuzz.cpp b/libc/fuzzing/math/remquof_differential_fuzz.cpp new file mode 100644 index 0000000000000..78ec6ea057b73 --- /dev/null +++ b/libc/fuzzing/math/remquof_differential_fuzz.cpp @@ -0,0 +1,23 @@ +//===-- remquof_differential_fuzz.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 +// +//===----------------------------------------------------------------------===// +/// +/// Differential fuzz test for llvm-libc remquof implementation. +/// +//===----------------------------------------------------------------------===// + +#include "fuzzing/math/RemQuoDiff.h" +#include "src/math/remquof.h" + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + RemQuoDiff(&__llvm_libc::remquof, &::remquof, data, size); + return 0; +} diff --git a/libc/fuzzing/math/remquol_differential_fuzz.cpp b/libc/fuzzing/math/remquol_differential_fuzz.cpp new file mode 100644 index 0000000000000..ab25fa1966312 --- /dev/null +++ b/libc/fuzzing/math/remquol_differential_fuzz.cpp @@ -0,0 +1,23 @@ +//===-- remquol_differential_fuzz.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 +// +//===----------------------------------------------------------------------===// +/// +/// Differential fuzz test for llvm-libc remquol implementation. +/// +//===----------------------------------------------------------------------===// + +#include "fuzzing/math/RemQuoDiff.h" +#include "src/math/remquol.h" + +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + RemQuoDiff(&__llvm_libc::remquol, &::remquol, data, size); + return 0; +}