[Tarantool-patches] [PATCH v2] Add infrastructure for fuzzing testing and fuzzers
Serge Petrenko
sergepetrenko at tarantool.org
Fri Apr 24 16:56:00 MSK 2020
Hi! Thanks for the patch!
I couldn’t build tarantool with ENABLE_FUZZER = ON on my machine, since I
don’t have LibFuzzer, even though I have clang and everything that Apple bundles
with it. I still have some comments though.
> 20 апр. 2020 г., в 11:47, Sergey Bronnikov <sergeyb at tarantool.org> написал(а):
>
> - introduce CMake flag to enable building fuzzers
> - add fuzzers based on LibFuzzer[1] to csv, http_parser and uri modules
>
> [1] https://llvm.org/docs/LibFuzzer.html
>
> Note: LibFuzzer requires Clang compiler
>
> How-To Use:
>
> $ mkdir build && cd build
> $ CC=clang CXX=clang++ cmake -DENABLE_FUZZER=ON ..
> $ make -j
> $ ./Testing/test_csv corpus/ -max_total_time=60*60*60 -workers=4
> ...
>
> Follows: #1809
> ---
Please attach the branch, like this:
https://github.com/tarantool/tarantool/tree/ligurio/gh-1809-libfuzzer
> CMakeLists.txt | 2 +-
> cmake/profile.cmake | 5 +++++
> src/lib/csv/CMakeLists.txt | 11 +++++++++++
> src/lib/csv/test_csv.c | 23 +++++++++++++++++++++++
> src/lib/http_parser/CMakeLists.txt | 11 +++++++++++
> src/lib/http_parser/test_http_parser.c | 22 ++++++++++++++++++++++
> src/lib/uri/CMakeLists.txt | 12 ++++++++++++
> src/lib/uri/test_uri.c | 22 ++++++++++++++++++++++
> 8 files changed, 107 insertions(+), 1 deletion(-)
> create mode 100644 src/lib/csv/test_csv.c
> create mode 100644 src/lib/http_parser/test_http_parser.c
> create mode 100644 src/lib/uri/test_uri.c
>
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index 1d80b6806..99a502e3a 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -571,7 +571,7 @@ set(PREFIX ${CMAKE_INSTALL_PREFIX})
> set(options PACKAGE VERSION BUILD C_COMPILER CXX_COMPILER C_FLAGS CXX_FLAGS
> PREFIX
> ENABLE_SSE2 ENABLE_AVX
> - ENABLE_GCOV ENABLE_GPROF ENABLE_VALGRIND ENABLE_ASAN
> + ENABLE_GCOV ENABLE_GPROF ENABLE_VALGRIND ENABLE_ASAN ENABLE_FUZZER
> ENABLE_BACKTRACE
> ENABLE_DOC
> ENABLE_DIST
> diff --git a/cmake/profile.cmake b/cmake/profile.cmake
> index bc4bf67f5..b9fcd7655 100644
> --- a/cmake/profile.cmake
> +++ b/cmake/profile.cmake
> @@ -42,6 +42,11 @@ else()
> add_definitions(-DNVALGRIND=1)
> endif()
>
> +option(ENABLE_FUZZER "Enable fuzzing testing" OFF)
> +if (ENABLE_FUZZER)
> + set(TESTING_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Testing")
> +endif ()
Maybe report some error on an attemt to set ENABLE_FUZZER=ON
when the compiler isn't clang? Then there’ll be no need to check
for CMAKE_CXX_COMPILER_ID in each test’s file.
> +
> option(ENABLE_ASAN "Enable AddressSanitizer, a fast memory error detector based on compiler instrumentation" OFF)
> if (ENABLE_ASAN)
> if (CMAKE_COMPILER_IS_GNUCC)
> diff --git a/src/lib/csv/CMakeLists.txt b/src/lib/csv/CMakeLists.txt
> index 3580e4da2..d5a3ed1f6 100644
> --- a/src/lib/csv/CMakeLists.txt
> +++ b/src/lib/csv/CMakeLists.txt
> @@ -4,3 +4,14 @@ set(lib_sources
>
> set_source_files_compile_flags(${lib_sources})
> add_library(csv STATIC ${lib_sources})
> +
> +if (ENABLE_FUZZER AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
Is there such a thing as CMAKE_C_COMPILER_ID ?
If yes, then maybe check it instead of _CXX_ one ?
> + set(TestName "test_csv")
> + add_executable(${TestName} ${TestName}.c)
> + set_target_properties(${TestName}
> + PROPERTIES
> + COMPILE_FLAGS "-fsanitize=fuzzer,address -g -O1"
> + LINK_FLAGS "-fsanitize=fuzzer,address")
> + target_link_libraries(${TestName} PRIVATE csv)
> + set_target_properties(${TestName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
> +endif ()
> diff --git a/src/lib/csv/test_csv.c b/src/lib/csv/test_csv.c
> new file mode 100644
> index 000000000..aa1703514
> --- /dev/null
> +++ b/src/lib/csv/test_csv.c
Maybe we should put all the tests to test/fuzzing/smth ?
Since we have test/unit/smth.
> @@ -0,0 +1,23 @@
> +#include <stdint.h>
> +#include <stdlib.h>
> +#include <stddef.h>
> +#include <string.h>
> +#include "csv.h"
> +
> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
> + struct csv csv;
> + csv_create(&csv);
> + char *buf = calloc(size, sizeof(char*));
> + if (buf == NULL) {
> + return -1;
> + }
> + memcpy(buf, data, size);
> + buf[size] = '\0';
> + char *end = buf + size;
> + csv_parse_chunk(&csv, buf, end);
> + csv_finish_parsing(&csv);
> + csv_destroy(&csv);
> + free(buf);
> +
> + return 0;
> +}
> diff --git a/src/lib/http_parser/CMakeLists.txt b/src/lib/http_parser/CMakeLists.txt
> index a48f83cb6..7af922fbb 100644
> --- a/src/lib/http_parser/CMakeLists.txt
> +++ b/src/lib/http_parser/CMakeLists.txt
> @@ -1 +1,12 @@
> add_library(http_parser STATIC http_parser.c)
> +
> +if (ENABLE_FUZZER AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
> + set(TestName "test_http_parser")
> + add_executable(${TestName} ${TestName}.c)
> + set_target_properties(${TestName}
> + PROPERTIES
> + COMPILE_FLAGS "-fsanitize=fuzzer,address -g -O1"
> + LINK_FLAGS "-fsanitize=fuzzer,address")
> + target_link_libraries(${TestName} PRIVATE http_parser)
> + set_target_properties(${TestName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
> +endif ()
> diff --git a/src/lib/http_parser/test_http_parser.c b/src/lib/http_parser/test_http_parser.c
> new file mode 100644
> index 000000000..a189e71e9
> --- /dev/null
> +++ b/src/lib/http_parser/test_http_parser.c
> @@ -0,0 +1,22 @@
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <stddef.h>
> +#include "http_parser.h"
> +
> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
> + struct http_parser parser;
> + char *buf = (char*)data;
> + http_parser_create(&parser);
> + parser.hdr_name = (char *)calloc((int)size, sizeof(char));
> + if (parser.hdr_name == NULL) {
> + return -1;
> + }
> + char *end_buf = buf + size;
> + int rc = http_parse_header_line(&parser, &buf, end_buf, size);
> + free(parser.hdr_name);
> + if (rc != 0) {
> + return rc;
> + }
> +
> + return 0;
Maybe plain
return rc;
will do?
> +}
> diff --git a/src/lib/uri/CMakeLists.txt b/src/lib/uri/CMakeLists.txt
> index 96410e5bf..77f5c5d57 100644
> --- a/src/lib/uri/CMakeLists.txt
> +++ b/src/lib/uri/CMakeLists.txt
> @@ -8,3 +8,15 @@ if (CC_HAS_WNO_IMPLICIT_FALLTHROUGH)
> -Wno-implicit-fallthrough)
> endif()
> add_library(uri STATIC uri.c)
> +
> +if (ENABLE_FUZZER AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
> + set(TestName "test_uri")
> + add_executable(${TestName} ${TestName}.c)
> + add_compile_options(-fsanitize=fuzzer,address -g -O1)
> + set_target_properties(${TestName}
> + PROPERTIES
> + COMPILE_FLAGS "-fsanitize=fuzzer,address -g -O1"
> + LINK_FLAGS "-fsanitize=fuzzer,address")
> + target_link_libraries(${TestName} PRIVATE uri)
> + set_target_properties(${TestName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
> +endif ()
> diff --git a/src/lib/uri/test_uri.c b/src/lib/uri/test_uri.c
> new file mode 100644
> index 000000000..ad8db6ef2
> --- /dev/null
> +++ b/src/lib/uri/test_uri.c
> @@ -0,0 +1,22 @@
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <stddef.h>
> +#include <string.h>
> +#include "uri.h"
> +
> +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
> + char *buf = calloc(size, sizeof(char*));
> + if (!buf) {
> + return -1;
> + }
> + strncpy(buf, (char*)data, size);
> + buf[size] = '\0';
> + struct uri uri;
> + int rc = uri_parse(&uri, buf);
> + free(buf);
> + if (rc != 0) {
> + return rc;
> + }
> +
> + return 0;
> +}
Same here.
> --
> 2.23.0
>
>
> --
> sergeyb@
--
Serge Petrenko
sergepetrenko at tarantool.org
More information about the Tarantool-patches
mailing list