@@ -5,21 +5,32 @@ enable_language(CXX) | |||||
include_directories(PUBLIC ${CMAKE_SOURCE_DIR}) | include_directories(PUBLIC ${CMAKE_SOURCE_DIR}) | ||||
include_directories(PUBLIC ${PROJECT_BINARY_DIR}) | include_directories(PUBLIC ${PROJECT_BINARY_DIR}) | ||||
# This sets up either the standalone runner or the user supplied libfuzzing | |||||
# engine. We're using the standalone runner for unit testing alone at the | |||||
# moment to make the sure the fuzzer builds and runs appropriately. | |||||
if(DEFINED ENV{LIB_FUZZING_ENGINE}) | if(DEFINED ENV{LIB_FUZZING_ENGINE}) | ||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LIB_FUZZING_ENGINE}") | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LIB_FUZZING_ENGINE}") | ||||
set(fuzzing_engine "") | |||||
set(FUZZING_ENGINE "") | |||||
else() | else() | ||||
add_library(fuzzing_engine standalone_runner.cc) | add_library(fuzzing_engine standalone_runner.cc) | ||||
set(fuzzing_engine fuzzing_engine) | |||||
set(FUZZING_ENGINE fuzzing_engine) | |||||
endif() | endif() | ||||
foreach(FUZZERNAME | foreach(FUZZERNAME | ||||
bad_fuzzer | |||||
tokener_parse_ex_fuzzer) | tokener_parse_ex_fuzzer) | ||||
add_executable(${FUZZERNAME} ${FUZZERNAME}.cc) | add_executable(${FUZZERNAME} ${FUZZERNAME}.cc) | ||||
target_link_libraries(${FUZZERNAME} | target_link_libraries(${FUZZERNAME} | ||||
json-c | json-c | ||||
${fuzzing_engine}) | |||||
${FUZZING_ENGINE}) | |||||
add_test(NAME test_${FUZZERNAME} COMMAND ${CMAKE_BINARY_DIR}/fuzz/${FUZZERNAME} ${CMAKE_SOURCE_DIR}/fuzz/tests/valid.json) | |||||
file(GLOB TESTFILES "${CMAKE_SOURCE_DIR}/fuzz/tests/*.json") | |||||
foreach(TESTFILE ${TESTFILES}) | |||||
get_filename_component(FILENAME ${TESTFILE} NAME_WE) | |||||
add_test(NAME test_${FUZZERNAME}_${FILENAME} | |||||
COMMAND ${CMAKE_BINARY_DIR}/fuzz/${FUZZERNAME} | |||||
${TESTFILE}) | |||||
endforeach(TESTFILE) | |||||
endforeach(FUZZERNAME) | endforeach(FUZZERNAME) |
@@ -4,3 +4,23 @@ This directory contains fuzzers that | |||||
target [llvm's LibFuzzer](https://llvm.org/docs/LibFuzzer.html). They are built | target [llvm's LibFuzzer](https://llvm.org/docs/LibFuzzer.html). They are built | ||||
and run automatically by | and run automatically by | ||||
Google's [OSS-Fuzz](https://github.com/google/oss-fuzz/) infrastructure. | Google's [OSS-Fuzz](https://github.com/google/oss-fuzz/) infrastructure. | ||||
## How do I test or run the fuzzers like oss-fuzz? | |||||
``` | |||||
git clone https://github.com/google/oss-fuzz.git | |||||
cd oss-fuzz | |||||
python infra/helper.py build_image json-c | |||||
python infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 json-c | |||||
python infra/helper.py run_fuzzer json-c tokener_parse_ex_fuzzer | |||||
``` | |||||
## How do I add new unit or regression tests for the fuzzer? | |||||
The tests directory contains json files that can be used to either test the fuzzer itself or be used as regression tests. As long as the files end in `.json`, cmake will pick them up and generate a Ctest test case. If/when oss-fuzz finds a bug with a fuzzer, simply pull that test case into the `./tests` directory and it will serve as a regression test. | |||||
Note - the fuzzers are not being run with sanitizers in this repository's CI at the moment; we're strictly building them here to ensure that they function. | |||||
## How do I reproduce a failure form a fuzzer? | |||||
Use [the steps detailed on OSS-fuzz](https://google.github.io/oss-fuzz/advanced-topics/reproducing/). |
@@ -0,0 +1,9 @@ | |||||
#include <stdint.h> | |||||
#include <stddef.h> | |||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { | |||||
int *array = new int[100]; | |||||
delete [] array; | |||||
return array[size]; // BOOM | |||||
} |
@@ -15,13 +15,22 @@ | |||||
# | # | ||||
################################################################################ | ################################################################################ | ||||
# this is expected to be run only by oss-fuzz. It will run from $SRC (above json-c) | # this is expected to be run only by oss-fuzz. It will run from $SRC (above json-c) | ||||
cp $SRC/json-c/fuzz/*.dict $OUT/ | |||||
cp $SRC/json-c/fuzz/*.dict "$OUT/" | |||||
BUILD="$SRC/json-c/build" | BUILD="$SRC/json-c/build" | ||||
mkdir $BUILD | |||||
cd $BUILD | |||||
zip -j "$SRC/corpus.zip" "$SRC/go-fuzz-corpus/json/corpus" | |||||
mkdir "$BUILD" | |||||
cd "$BUILD" | |||||
cmake -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DBUILD_SHARED_LIBS=OFF .. | cmake -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DBUILD_SHARED_LIBS=OFF .. | ||||
make -j$(nproc) | make -j$(nproc) | ||||
cp fuzz/*_fuzzer $OUT/ | |||||
cp fuzz/*_fuzzer "$OUT/" | |||||
fuzzerFiles=$(find fuzz/ -name "*_fuzzer") | |||||
for F in $fuzzerFiles; do | |||||
FN=$(basename -- $F) | |||||
cp "$SRC/corpus.zip" "$OUT/${FN}_seed_corpus.zip" | |||||
done | |||||
# for fuzzer in fuzz copy the json corpus as a zip file |