Tarantool development patches archive
 help / color / mirror / Atom feed
From: sergeyb@tarantool.org
To: tarantool-patches@dev.tarantool.org, imun@tarantool.org,
	sergepetrenko@tarantool.org
Subject: [Tarantool-patches] [PATCH 1/4] test: add infrastructure for fuzzing testing and fuzzers
Date: Mon, 30 Nov 2020 23:24:46 +0300	[thread overview]
Message-ID: <ce3bb1f82c97a2fa077a41640c6ae9f9bf74a1e4.1606766417.git.sergeyb@tarantool.org> (raw)
In-Reply-To: <cover.1606766417.git.sergeyb@tarantool.org>

From: Sergey Bronnikov <sergeyb@tarantool.org>

There is a number of bugs related to parsing and encoding/decoding data.
Examples:

- csv: #2692, #4497, #2692
- uri: #585

One of the effective method to find such issues is a fuzzing testing.
Patch introduce a CMake flag to enable building fuzzers (ENABLE_FUZZER)
and add fuzzers based on LibFuzzer [1] to csv, http_parser and uri modules.
NOTE: LibFuzzer requires Clang compiler.

[1] https://llvm.org/docs/LibFuzzer.html

How-To Use:

$ mkdir build && cd build
$ CC=clang CXX=clang++ cmake -DENABLE_FUZZER=ON -DENABLE_ASAN=ON -DCMAKE_BUILD_TYPE=Debug ..
$ make fuzzers
$ ./test/fuzz/csv_fuzzer -max_total_time=60*60*60 -workers=4 ../test/static/corpus/csv

Part of #1809
---
 CMakeLists.txt                 |  2 +-
 cmake/profile.cmake            | 13 ++++++++++
 test/CMakeLists.txt            |  3 +++
 test/fuzz/CMakeLists.txt       | 45 ++++++++++++++++++++++++++++++++++
 test/fuzz/csv_fuzzer.c         | 23 +++++++++++++++++
 test/fuzz/http_parser_fuzzer.c | 18 ++++++++++++++
 test/fuzz/uri_fuzzer.c         | 19 ++++++++++++++
 7 files changed, 122 insertions(+), 1 deletion(-)
 create mode 100644 test/fuzz/CMakeLists.txt
 create mode 100644 test/fuzz/csv_fuzzer.c
 create mode 100644 test/fuzz/http_parser_fuzzer.c
 create mode 100644 test/fuzz/uri_fuzzer.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index fa6818f8e..8bc6f22bd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -607,7 +607,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_UB_SANITIZER
+    ENABLE_GCOV ENABLE_GPROF ENABLE_VALGRIND ENABLE_ASAN ENABLE_UB_SANITIZER ENABLE_FUZZER
     ENABLE_BACKTRACE
     ENABLE_DOC
     ENABLE_DIST
diff --git a/cmake/profile.cmake b/cmake/profile.cmake
index bc4bf67f5..45e3d112c 100644
--- a/cmake/profile.cmake
+++ b/cmake/profile.cmake
@@ -42,6 +42,19 @@ else()
     add_definitions(-DNVALGRIND=1)
 endif()
 
+option(OSS_FUZZ "Set this option to use flags by oss-fuzz" OFF)
+option(ENABLE_FUZZER "Enable fuzzing testing" OFF)
+if(ENABLE_FUZZER)
+    if(CMAKE_COMPILER_IS_GNUCC)
+        message(FATAL_ERROR
+            "\n"
+            "Fuzzing is unsupported with GCC compiler. Use Clang:\n"
+            " $ git clean -xfd; git submodule foreach --recursive git clean -xfd\n"
+            " $ CC=clang CXX=clang++ cmake . <...> -DENABLE_FUZZER=ON && make -j\n"
+            "\n")
+    endif()
+endif()
+
 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/test/CMakeLists.txt b/test/CMakeLists.txt
index 10882c6a1..d20a4eb5d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -75,6 +75,9 @@ add_subdirectory(app-tap)
 add_subdirectory(box)
 add_subdirectory(box-tap)
 add_subdirectory(unit)
+if(ENABLE_FUZZER)
+    add_subdirectory(fuzz)
+endif()
 add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/luajit/test
                  ${PROJECT_BINARY_DIR}/third_party/luajit/test)
 
diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt
new file mode 100644
index 000000000..142d38f67
--- /dev/null
+++ b/test/fuzz/CMakeLists.txt
@@ -0,0 +1,45 @@
+include_directories(${PROJECT_SOURCE_DIR}/src)
+include_directories(${PROJECT_BINARY_DIR}/src)
+include_directories(${PROJECT_SOURCE_DIR}/src/box)
+
+# A special target with fuzzer and sanitizer flags.
+add_library(fuzzer_config INTERFACE)
+
+target_compile_options(
+    fuzzer_config
+    INTERFACE
+        $<$<BOOL:${ENABLE_ASAN}>:
+        -fsanitize=fuzzer,address
+        >
+        $<$<BOOL:${ENABLE_UB_SANITIZER}>:
+        -fsanitize=fuzzer,undefined
+        >
+)
+target_link_libraries(
+    fuzzer_config
+    INTERFACE
+        $<$<BOOL:${ENABLE_ASAN}>:
+        -fsanitize=fuzzer,address
+        >
+        $<$<BOOL:${ENABLE_UB_SANITIZER}>:
+        -fsanitize=fuzzer,undefined
+        >
+)
+
+# Use PUBLIC to force 'fuzzer_config' for all dependent targets.
+add_executable(csv_fuzzer csv_fuzzer.c)
+target_link_libraries(csv_fuzzer PUBLIC csv fuzzer_config)
+
+add_executable(uri_fuzzer uri_fuzzer.c)
+target_link_libraries(uri_fuzzer PUBLIC uri fuzzer_config)
+
+add_executable(http_parser_fuzzer http_parser_fuzzer.c)
+target_link_libraries(http_parser_fuzzer PUBLIC http_parser fuzzer_config)
+
+set(fuzzing_binaries csv_fuzzer
+		http_parser_fuzzer
+		uri_fuzzer)
+
+add_custom_target(fuzzers
+                  DEPENDS ${fuzzing_binaries}
+                  COMMENT "Build fuzzers")
diff --git a/test/fuzz/csv_fuzzer.c b/test/fuzz/csv_fuzzer.c
new file mode 100644
index 000000000..8853d6308
--- /dev/null
+++ b/test/fuzz/csv_fuzzer.c
@@ -0,0 +1,23 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include "csv/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);
+        int rc = csv_get_error_status(&csv) == CSV_ER_INVALID ? 1 : 0;
+        csv_destroy(&csv);
+        free(buf);
+
+        return rc;
+}
diff --git a/test/fuzz/http_parser_fuzzer.c b/test/fuzz/http_parser_fuzzer.c
new file mode 100644
index 000000000..a0aaf6786
--- /dev/null
+++ b/test/fuzz/http_parser_fuzzer.c
@@ -0,0 +1,18 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include "http_parser/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);
+
+        return rc;
+}
diff --git a/test/fuzz/uri_fuzzer.c b/test/fuzz/uri_fuzzer.c
new file mode 100644
index 000000000..8397505bd
--- /dev/null
+++ b/test/fuzz/uri_fuzzer.c
@@ -0,0 +1,19 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include "uri/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);
+
+        return rc;
+}
-- 
2.25.1

  reply	other threads:[~2020-11-30 20:25 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-30 20:24 [Tarantool-patches] [PATCH 0/4] Add fuzzing testing sergeyb
2020-11-30 20:24 ` sergeyb [this message]
2020-12-07 17:24   ` [Tarantool-patches] [PATCH 1/4] test: add infrastructure for fuzzing testing and fuzzers Igor Munkin
2020-12-07 19:54     ` Igor Munkin
2020-12-13 18:56     ` Sergey Bronnikov
2020-12-20 13:31       ` Igor Munkin
2020-12-24 10:18         ` Sergey Bronnikov
2020-12-24 13:22           ` Igor Munkin
2020-12-24 17:25             ` Sergey Bronnikov
2020-12-24 17:50               ` Igor Munkin
2020-12-25  7:07                 ` Sergey Bronnikov
2020-12-25  9:02                   ` Igor Munkin
2020-12-25 10:33                     ` Sergey Bronnikov
2020-11-30 20:24 ` [Tarantool-patches] [PATCH 2/4] test: add corpus to be used with fuzzers sergeyb
2020-12-07 17:34   ` Igor Munkin
2020-12-13 18:56     ` Sergey Bronnikov
2020-11-30 20:24 ` [Tarantool-patches] [PATCH 3/4] travis: build tarantool with ENABLE_FUZZER sergeyb
2020-12-07 17:38   ` Igor Munkin
2020-11-30 20:24 ` [Tarantool-patches] [PATCH 4/4] test: integrate with OSS Fuzz sergeyb
2020-12-07 17:42   ` Igor Munkin
2020-12-01 10:54 ` [Tarantool-patches] [PATCH 0/4] Add fuzzing testing Serge Petrenko
2020-12-01 14:41   ` Sergey Bronnikov
2020-12-01 14:45     ` Serge Petrenko
2020-12-07 17:49 ` Igor Munkin
2020-12-25 13:08 ` Igor Munkin
2020-12-25 14:52 ` Kirill Yukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ce3bb1f82c97a2fa077a41640c6ae9f9bf74a1e4.1606766417.git.sergeyb@tarantool.org \
    --to=sergeyb@tarantool.org \
    --cc=imun@tarantool.org \
    --cc=sergepetrenko@tarantool.org \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH 1/4] test: add infrastructure for fuzzing testing and fuzzers' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox