Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSSFuzz Integration PR #811

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ option( MANUAL_TZ_DB "User will set TZ DB manually by invoking set_install in th
option( USE_TZ_DB_IN_DOT "Save the timezone database in the current folder" OFF )
option( BUILD_SHARED_LIBS "Build a shared version of library" OFF )
option( ENABLE_DATE_TESTING "Enable unit tests" OFF )
option( ENABLE_FUZZ_TESTING "Build fuzz harnesses" OFF )
option( DISABLE_STRING_VIEW "Disable string view" OFF )
option( COMPILE_WITH_C_LOCALE "define ONLY_C_LOCALE=1" OFF )
option( BUILD_TZ_LIB "build/install of TZ library" OFF )
Expand Down Expand Up @@ -275,3 +276,10 @@ if( ENABLE_DATE_TESTING )
endif( )
endforeach( )
endif( )

#[===================================================================[
fuzzing
#]===================================================================]
if(ENABLE_FUZZ_TESTING)
add_subdirectory(test/fuzzing)
endif()
72 changes: 72 additions & 0 deletions test/fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
if (NOT DEFINED ENV{OUT} OR NOT DEFINED ENV{LIB_FUZZING_ENGINE})
message(FATAL_ERROR "Environment variables expected for OSSFuzz builds not provided! Cannot build fuzzer")
endif()

# Create utility library
add_library(libfuzzutil
STATIC
fuzzutil.cpp
)

target_include_directories(libfuzzutil
PUBLIC "inc"
)

target_link_libraries(libfuzzutil
PUBLIC date::date
)

target_compile_options(libfuzzutil
PRIVATE
$ENV{LIB_FUZZING_ENGINE}
)

target_link_options(libfuzzutil
PRIVATE
$ENV{LIB_FUZZING_ENGINE}
)

function(create_harness source_path)

get_filename_component(harness_name "${source_path}" NAME_WE)

add_executable(${harness_name}
"${source_path}"
)

target_link_libraries(${harness_name}
PRIVATE
libfuzzutil
)

target_compile_definitions(${harness_name}
PRIVATE
-DNDEBUG # Do not want assertions
)

target_compile_features(${harness_name}
PRIVATE
cxx_std_17
)

target_compile_options(${harness_name}
PRIVATE
$ENV{LIB_FUZZING_ENGINE}
)

target_link_options(${harness_name}
PRIVATE
$ENV{LIB_FUZZING_ENGINE}
)

install(TARGETS ${harness_name} DESTINATION $ENV{OUT})
endfunction()

# Create a harness executable for all sources following fuzz_*.cpp pattern
file(GLOB_RECURSE
fuzz_source_files
fuzz_*.cpp
)
foreach(file ${fuzz_source_files})
create_harness("${file}")
endforeach ()
20 changes: 20 additions & 0 deletions test/fuzzing/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash -eu

# Performs the necessary steps to build the fuzz harnesses utilized to prepare the test library for fuzz-test
# integration into OSSFuzz

cd "$SRC"/date
mkdir -p build
cmake -S. -B build -DENABLE_FUZZ_TESTING=ON -DBUILD_TZ_LIB=OFF -DBUILD_SHARED_LIBS=OFF
cmake --build build --target install

# Compress the corpus to the $OUT directory
zip -q $WORK/seed_corpus.zip test/fuzzing/corpus/*

# Create a copy of the corpus in the $OUT directory for each target
for file in $(find "$OUT" -type f -regex ".*fuzz_.*")
do
target=$(basename -- "$file")
echo "Zipping corpus for target $target"
cp $WORK/seed_corpus.zip $OUT/"$target"_seed_corpus.zip
done
1 change: 1 addition & 0 deletions test/fuzzing/corpus/seed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
%C %u %F %T
1 change: 1 addition & 0 deletions test/fuzzing/corpus/seed1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sun 2016-12-11
1 change: 1 addition & 0 deletions test/fuzzing/corpus/seed2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sunday 2016-12-11
1 change: 1 addition & 0 deletions test/fuzzing/corpus/seed3
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
%A %F
1 change: 1 addition & 0 deletions test/fuzzing/corpus/seed4
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
%H %I %M %p %r %R %S %T %X %n %t %%
18 changes: 18 additions & 0 deletions test/fuzzing/fuzz_date_parse.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"

using namespace date;
using namespace std::chrono;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
const auto format = fdp.ConsumeRandomLengthString();
auto date = consume_year_month_day(fdp);
std::istringstream in{fdp.ConsumeRandomLengthString()};

in >> parse(format.c_str(), date);

return 0;
}
23 changes: 23 additions & 0 deletions test/fuzzing/fuzz_format.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"

using namespace date;
using namespace std::chrono;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
const auto format_str = fdp.ConsumeRandomLengthString();
std::ostringstream os;

try {
os << format(format_str.c_str(), consume_year_month_day(fdp));
}
catch (std::ios_base::failure&)
{
return -1;
}

return 0;
}
18 changes: 18 additions & 0 deletions test/fuzzing/fuzz_from_stream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"

using namespace date;
using namespace std::chrono;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
const auto format = fdp.ConsumeRandomLengthString();

std::istringstream is{fdp.ConsumeRandomLengthString()};
year_month_day ymd;
from_stream(is, format.c_str(), ymd);

return 0;
}
37 changes: 37 additions & 0 deletions test/fuzzing/fuzz_islamic_conversion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"
#include "date/islamic.h"
#include "date/iso_week.h"

using namespace date;
using namespace std::chrono;

enum class ConvType
{
ToYMD,
ToIYMD,
ToISOWeek,
kMaxValue=ToISOWeek // NOLINT: FuzzedDataProvider requires this field as is
};

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
std::ostringstream os;
switch (fdp.ConsumeEnum<ConvType>())
{
case ConvType::ToYMD:
os << year_month_day{consume_islamic_year_month_day(fdp)};
break;
case ConvType::ToIYMD:
os << islamic::year_month_day{consume_year_month_day(fdp)};
break;
case ConvType::ToISOWeek:
os << iso_week::year_weeknum_weekday{consume_islamic_year_month_day(fdp)};
break;
default:
return -1;
}
return 0;
}
37 changes: 37 additions & 0 deletions test/fuzzing/fuzz_julian_conversion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"
#include "date/julian.h"
#include "date/iso_week.h"

using namespace date;
using namespace std::chrono;

enum class ConvType
{
ToYMD,
ToJYMD,
ToISOWeek,
kMaxValue=ToISOWeek // NOLINT: FuzzedDataProvider requires this field as is
};

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
std::ostringstream os;
switch (fdp.ConsumeEnum<ConvType>())
{
case ConvType::ToYMD:
os << year_month_day{consume_julian_year_month_day(fdp)};
break;
case ConvType::ToJYMD:
os << julian::year_month_day{consume_year_month_day(fdp)};
break;
case ConvType::ToISOWeek:
os << iso_week::year_weeknum_weekday{consume_julian_year_month_day(fdp)};
break;
default:
return -1;
}
return 0;
}
51 changes: 51 additions & 0 deletions test/fuzzing/fuzz_make_time.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"

using namespace date;
using namespace std::chrono;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};

const auto dur_val = fdp.ConsumeIntegral<int64_t>();

switch (fdp.ConsumeEnum<duration_type>())
{
case duration_type::NANOSECONDS:
make_time(nanoseconds{dur_val});
break;
case duration_type::MICROSECONDS:
make_time(microseconds{dur_val});
break;
case duration_type::MILLISECONDS:
make_time(milliseconds {dur_val});
break;
case duration_type::SECONDS:
make_time(seconds {dur_val});
break;
case duration_type::MINUTES:
make_time(minutes {dur_val});
break;
case duration_type::HOURS:
make_time(hours {dur_val});
break;
case duration_type::DAYS:
make_time(days {dur_val});
break;
case duration_type::WEEKS:
make_time(weeks {dur_val});
break;
case duration_type::MONTHS:
make_time(months {dur_val});
break;
case duration_type::YEARS:
make_time(years {dur_val});
break;
default:
return -1;
}

return 0;
}
25 changes: 25 additions & 0 deletions test/fuzzing/fuzz_sys_parse.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"

using namespace date;
using namespace std::chrono;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
const auto format_str = fdp.ConsumeRandomLengthString();
std::istringstream in{fdp.ConsumeRandomLengthString()};

if (fdp.ConsumeBool())
{
sys_days tp;
in >> parse(format_str, tp);
}
else
{
sys_seconds tp;
in >> parse(format_str, tp);
}
return 0;
}
17 changes: 17 additions & 0 deletions test/fuzzing/fuzz_to_stream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"

using namespace date;
using namespace std::chrono;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
const auto format = fdp.ConsumeRandomLengthString();

std::ostringstream os;
to_stream(os, format.c_str(), consume_year_month_day(fdp));

return 0;
}
16 changes: 16 additions & 0 deletions test/fuzzing/fuzz_week_to_stream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <fuzzer/FuzzedDataProvider.h>

#include "fuzzutil.hpp"
#include "date/iso_week.h"

using namespace date;
using namespace std::chrono;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, std::size_t size)
{
FuzzedDataProvider fdp{data, size};
std::ostringstream os;
auto a = iso_week::year_weeknum_weekday{sys_days{days{fdp.ConsumeIntegral<int64_t>()}}};
os << a;
return 0;
}
Loading