Skip to content

Commit a23b7a1

Browse files
committed
refactor
1 parent 9a3f4cf commit a23b7a1

File tree

7 files changed

+60
-36
lines changed

7 files changed

+60
-36
lines changed

test/fuzzing/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ set(FMT_FUZZ_LDFLAGS "" CACHE STRING "LDFLAGS for the fuzz targets")
1212

1313
#find all fuzzers.
1414
set(SOURCES
15-
chrono_duration.cpp # this triggers integer overflows I yet not know how to fix
15+
chrono_duration.cpp
1616
named_arg.cpp
1717
one_arg.cpp
1818
sprintf.cpp
@@ -26,7 +26,7 @@ endif()
2626
macro(implement_fuzzer sourcefile)
2727
get_filename_component(basename ${sourcefile} NAME_WE)
2828
set(name fuzzer_${basename})
29-
add_executable(${name} ${sourcefile})
29+
add_executable(${name} ${sourcefile} fuzzer_common.h)
3030
target_link_libraries(${name} PRIVATE fmt)
3131
if(FMT_FUZZ_LDFLAGS)
3232
target_link_libraries(${name} PRIVATE ${FMT_FUZZ_LDFLAGS})

test/fuzzing/chrono_duration.cpp

+5-14
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,13 @@
88
#include <stdexcept>
99
#include <type_traits>
1010
#include <vector>
11+
#include "fuzzer_common.h"
1112

1213
template <typename Item, typename Ratio>
1314
void invoke_inner(fmt::string_view formatstring, const Item item) {
1415
const std::chrono::duration<Item, Ratio> value(item);
1516
try {
16-
// Don't switch these two dynamically,
17-
// there is already a large combinatoric explosion
18-
// of type and ratio, causing afl to suffer and the corpus
19-
// getting enormous. Occasionally, flip this switch and
20-
// try manually.
21-
#if 0
17+
#if FMT_FUZZ_FORMAT_TO_STRING
2218
std::string message = fmt::format(formatstring, value);
2319
#else
2420
fmt::memory_buffer buf;
@@ -31,21 +27,16 @@ void invoke_inner(fmt::string_view formatstring, const Item item) {
3127
// Item is the underlying type for duration (int, long etc)
3228
template <typename Item>
3329
void invoke_outer(const uint8_t* Data, std::size_t Size, const int scaling) {
34-
// always use a fixed location of the data, so different cases will
35-
// cooperate better. the same bit pattern, interpreted as another type,
36-
// is likely interesting.
37-
// won't work on travis.
38-
//constexpr auto Nfixed = std::max(sizeof(long double), sizeof(std::intmax_t));
39-
constexpr auto Nfixed=16;
30+
// always use a fixed location of the data
31+
using fmt_fuzzer::Nfixed;
4032

4133
constexpr auto N = sizeof(Item);
4234
static_assert(N <= Nfixed, "fixed size is too small");
4335
if (Size <= Nfixed + 1) {
4436
return;
4537
}
4638

47-
// travis doesn't handle this
48-
#if 0
39+
#if __cplusplus >= 201402L
4940
static_assert(std::is_trivially_copyable<Item>::value,
5041
"Item must be blittable");
5142
#endif

test/fuzzing/fuzzer_common.h

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#ifndef FUZZER_COMMON_H
2+
#define FUZZER_COMMON_H
3+
// Copyright (c) 2019, Paul Dreik
4+
// License: see LICENSE.rst in the fmt root directory
5+
6+
// one can format to either a string, or a buf. buf is faster,
7+
// but one may be interested in formatting to a string instead to
8+
// verify it works as intended. to avoid a combinatoric explosion,
9+
// select this at compile time instead of dynamically from the fuzz data
10+
#define FMT_FUZZ_FORMAT_TO_STRING 1
11+
12+
// if fmt is given a buffer that is separately allocated,
13+
// chances that address sanitizer detects out of bound reads is
14+
// much higher. However, it slows down the fuzzing.
15+
#define FMT_FUZZ_SEPARATE_ALLOCATION 1
16+
17+
18+
19+
// To let the the fuzzer mutation be efficient at cross pollinating
20+
// between different types, use a fixed size format.
21+
// The same bit pattern, interpreted as another type,
22+
// is likely interesting.
23+
// For this, we must know the size of the largest possible type in use.
24+
// There are some problems on old compilers, hence the C++ version check
25+
#if __cplusplus >= 201402L
26+
# include <algorithm>
27+
# include <cstdint>
28+
namespace fmt_fuzzer {
29+
constexpr auto Nfixed = std::max(sizeof(long double), sizeof(std::intmax_t));
30+
}
31+
#else
32+
namespace fmt_fuzzer {
33+
constexpr auto Nfixed=16;
34+
}
35+
#endif
36+
37+
#endif // FUZZER_COMMON_H

test/fuzzing/named_arg.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <stdexcept>
88
#include <type_traits>
99
#include <vector>
10+
#include "fuzzer_common.h"
1011

1112
template <typename Item1>
1213
void invoke_fmt(const uint8_t* Data, std::size_t Size, int argsize) {
@@ -30,8 +31,7 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size, int argsize) {
3031

3132
// allocating buffers separately is slower, but increases chances
3233
// of detecting memory errors
33-
#define SEPARATE_ALLOCATION 1
34-
#if SEPARATE_ALLOCATION
34+
#if FMT_FUZZ_SEPARATE_ALLOCATION
3535
std::vector<char> argnamebuffer(argsize);
3636
std::memcpy(argnamebuffer.data(), Data, argsize);
3737
auto argname = fmt::string_view(argnamebuffer.data(), argsize);
@@ -41,7 +41,7 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size, int argsize) {
4141
Data += argsize;
4242
Size -= argsize;
4343

44-
#if SEPARATE_ALLOCATION
44+
#if FMT_FUZZ_SEPARATE_ALLOCATION
4545
// allocates as tight as possible, making it easier to catch buffer overruns.
4646
std::vector<char> fmtstringbuffer(Size);
4747
std::memcpy(fmtstringbuffer.data(), Data, Size);
@@ -50,7 +50,6 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size, int argsize) {
5050
auto fmtstring = fmt::string_view((const char*)Data, Size);
5151
#endif
5252
std::string message = fmt::format(fmtstring, fmt::arg(argname, item1));
53-
#undef SEPARATE_ALLOCATION
5453
}
5554

5655
// for dynamic dispatching to an explicit instantiation

test/fuzzing/one_arg.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <vector>
99

1010
#include <fmt/chrono.h>
11+
#include "fuzzer_common.h"
1112

1213
template <typename Item>
1314
void invoke_fmt(const uint8_t* Data, std::size_t Size) {
@@ -24,17 +25,16 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size) {
2425
Data += N;
2526
Size -= N;
2627

27-
#define SEPARATE_ALLOCATION 0
28-
#if SEPARATE_ALLOCATION
28+
#if FMT_FUZZ_SEPARATE_ALLOCATION
2929
// allocates as tight as possible, making it easier to catch buffer overruns.
3030
std::vector<char> fmtstringbuffer(Size);
3131
std::memcpy(fmtstringbuffer.data(), Data, Size);
3232
auto fmtstring = fmt::string_view(fmtstringbuffer.data(), Size);
3333
#else
3434
auto fmtstring = fmt::string_view((const char*)Data, Size);
3535
#endif
36-
#define ALLOCATE_RESULT_IN_STRING 0
37-
#if ALLOCATE_RESULT_IN_STRING
36+
37+
#if FMT_FUZZ_FORMAT_TO_STRING
3838
std::string message = fmt::format(fmtstring, item);
3939
#else
4040
fmt::memory_buffer message;
@@ -52,7 +52,7 @@ void invoke_fmt_time(const uint8_t* Data, std::size_t Size) {
5252
std::memcpy(&item, Data, N);
5353
Data += N;
5454
Size -= N;
55-
#if SEPARATE_ALLOCATION
55+
#if FMT_FUZZ_SEPARATE_ALLOCATION
5656
// allocates as tight as possible, making it easier to catch buffer overruns.
5757
std::vector<char> fmtstringbuffer(Size);
5858
std::memcpy(fmtstringbuffer.data(), Data, Size);
@@ -62,7 +62,7 @@ void invoke_fmt_time(const uint8_t* Data, std::size_t Size) {
6262
#endif
6363
auto* b = std::localtime(&item);
6464
if (b) {
65-
#if ALLOCATE_RESULT_IN_STRING
65+
#if FMT_FUZZ_FORMAT_TO_STRING
6666
std::string message = fmt::format(fmtstring, *b);
6767
#else
6868
fmt::memory_buffer message;

test/fuzzing/sprintf.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
#include <cstdint>
66
#include <stdexcept>
77

8+
#include "fuzzer_common.h"
89

9-
// won't work on travis.
10-
//constexpr auto Nmax = std::max(sizeof(long double), sizeof(std::intmax_t));
11-
constexpr auto Nmax=16;
10+
constexpr auto Nmax=fmt_fuzzer::Nfixed;
1211

1312
template <class Item>
1413
Item assignFromBuf(const uint8_t* Data, std::size_t Size) {
@@ -40,8 +39,7 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size) {
4039

4140
auto fmtstring = fmt::string_view((const char*)Data, Size);
4241

43-
#define ALLOCATE_RESULT_IN_STRING 0
44-
#if ALLOCATE_RESULT_IN_STRING
42+
#if FMT_FUZZ_FORMAT_TO_STRING
4543
std::string message = fmt::format(fmtstring, item1, item2);
4644
#else
4745
fmt::memory_buffer message;

test/fuzzing/two_args.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
#include <stdexcept>
66
#include <type_traits>
77

8-
// won't work on travis.
9-
//constexpr auto Nmax = std::max(sizeof(long double), sizeof(std::intmax_t));
10-
constexpr auto Nmax=16;
8+
#include "fuzzer_common.h"
9+
10+
constexpr auto Nmax=fmt_fuzzer::Nfixed;
1111

1212
template <typename Item1, typename Item2>
1313
void invoke_fmt(const uint8_t* Data, std::size_t Size) {
@@ -38,8 +38,7 @@ void invoke_fmt(const uint8_t* Data, std::size_t Size) {
3838

3939
auto fmtstring = fmt::string_view((const char*)Data, Size);
4040

41-
#define ALLOCATE_RESULT_IN_STRING 0
42-
#if ALLOCATE_RESULT_IN_STRING
41+
#if FMT_FUZZ_FORMAT_TO_STRING
4342
std::string message = fmt::format(fmtstring, item1, item2);
4443
#else
4544
fmt::memory_buffer message;

0 commit comments

Comments
 (0)