From 986ea2b37e5898ed5256be9205fe2913f30d24dd Mon Sep 17 00:00:00 2001 From: ArthurSonzogni Date: Thu, 17 Jun 2021 23:07:26 +0200 Subject: [PATCH] Add fuzzer for termin_input_parser Current state: the fuzzer find interesting input immediately... ``` terminate called after throwing an instance of 'std::range_error' what(): wstring_convert::from_bytes ``` See: https://github.com/ArthurSonzogni/FTXUI/issues/118 --- CMakeLists.txt | 30 +++++++++++++++---- include/ftxui/component/receiver.hpp | 3 +- .../terminal_input_parser_test_fuzz.cpp | 19 ++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 src/ftxui/component/terminal_input_parser_test_fuzz.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e6eb51a..fce83fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,12 +18,11 @@ project(ftxui VERSION 0.6.${git_version} ) -option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON) -option(FTXUI_ENABLE_INSTALL "Generate the install target" ON) -option(FTXUI_BUILD_TESTS "Set to ON to build tests" OFF) option(FTXUI_BUILD_DOCS "Set to ON to build tests" ON) - -enable_testing() +option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON) +option(FTXUI_BUILD_TESTS "Set to ON to build tests" OFF) +option(FTXUI_BUILD_TESTS_FUZZER "Set to ON to enable fuzzing" OFF) +option(FTXUI_ENABLE_INSTALL "Generate the install target" ON) find_package(Threads) @@ -209,6 +208,7 @@ export(TARGETS screen dom component NAMESPACE ftxui:: if (FTXUI_BUILD_TESTS AND ${CMAKE_VERSION} VERSION_GREATER "3.11.4") + enable_testing() set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE) @@ -254,6 +254,26 @@ if (FTXUI_BUILD_TESTS AND ${CMAKE_VERSION} VERSION_GREATER "3.11.4") ) set_property(TARGET tests PROPERTY CXX_STANDARD 17) + + if (FTXUI_BUILD_TESTS_FUZZER) + set(CMAKE_C_COMPILER clang) + set(CMAKE_CXX_COMPILER clang++) + add_executable(terminal_input_parser_test_fuzz + src/ftxui/component/terminal_input_parser_test_fuzz.cpp + ) + target_include_directories(terminal_input_parser_test_fuzz + PRIVATE src + ) + target_link_libraries(terminal_input_parser_test_fuzz + PRIVATE component + ) + target_compile_options(terminal_input_parser_test_fuzz + PRIVATE -fsanitize=fuzzer,address + ) + target_link_libraries(terminal_input_parser_test_fuzz + PRIVATE -fsanitize=fuzzer,address + ) + endif() endif() if(FTXUI_BUILD_EXAMPLES) diff --git a/include/ftxui/component/receiver.hpp b/include/ftxui/component/receiver.hpp index 2f35f44..c41c7e8 100644 --- a/include/ftxui/component/receiver.hpp +++ b/include/ftxui/component/receiver.hpp @@ -70,6 +70,7 @@ class ReceiverImpl { senders_++; return std::unique_ptr>(new SenderImpl(this)); } + ReceiverImpl() { senders_ = 0; } bool Receive(T* t) { while (senders_ || !queue_.empty()) { @@ -109,7 +110,7 @@ class ReceiverImpl { std::mutex mutex_; std::queue queue_; std::condition_variable notifier_; - std::atomic senders_ = 0; + std::atomic senders_; }; template diff --git a/src/ftxui/component/terminal_input_parser_test_fuzz.cpp b/src/ftxui/component/terminal_input_parser_test_fuzz.cpp new file mode 100644 index 0000000..a1897a7 --- /dev/null +++ b/src/ftxui/component/terminal_input_parser_test_fuzz.cpp @@ -0,0 +1,19 @@ +//#include "ftxui/component/event.hpp" +//#include "ftxui/component/receiver.hpp" +#include "ftxui/component/terminal_input_parser.hpp" +#include + +extern "C" int LLVMFuzzerTestOneInput(const char* data, size_t size) { + using namespace ftxui; + auto event_receiver = MakeReceiver(); + { + auto parser = TerminalInputParser(event_receiver->MakeSender()); + for (size_t i = 0; i < size; ++i) + parser.Add(data[i]); + } + + Event received; + while (event_receiver->Receive(&received)) + ; + return 0; // Non-zero return values are reserved for future use. +}