[libc] Combine all math differential fuzzers into one target.

Also added diffing of a few more math functions. Combining the diff check
for all of these functions helps us meet the OSS fuzz bar of a minimum of
100 program edges.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D91817
This commit is contained in:
Siva Chandra Reddy 2020-11-19 12:51:04 -08:00
parent 6f1c07b23a
commit 4766a86cf2
13 changed files with 328 additions and 240 deletions

View File

@ -1,65 +1,50 @@
add_libc_fuzzer(
ldexp_differential_fuzz
math_differential_fuzz
SRCS
ldexp_differential_fuzz.cpp
math_differential_fuzz.cpp
HDRS
LdExpDiff.h
Compare.h
RemQuoDiff.h
SingleInputSingleOutputDiff.h
TwoInputSingleOutputDiff.h
DEPENDS
libc.src.math.ceil
libc.src.math.ceilf
libc.src.math.ceill
libc.src.math.fdim
libc.src.math.fdimf
libc.src.math.fdiml
libc.src.math.floor
libc.src.math.floorf
libc.src.math.floorl
libc.src.math.frexp
libc.src.math.frexpf
libc.src.math.frexpl
libc.src.math.hypotf
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.logb
libc.src.math.logbf
libc.src.math.logbl
libc.src.math.modf
libc.src.math.modff
libc.src.math.modfl
libc.src.math.sqrt
libc.src.math.sqrtf
libc.src.math.sqrtl
libc.src.math.remainder
libc.src.math.remainderf
libc.src.math.remainderl
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.src.math.round
libc.src.math.roundf
libc.src.math.roundl
libc.src.math.trunc
libc.src.math.truncf
libc.src.math.truncl
libc.utils.FPUtil.fputil
libc.utils.CPP.standalone_cpp
)

View File

@ -0,0 +1,34 @@
//===-- Template functions to compare scalar values -------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_FUZZING_MATH_COMPARE_H
#define LLVM_LIBC_FUZZING_MATH_COMPARE_H
#include "utils/CPP/TypeTraits.h"
template <typename T>
__llvm_libc::cpp::EnableIfType<__llvm_libc::cpp::IsFloatingPointType<T>::Value,
bool>
ValuesEqual(T x1, T x2) {
__llvm_libc::fputil::FPBits<T> bits1(x1);
__llvm_libc::fputil::FPBits<T> bits2(x2);
// If either is NaN, we want both to be NaN.
if (bits1.isNaN() || bits2.isNaN())
return bits2.isNaN() && bits2.isNaN();
// For all other values, we want the values to be bitwise equal.
return bits1.bitsAsUInt() == bits2.bitsAsUInt();
}
template <typename T>
__llvm_libc::cpp::EnableIfType<__llvm_libc::cpp::IsIntegral<T>::Value, bool>
ValuesEqual(T x1, T x2) {
return x1 == x1;
}
#endif // LLVM_LIBC_FUZZING_MATH_COMPARE_H

View File

