diff --git a/CMakeLists.txt b/CMakeLists.txt index de7717c..e504d13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ set(SO_PATCH 1) option(UTF8PROC_INSTALL "Enable installation of utf8proc" On) option(UTF8PROC_ENABLE_TESTING "Enable testing of utf8proc" Off) +option(LIB_FUZZING_ENGINE "Fuzzing engine to link against" Off) add_library (utf8proc utf8proc.c @@ -98,4 +99,12 @@ if(UTF8PROC_ENABLE_TESTING) target_link_libraries(normtest utf8proc) add_test(utf8proc.testgraphemetest graphemetest data/GraphemeBreakTest.txt) add_test(utf8proc.testnormtest normtest data/NormalizationTest.txt) + + if(LIB_FUZZING_ENGINE) + add_executable(fuzzer utf8proc.h test/fuzzer.c) + target_link_libraries(fuzzer ${LIB_FUZZING_ENGINE} utf8proc) + else() + add_executable(fuzzer utf8proc.h test/fuzz_main.c test/fuzzer.c) + target_link_libraries(fuzzer utf8proc) + endif() endif() diff --git a/test/fuzz_main.c b/test/fuzz_main.c new file mode 100644 index 0000000..7b0c22b --- /dev/null +++ b/test/fuzz_main.c @@ -0,0 +1,54 @@ +#include +#include +#include + +/* Fuzz target entry point, works without libFuzzer */ + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); + +int main(int argc, char **argv) +{ + FILE *f; + char *buf = NULL; + long siz_buf; + + if(argc < 2) + { + fprintf(stderr, "no input file\n"); + goto err; + } + + f = fopen(argv[1], "rb"); + if(f == NULL) + { + fprintf(stderr, "error opening input file %s\n", argv[1]); + goto err; + } + + fseek(f, 0, SEEK_END); + + siz_buf = ftell(f); + rewind(f); + + if(siz_buf < 1) goto err; + + buf = (char*)malloc(siz_buf); + if(buf == NULL) + { + fprintf(stderr, "malloc() failed\n"); + goto err; + } + + if(fread(buf, siz_buf, 1, f) != 1) + { + fprintf(stderr, "fread() failed\n"); + goto err; + } + + (void)LLVMFuzzerTestOneInput((uint8_t*)buf, siz_buf); + +err: + free(buf); + + return 0; +} diff --git a/test/fuzzer.c b/test/fuzzer.c new file mode 100644 index 0000000..cc91e67 --- /dev/null +++ b/test/fuzzer.c @@ -0,0 +1,16 @@ +#include + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if(size < 1) return 0; + + if(data[size-1] != '\0') return 0; + + free(utf8proc_NFD(data)); + free(utf8proc_NFC(data)); + free(utf8proc_NFKD(data)); + free(utf8proc_NFKC(data)); + free(utf8proc_NFKC_Casefold(data)); + + return 0; +} \ No newline at end of file diff --git a/test/ossfuzz.sh b/test/ossfuzz.sh new file mode 100755 index 0000000..8a127a3 --- /dev/null +++ b/test/ossfuzz.sh @@ -0,0 +1,13 @@ +#!/bin/bash -eu +# This script is meant to be run by +# https://github.com/google/oss-fuzz/blob/master/projects/utf8proc/Dockerfile + +mkdir build +cd build +cmake .. -DUTF8PROC_ENABLE_TESTING=ON -DLIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" +make -j$(nproc) + +cp $SRC/utf8proc/build/fuzzer utf8proc_fuzzer + +find $SRC/utf8proc/test -name "*.txt" | \ + xargs zip $OUT/utf8proc_fuzzer_seed_corpus.zip