From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp33.i.mail.ru (smtp33.i.mail.ru [94.100.177.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 043024696C3 for ; Fri, 24 Apr 2020 16:56:01 +0300 (MSK) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.80.23.2.2\)) From: Serge Petrenko In-Reply-To: <33ba1d50585e101aa025d899116c48d56be59202.1587372354.git.sergeyb@tarantool.org> Date: Fri, 24 Apr 2020 16:56:00 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: <7A9E4292-A080-46A7-AFF2-084AD61A51EC@tarantool.org> References: <33ba1d50585e101aa025d899116c48d56be59202.1587372354.git.sergeyb@tarantool.org> Subject: Re: [Tarantool-patches] [PATCH v2] Add infrastructure for fuzzing testing and fuzzers List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Sergey Bronnikov Cc: o.piskunov@tarantool.org, tml Hi! Thanks for the patch! I couldn=E2=80=99t build tarantool with ENABLE_FUZZER =3D ON on my = machine, since I don=E2=80=99t have LibFuzzer, even though I have clang and everything = that Apple bundles with it. I still have some comments though. > 20 =D0=B0=D0=BF=D1=80. 2020 =D0=B3., =D0=B2 11:47, Sergey Bronnikov = =D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB(=D0=B0)= : >=20 > - introduce CMake flag to enable building fuzzers > - add fuzzers based on LibFuzzer[1] to csv, http_parser and uri = modules >=20 > [1] https://llvm.org/docs/LibFuzzer.html >=20 > Note: LibFuzzer requires Clang compiler >=20 > How-To Use: >=20 > $ mkdir build && cd build > $ CC=3Dclang CXX=3Dclang++ cmake -DENABLE_FUZZER=3DON .. > $ make -j > $ ./Testing/test_csv corpus/ -max_total_time=3D60*60*60 -workers=3D4 > ... >=20 > 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 >=20 > 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=3D1) > endif() >=20 > +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=3DON when the compiler isn't clang? Then there=E2=80=99ll be no need to check for CMAKE_CXX_COMPILER_ID in each test=E2=80=99s 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 >=20 > 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=3Dfuzzer,address -g -O1" > + LINK_FLAGS "-fsanitize=3Dfuzzer,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 > +#include > +#include > +#include > +#include "csv.h" > + > +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { > + struct csv csv; > + csv_create(&csv); > + char *buf =3D calloc(size, sizeof(char*)); > + if (buf =3D=3D NULL) { > + return -1; > + } > + memcpy(buf, data, size); > + buf[size] =3D '\0'; > + char *end =3D 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=3Dfuzzer,address -g -O1" > + LINK_FLAGS "-fsanitize=3Dfuzzer,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 > +#include > +#include > +#include "http_parser.h" > + > +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { > + struct http_parser parser; > + char *buf =3D (char*)data; > + http_parser_create(&parser); > + parser.hdr_name =3D (char *)calloc((int)size, sizeof(char)); > + if (parser.hdr_name =3D=3D NULL) { > + return -1; > + } > + char *end_buf =3D buf + size; > + int rc =3D http_parse_header_line(&parser, &buf, end_buf, size); > + free(parser.hdr_name); > + if (rc !=3D 0) { > + return rc; > + } > + > + return 0; Maybe plain=20 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=3Dfuzzer,address -g -O1) > + set_target_properties(${TestName} > + PROPERTIES > + COMPILE_FLAGS "-fsanitize=3Dfuzzer,address -g -O1" > + LINK_FLAGS "-fsanitize=3Dfuzzer,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 > +#include > +#include > +#include > +#include "uri.h" > + > +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { > + char *buf =3D calloc(size, sizeof(char*)); > + if (!buf) { > + return -1; > + } > + strncpy(buf, (char*)data, size); > + buf[size] =3D '\0'; > + struct uri uri; > + int rc =3D uri_parse(&uri, buf); > + free(buf); > + if (rc !=3D 0) { > + return rc; > + } > + > + return 0; > +} Same here. > --=20 > 2.23.0 >=20 >=20 > --=20 > sergeyb@ -- Serge Petrenko sergepetrenko@tarantool.org=