mirror of
https://github.com/fmtlib/fmt.git
synced 2024-11-29 13:21:05 +00:00
Add float fuzzer and cleanup
This commit is contained in:
parent
82c4e2236a
commit
010efc310f
@ -9,6 +9,8 @@ option(FMT_FUZZ_LINKMAIN "Enables the reproduce mode, instead of libFuzzer" On)
|
|||||||
# the fuzz targets, otherwise the CMake configuration step fails.
|
# the fuzz targets, otherwise the CMake configuration step fails.
|
||||||
set(FMT_FUZZ_LDFLAGS "" CACHE STRING "LDFLAGS for the fuzz targets")
|
set(FMT_FUZZ_LDFLAGS "" CACHE STRING "LDFLAGS for the fuzz targets")
|
||||||
|
|
||||||
|
# Adds a binary for reproducing, i.e. no fuzzing, just enables replaying data
|
||||||
|
# through the fuzzers.
|
||||||
function(add_fuzzer source)
|
function(add_fuzzer source)
|
||||||
get_filename_component(basename ${source} NAME_WE)
|
get_filename_component(basename ${source} NAME_WE)
|
||||||
set(name ${basename}-fuzzer)
|
set(name ${basename}-fuzzer)
|
||||||
@ -23,6 +25,6 @@ function(add_fuzzer source)
|
|||||||
target_compile_features(${name} PRIVATE cxx_generic_lambdas)
|
target_compile_features(${name} PRIVATE cxx_generic_lambdas)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
foreach (source chrono-duration.cc named-arg.cc one-arg.cc two-args.cc)
|
foreach (source chrono-duration.cc float.cc named-arg.cc one-arg.cc two-args.cc)
|
||||||
add_fuzzer(${source})
|
add_fuzzer(${source})
|
||||||
endforeach ()
|
endforeach ()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Creates fuzzer builds of various kinds
|
# Creates fuzzer builds of various kinds
|
||||||
# - reproduce mode (no fuzzing, just enables replaying data through the fuzzers)
|
|
||||||
# - oss-fuzz emulated mode (makes sure a simulated invocation by oss-fuzz works)
|
# - oss-fuzz emulated mode (makes sure a simulated invocation by oss-fuzz works)
|
||||||
# - libFuzzer build (you will need clang)
|
# - libFuzzer build (you will need clang)
|
||||||
# - afl build (you will need afl)
|
# - afl build (you will need afl)
|
||||||
@ -23,15 +22,6 @@ here=$(pwd)
|
|||||||
CXXFLAGSALL="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION= -g"
|
CXXFLAGSALL="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION= -g"
|
||||||
CMAKEFLAGSALL="$root -GNinja -DCMAKE_BUILD_TYPE=Debug -DFMT_DOC=Off -DFMT_TEST=Off -DFMT_FUZZ=On -DCMAKE_CXX_STANDARD=17"
|
CMAKEFLAGSALL="$root -GNinja -DCMAKE_BUILD_TYPE=Debug -DFMT_DOC=Off -DFMT_TEST=Off -DFMT_FUZZ=On -DCMAKE_CXX_STANDARD=17"
|
||||||
|
|
||||||
# Builds the fuzzers as one would do if using afl or just making
|
|
||||||
# binaries for reproducing.
|
|
||||||
builddir=$here/build-fuzzers-reproduce
|
|
||||||
mkdir -p $builddir
|
|
||||||
cd $builddir
|
|
||||||
CXX="ccache g++" CXXFLAGS="$CXXFLAGSALL" cmake \
|
|
||||||
$CMAKEFLAGSALL
|
|
||||||
cmake --build $builddir
|
|
||||||
|
|
||||||
# For performance analysis of the fuzzers.
|
# For performance analysis of the fuzzers.
|
||||||
builddir=$here/build-fuzzers-perfanalysis
|
builddir=$here/build-fuzzers-perfanalysis
|
||||||
mkdir -p $builddir
|
mkdir -p $builddir
|
||||||
@ -68,18 +58,6 @@ cmake $CMAKEFLAGSALL \
|
|||||||
|
|
||||||
cmake --build $builddir
|
cmake --build $builddir
|
||||||
|
|
||||||
# Builds fuzzers for local fuzzing with libfuzzer with asan only.
|
|
||||||
builddir=$here/build-fuzzers-libfuzzer-addr
|
|
||||||
mkdir -p $builddir
|
|
||||||
cd $builddir
|
|
||||||
CXX="clang++" \
|
|
||||||
CXXFLAGS="$CXXFLAGSALL -fsanitize=fuzzer-no-link,undefined" cmake \
|
|
||||||
cmake $CMAKEFLAGSALL \
|
|
||||||
-DFMT_FUZZ_LINKMAIN=Off \
|
|
||||||
-DFMT_FUZZ_LDFLAGS="-fsanitize=fuzzer"
|
|
||||||
|
|
||||||
cmake --build $builddir
|
|
||||||
|
|
||||||
# Builds a fast fuzzer for making coverage fast.
|
# Builds a fast fuzzer for making coverage fast.
|
||||||
builddir=$here/build-fuzzers-fast
|
builddir=$here/build-fuzzers-fast
|
||||||
mkdir -p $builddir
|
mkdir -p $builddir
|
||||||
|
@ -81,6 +81,7 @@ void invoke_outer(const uint8_t* data, size_t size, int period) {
|
|||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
invoke_inner<std::exa>(format_str, rep);
|
invoke_inner<std::exa>(format_str, rep);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,8 +130,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|||||||
case 12:
|
case 12:
|
||||||
invoke_outer<long double>(data, size, period);
|
invoke_outer<long double>(data, size, period);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
34
test/fuzzing/float.cc
Normal file
34
test/fuzzing/float.cc
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// A fuzzer for floating-point formatter.
|
||||||
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <limits>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "fuzzer-common.h"
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
|
if (size <= sizeof(double) || !std::numeric_limits<double>::is_iec559)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto value = assign_from_buf<double>(data);
|
||||||
|
auto buffer = fmt::memory_buffer();
|
||||||
|
fmt::format_to(buffer, "{}", value);
|
||||||
|
|
||||||
|
// Check a round trip.
|
||||||
|
if (std::isnan(value)) {
|
||||||
|
auto nan = std::signbit(value) ? "-nan" : "nan";
|
||||||
|
if (fmt::string_view(buffer.data(), buffer.size()) != nan)
|
||||||
|
throw std::runtime_error("round trip failure");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buffer.push_back('\0');
|
||||||
|
char* ptr = nullptr;
|
||||||
|
if (std::strtod(buffer.data(), &ptr) != value)
|
||||||
|
throw std::runtime_error("round trip failure");
|
||||||
|
if (ptr != buffer.end())
|
||||||
|
throw std::runtime_error("unparsed output");
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,11 +1,10 @@
|
|||||||
// Copyright (c) 2019, Paul Dreik
|
// Copyright (c) 2019, Paul Dreik
|
||||||
// For the license information refer to format.h.
|
// For the license information refer to format.h.
|
||||||
|
|
||||||
#include <fmt/chrono.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <fmt/chrono.h>
|
||||||
|
|
||||||
#include "fuzzer-common.h"
|
#include "fuzzer-common.h"
|
||||||
|
|
||||||
@ -23,13 +22,16 @@ void invoke_fmt(const uint8_t* data, size_t size, unsigned arg_name_size) {
|
|||||||
size -= arg_name_size;
|
size -= arg_name_size;
|
||||||
|
|
||||||
data_to_string format_str(data, size);
|
data_to_string format_str(data, size);
|
||||||
|
try {
|
||||||
#if FMT_FUZZ_FORMAT_TO_STRING
|
#if FMT_FUZZ_FORMAT_TO_STRING
|
||||||
std::string message =
|
std::string message =
|
||||||
fmt::format(format_str.get(), fmt::arg(arg_name.data(), value));
|
fmt::format(format_str.get(), fmt::arg(arg_name.data(), value));
|
||||||
#else
|
#else
|
||||||
fmt::memory_buffer out;
|
fmt::memory_buffer out;
|
||||||
fmt::format_to(out, format_str.get(), fmt::arg(arg_name.data(), value));
|
fmt::format_to(out, format_str.get(), fmt::arg(arg_name.data(), value));
|
||||||
#endif
|
#endif
|
||||||
|
} catch (std::exception&) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For dynamic dispatching to an explicit instantiation.
|
// For dynamic dispatching to an explicit instantiation.
|
||||||
@ -91,11 +93,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|||||||
data++;
|
data++;
|
||||||
size--;
|
size--;
|
||||||
|
|
||||||
try {
|
invoke(type, [=](auto arg) {
|
||||||
invoke(type, [=](auto arg) {
|
invoke_fmt<decltype(arg)>(data, size, arg_name_size);
|
||||||
invoke_fmt<decltype(arg)>(data, size, arg_name_size);
|
});
|
||||||
});
|
|
||||||
} catch (std::exception&) {
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,15 @@ void invoke_fmt(const uint8_t* data, size_t size) {
|
|||||||
data += fixed_size;
|
data += fixed_size;
|
||||||
size -= fixed_size;
|
size -= fixed_size;
|
||||||
data_to_string format_str(data, size);
|
data_to_string format_str(data, size);
|
||||||
|
try {
|
||||||
#if FMT_FUZZ_FORMAT_TO_STRING
|
#if FMT_FUZZ_FORMAT_TO_STRING
|
||||||
std::string message = fmt::format(format_str.get(), *value);
|
std::string message = fmt::format(format_str.get(), *value);
|
||||||
#else
|
#else
|
||||||
fmt::memory_buffer message;
|
fmt::memory_buffer message;
|
||||||
fmt::format_to(message, format_str.get(), *value);
|
fmt::format_to(message, format_str.get(), *value);
|
||||||
#endif
|
#endif
|
||||||
|
} catch (std::exception&) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||||
@ -40,54 +43,49 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|||||||
data++;
|
data++;
|
||||||
size--;
|
size--;
|
||||||
|
|
||||||
try {
|
switch (first) {
|
||||||
switch (first) {
|
case 0:
|
||||||
case 0:
|
invoke_fmt<bool>(data, size);
|
||||||
invoke_fmt<bool>(data, size);
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 1:
|
invoke_fmt<char>(data, size);
|
||||||
invoke_fmt<char>(data, size);
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
invoke_fmt<unsigned char>(data, size);
|
||||||
invoke_fmt<unsigned char>(data, size);
|
break;
|
||||||
break;
|
case 3:
|
||||||
case 3:
|
invoke_fmt<signed char>(data, size);
|
||||||
invoke_fmt<signed char>(data, size);
|
break;
|
||||||
break;
|
case 4:
|
||||||
case 4:
|
invoke_fmt<short>(data, size);
|
||||||
invoke_fmt<short>(data, size);
|
break;
|
||||||
break;
|
case 5:
|
||||||
case 5:
|
invoke_fmt<unsigned short>(data, size);
|
||||||
invoke_fmt<unsigned short>(data, size);
|
break;
|
||||||
break;
|
case 6:
|
||||||
case 6:
|
invoke_fmt<int>(data, size);
|
||||||
invoke_fmt<int>(data, size);
|
break;
|
||||||
break;
|
case 7:
|
||||||
case 7:
|
invoke_fmt<unsigned int>(data, size);
|
||||||
invoke_fmt<unsigned int>(data, size);
|
break;
|
||||||
break;
|
case 8:
|
||||||
case 8:
|
invoke_fmt<long>(data, size);
|
||||||
invoke_fmt<long>(data, size);
|
break;
|
||||||
break;
|
case 9:
|
||||||
case 9:
|
invoke_fmt<unsigned long>(data, size);
|
||||||
invoke_fmt<unsigned long>(data, size);
|
break;
|
||||||
break;
|
case 10:
|
||||||
case 10:
|
invoke_fmt<float>(data, size);
|
||||||
invoke_fmt<float>(data, size);
|
break;
|
||||||
break;
|
case 11:
|
||||||
case 11:
|
invoke_fmt<double>(data, size);
|
||||||
invoke_fmt<double>(data, size);
|
break;
|
||||||
break;
|
case 12:
|
||||||
case 12:
|
invoke_fmt<long double>(data, size);
|
||||||
invoke_fmt<long double>(data, size);
|
break;
|
||||||
break;
|
case 13:
|
||||||
case 13:
|
invoke_fmt<std::tm, std::time_t>(data, size);
|
||||||
invoke_fmt<std::tm, std::time_t>(data, size);
|
break;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (std::exception&) {
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user