[Tarantool-patches] [PATCH v2] Add infrastructure for fuzzing testing and fuzzers
Sergey Bronnikov
sergeyb at tarantool.org
Wed Apr 29 15:09:56 MSK 2020
Hi, Igor
thanks a lot for review! See my answers inline.
On 14:19 Tue 28 Apr , Igor Munkin wrote:
> Sergey,
>
> Thanks for the patch! I left several comments, please consider them.
>
> On 20.04.20, Sergey Bronnikov wrote:
> > - 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
>
> I can't test your patch manually since this recipe doesn't work for me:
perhaps you should install package sys-libs/compiler-rt-sanitizers [1]
1. https://packages.gentoo.org/packages/sys-libs/compiler-rt-sanitizers
> | $ cat /etc/os-release
> | NAME=Gentoo
> | ID=gentoo
> | PRETTY_NAME="Gentoo/Linux"
> | ANSI_COLOR="1;32"
> | HOME_URL="https://www.gentoo.org/"
> | SUPPORT_URL="https://www.gentoo.org/support/"
> | BUG_REPORT_URL="https://bugs.gentoo.org/"
> | $ clang --version
> | clang version 8.0.1 (tags/RELEASE_801/final)
> | Target: x86_64-pc-linux-gnu
> | Thread model: posix
> | InstalledDir: /usr/lib/llvm/8/bin
> | $ clang++ --version
> | clang version 8.0.1 (tags/RELEASE_801/final)
> | Target: x86_64-pc-linux-gnu
> | Thread model: posix
> | InstalledDir: /usr/lib/llvm/8/bin
> | $ git status | head -1
> | On branch ligurio/gh-1809-libfuzzer
> | $ mkdir -p libfuzzer
> | $ cd !$
> | cd libfuzzer
> | $ CC=clang CXX=clang++ cmake -DENABLE_FUZZER=ON ..
> | -- Enabling LTO: FALSE
> | -- OpenSSL 1.1.1d found
> | --
> | CMake Deprecation Warning at test/CMakeLists.txt:21 (cmake_policy):
> | The OLD behavior for policy CMP0037 will be removed from a future version
> | of CMake.
> |
> | The cmake-policies(7) manual explains that the OLD behaviors of all
> | policies are deprecated and that a policy should be set to OLD only under
> | specific short-term circumstances. Projects should be ported to the NEW
> | behavior and not rely on setting a policy to OLD.
> |
> |
> | --
> | --
> | -- Configuring done
> | -- Generating done
> | -- Build files have been written to: /home/imun/projects/tarantool
> | $ echo $?
> | 0
> | $ make -j
> | make: *** No targets specified and no makefile found. Stop.
I suspect the problem was due to specifying "CXX=clang++".
I have changed check for compiler and it can probably fixes your problem.
> > ...
> >
> > Follows: #1809
>
> Please, don't use ':' in gh tags. It just doesn't respect our commit
> message style.
Fixed.
<snipped>
> > +if (ENABLE_FUZZER)
> > + set(TESTING_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Testing")
> > +endif ()
>
> There is no space before parentheses in other code, please adjust yours.
Fixed.
<snipped>
> > +if (ENABLE_FUZZER AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
> > + 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}")
>
> What if ${TESTING_OUTPUT_DIRECTORY} is not defined?
Why it can be undefined if I set it in cmake/profile.cmake when ENABLE_FUZZER is enabled?
> > +endif ()
>
> There is no space before parentheses in other code, please adjust yours.
Fixed.
> > 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
>
> This C file doesn't respect our C style guide[1], please adjust it.
>
> > @@ -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;
>
> So, csv parsing succeeds regardless the input? Then what is the purpose
> of the testing?
Yes, function LLVMFuzzerTestOneInput succeeds when csv parsing
finishes without any issues like memory corruption, buffer overflow etc.
Unfortunately these csv_* functions returns void and I cannot additionaly
check was parsing successfull or not. Anyway fuzzing is about negative testing
and our goal to check function for reliability with junk input.
> > +}
> > 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}")
>
> What if ${TESTING_OUTPUT_DIRECTORY} is not defined?
Why it can be undefined if I set it in cmake/profile.cmake when ENABLE_FUZZER is enabled?
> > +endif ()
>
> There is no space before parentheses in other code, please adjust yours.
Fixed.
> > 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
>
> This C file doesn't respect our C style guide[1], please adjust it.
Fixed.
> > @@ -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;
> > + }
>
> As Serge already mentioned, this branch is excess.
Agree, it's useless check.
> > +
> > + return 0;
> > +}
> > 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}")
>
> What if ${TESTING_OUTPUT_DIRECTORY} is not defined?
Why it can be undefined if I set it in cmake/profile.cmake when ENABLE_FUZZER is enabled?
> > +endif ()
>
> There is no space before parentheses in other code, please adjust yours.
Fixed.
> > 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
>
> This C file doesn't respect our C style guide[1], please adjust it.
Fixed.
> > @@ -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;
> > + }
>
> As Serge already mentioned, this branch is excess.
Fixed.
<snipped>
--
sergeyb@
More information about the Tarantool-patches
mailing list