@ -1,44 +0,0 @@
//===-- 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 <math.h>
#include <stddef.h>
#include <stdint.h>
template <typename T> using LdExpFunc = T (*)(T, int);
template <typename T>
void LdExpDiff(LdExpFunc<T> func1, LdExpFunc<T> func2, const uint8_t *data,
size_t size) {
constexpr size_t typeSize = sizeof(T);
if (size < typeSize + sizeof(int))
return;
T x = *reinterpret_cast<const T *>(data);
T i = *reinterpret_cast<const int *>(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<T> bits1(result1);
__llvm_libc::fputil::FPBits<T> bits2(result2);
if (bits1.bitsAsUInt() != bits2.bitsAsUInt())
__builtin_trap();
}

View File

@ -33,11 +33,9 @@ void RemQuoDiff(RemQuoFunc<T> func1, RemQuoFunc<T> func2, const uint8_t *data,
__builtin_trap();
return;
}
if (isinf(remainder1)) {
if (isinf(remainder2) != isinf(remainder1))
__builtin_trap();
return;
}
if (isinf(remainder2) != isinf(remainder1))
__builtin_trap();
// Compare only the 3 LS bits of the quotient.
if ((q1 & 0x7) != (q2 & 0x7))

View File

@ -0,0 +1,61 @@
//===-- Template to diff single-input-single-output functions ---*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_FUZZING_MATH_SINGLE_INPUT_SINGLE_OUTPUT_DIFF_H
#define LLVM_LIBC_FUZZING_MATH_SINGLE_INPUT_SINGLE_OUTPUT_DIFF_H
#include "fuzzing/math/Compare.h"
#include "utils/FPUtil/FPBits.h"
#include <math.h>
#include <stddef.h>
#include <stdint.h>
template <typename T> using SingleInputSingleOutputFunc = T (*)(T);
template <typename T>
void SingleInputSingleOutputDiff(SingleInputSingleOutputFunc<T> func1,
SingleInputSingleOutputFunc<T> func2,
const uint8_t *data, size_t size) {
if (size < sizeof(T))
return;
T x = *reinterpret_cast<const T *>(data);
T result1 = func1(x);
T result2 = func2(x);
if (!ValuesEqual(result1, result2))
__builtin_trap();
}
template <typename T1, typename T2>
using SingleInputSingleOutputWithSideEffectFunc = T1 (*)(T1, T2 *);
template <typename T1, typename T2>
void SingleInputSingleOutputWithSideEffectDiff(
SingleInputSingleOutputWithSideEffectFunc<T1, T2> func1,
SingleInputSingleOutputWithSideEffectFunc<T1, T2> func2,
const uint8_t *data, size_t size) {
if (size < sizeof(T1))
return;
T1 x = *reinterpret_cast<const T1 *>(data);
T2 sideEffect1, sideEffect2;
T1 result1 = func1(x, &sideEffect1);
T1 result2 = func2(x, &sideEffect2);
if (!ValuesEqual(result1, result2))
__builtin_trap();
if (!ValuesEqual(sideEffect1, sideEffect2))
__builtin_trap();
}
#endif // LLVM_LIBC_FUZZING_MATH_SINGLE_INPUT_SINGLE_OUTPUT_DIFF_H

View File

@ -0,0 +1,40 @@
//===-- Template to diff two-input-single-output functions ------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_FUZZING_MATH_TWO_INPUT_SINGLE_OUTPUT_DIFF_H
#define LLVM_LIBC_FUZZING_MATH_TWO_INPUT_SINGLE_OUTPUT_DIFF_H
#include "fuzzing/math/Compare.h"
#include "utils/FPUtil/FPBits.h"
#include <math.h>
#include <stddef.h>
#include <stdint.h>
template <typename T1, typename T2>
using TwoInputSingleOutputFunc = T1 (*)(T1, T2);
template <typename T1, typename T2>
void TwoInputSingleOutputDiff(TwoInputSingleOutputFunc<T1, T2> func1,
TwoInputSingleOutputFunc<T1, T2> func2,
const uint8_t *data, size_t size) {
constexpr size_t t1Size = sizeof(T1);
if (size < t1Size + sizeof(T2))
return;
T1 x = *reinterpret_cast<const T1 *>(data);
T2 y = *reinterpret_cast<const T2 *>(data + t1Size);
T1 result1 = func1(x, y);
T1 result2 = func2(x, y);
if (!ValuesEqual(result1, result2))
__builtin_trap();
}
#endif // LLVM_LIBC_FUZZING_MATH_TWO_INPUT_SINGLE_OUTPUT_DIFF_H

View File

@ -1,23 +0,0 @@
//===-- 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 <math.h>
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
LdExpDiff<double>(&__llvm_libc::ldexp, &::ldexp, data, size);
return 0;
}

View File

@ -1,23 +0,0 @@
//===-- 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 <math.h>
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
LdExpDiff<float>(&__llvm_libc::ldexpf, &::ldexpf, data, size);
return 0;
}

View File

@ -1,23 +0,0 @@
//===-- 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 <math.h>
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
LdExpDiff<long double>(&__llvm_libc::ldexpl, &::ldexpl, data, size);
return 0;
}

View File

@ -0,0 +1,152 @@
//===-- 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/RemQuoDiff.h"
#include "fuzzing/math/SingleInputSingleOutputDiff.h"
#include "fuzzing/math/TwoInputSingleOutputDiff.h"
#include "src/math/ceil.h"
#include "src/math/ceilf.h"
#include "src/math/ceill.h"
#include "src/math/fdim.h"
#include "src/math/fdimf.h"
#include "src/math/fdiml.h"
#include "src/math/floor.h"
#include "src/math/floorf.h"
#include "src/math/floorl.h"
#include "src/math/frexp.h"
#include "src/math/frexpf.h"
#include "src/math/frexpl.h"
#include "src/math/hypotf.h"
#include "src/math/ldexp.h"
#include "src/math/ldexpf.h"
#include "src/math/ldexpl.h"
#include "src/math/logb.h"
#include "src/math/logbf.h"
#include "src/math/logbl.h"
#include "src/math/modf.h"
#include "src/math/modff.h"
#include "src/math/modfl.h"
#include "src/math/remainder.h"
#include "src/math/remainderf.h"
#include "src/math/remainderl.h"
#include "src/math/remquo.h"
#include "src/math/remquof.h"
#include "src/math/remquol.h"
#include "src/math/round.h"
#include "src/math/roundf.h"
#include "src/math/roundl.h"
#include "src/math/sqrt.h"
#include "src/math/sqrtf.h"
#include "src/math/sqrtl.h"
#include "src/math/trunc.h"
#include "src/math/truncf.h"
#include "src/math/truncl.h"
#include <math.h>
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
SingleInputSingleOutputDiff<float>(&__llvm_libc::ceilf, &::ceilf, data, size);
SingleInputSingleOutputDiff<double>(&__llvm_libc::ceil, &::ceil, data, size);
SingleInputSingleOutputDiff<long double>(&__llvm_libc::ceill, &::ceill, data,
size);
SingleInputSingleOutputDiff<float>(&__llvm_libc::floorf, &::floorf, data,
size);
SingleInputSingleOutputDiff<double>(&__llvm_libc::floor, &::floor, data,
size);
SingleInputSingleOutputDiff<long double>(&__llvm_libc::floorl, &::floorl,
data, size);
SingleInputSingleOutputDiff<float>(&__llvm_libc::roundf, &::roundf, data,
size);
SingleInputSingleOutputDiff<double>(&__llvm_libc::round, &::round, data,
size);
SingleInputSingleOutputDiff<long double>(&__llvm_libc::roundl, &::roundl,
data, size);
SingleInputSingleOutputDiff<float>(&__llvm_libc::truncf, &::truncf, data,
size);
SingleInputSingleOutputDiff<double>(&__llvm_libc::trunc, &::trunc, data,
size);
SingleInputSingleOutputDiff<long double>(&__llvm_libc::truncl, &::truncl,
data, size);
SingleInputSingleOutputDiff<float>(&__llvm_libc::logbf, &::logbf, data, size);
SingleInputSingleOutputDiff<double>(&__llvm_libc::logb, &::logb, data, size);
SingleInputSingleOutputDiff<long double>(&__llvm_libc::logbl, &::logbl, data,
size);
TwoInputSingleOutputDiff<float, float>(&__llvm_libc::hypotf, &::hypotf, data,
size);
TwoInputSingleOutputDiff<float, float>(&__llvm_libc::remainderf,
&::remainderf, data, size);
TwoInputSingleOutputDiff<double, double>(&__llvm_libc::remainder,
&::remainder, data, size);
TwoInputSingleOutputDiff<long double, long double>(&__llvm_libc::remainderl,
&::remainderl, data, size);
TwoInputSingleOutputDiff<float, float>(&__llvm_libc::fdimf, &::fdimf, data,
size);
TwoInputSingleOutputDiff<double, double>(&__llvm_libc::fdim, &::fdim, data,
size);
TwoInputSingleOutputDiff<long double, long double>(&__llvm_libc::fdiml,
&::fdiml, data, size);
SingleInputSingleOutputDiff<float>(&__llvm_libc::sqrtf, &::sqrtf, data, size);
SingleInputSingleOutputDiff<double>(&__llvm_libc::sqrt, &::sqrt, data, size);
SingleInputSingleOutputDiff<long double>(&__llvm_libc::sqrtl, &::sqrtl, data,
size);
SingleInputSingleOutputWithSideEffectDiff<float, int>(&__llvm_libc::frexpf,
&::frexpf, data, size);
SingleInputSingleOutputWithSideEffectDiff<double, int>(&__llvm_libc::frexp,
&::frexp, data, size);
SingleInputSingleOutputWithSideEffectDiff<long double, int>(
&__llvm_libc::frexpl, &::frexpl, data, size);
SingleInputSingleOutputWithSideEffectDiff<float, float>(&__llvm_libc::modff,
&::modff, data, size);
SingleInputSingleOutputWithSideEffectDiff<double, double>(
&__llvm_libc::modf, &::modf, data, size);
SingleInputSingleOutputWithSideEffectDiff<long double, long double>(
&__llvm_libc::modfl, &::modfl, data, size);
TwoInputSingleOutputDiff<float, int>(&__llvm_libc::ldexpf, &::ldexpf, data,
size);
TwoInputSingleOutputDiff<double, int>(&__llvm_libc::ldexp, &::ldexp, data,
size);
TwoInputSingleOutputDiff<long double, int>(&__llvm_libc::ldexpl, &::ldexpl,
data, size);
RemQuoDiff<float>(&__llvm_libc::remquof, &::remquof, data, size);
RemQuoDiff<double>(&__llvm_libc::remquo, &::remquo, data, size);
RemQuoDiff<long double>(&__llvm_libc::remquol, &::remquol, data, size);
return 0;
}

View File

@ -1,23 +0,0 @@
//===-- 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 <math.h>
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
RemQuoDiff<double>(&__llvm_libc::remquo, &::remquo, data, size);
return 0;
}

View File

@ -1,23 +0,0 @@
//===-- 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 <math.h>
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
RemQuoDiff<float>(&__llvm_libc::remquof, &::remquof, data, size);
return 0;
}

View File

@ -1,23 +0,0 @@
//===-- 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 <math.h>
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
RemQuoDiff<long double>(&__llvm_libc::remquol, &::remquol, data, size);
return 0;
}