Parcourir la source

Integrate fuzzer into continuous build env

Stefan Profanter il y a 6 ans
Parent
commit
e1246aa354

+ 18 - 11
.travis.yml

@@ -23,6 +23,7 @@ env:
     - ANALYZE=false
     - ANALYZE=true
     - DOCKER=true
+    - FUZZER=true
 
 matrix:
   exclude:
@@ -33,9 +34,14 @@ matrix:
       env: ANALYZE=true
     - os: osx
       env: DOCKER=true
+    - os: osx
+      env: FUZZER=true
     - os: linux
       compiler: clang
       env: DOCKER=true
+    - os: linux
+      compiler: gcc
+      env: FUZZER=true
 
 # Required for docker build test
 services:
@@ -48,25 +54,26 @@ addons:
     packages:
       - binutils-mingw-w64-i686
       - build-essential
-      - cmake
-      - gcc-multilib
-      - g++-multilib
-      - valgrind
       - check
+      - clang-3.9
+      - clang-tidy-3.9
+      - cmake
       - cppcheck
-      - mingw-w64
-      - g++-mingw-w64-x86-64
+      - gcc-multilib
       - g++-mingw-w64-i686
-      - libc6-dbg # for valgrind compilation
+      - g++-mingw-w64-x86-64
+      - g++-multilib
+      - graphviz
       - libsubunit-dev
       - libx11-dev
+      - mingw-w64
+      - texlive-fonts-recommended
+      - texlive-latex-extra
+      - texlive-latex-recommended
+      - valgrind
       - wget
       - xutils-dev
       - zip
-      - graphviz
-      - texlive-latex-recommended
-      - texlive-latex-extra
-      - texlive-fonts-recommended
   coverity_scan:
     project:
       name: "open62541/open62541"

+ 5 - 0
CMakeLists.txt

@@ -113,6 +113,7 @@ endif()
 # Build Targets
 option(UA_BUILD_EXAMPLES "Build example servers and clients" OFF)
 option(UA_BUILD_UNIT_TESTS "Build the unit tests" OFF)
+option(UA_BUILD_FUZZING "Build the fuzzing executables" OFF)
 option(UA_BUILD_EXAMPLES_NODESET_COMPILER "Generate an OPC UA information model from a nodeset XML (experimental)" OFF)
 
 # Advanced Build Targets
@@ -495,6 +496,10 @@ if(UA_BUILD_UNIT_TESTS)
     add_subdirectory(tests)
 endif()
 
+if(UA_BUILD_FUZZING)
+    add_subdirectory(tests/fuzz)
+endif()
+
 ############################
 # Linting run (clang-tidy) #
 ############################

+ 64 - 0
tests/fuzz/CMakeLists.txt

@@ -0,0 +1,64 @@
+include_directories(${PROJECT_SOURCE_DIR}/include)
+include_directories(${PROJECT_SOURCE_DIR}/deps)
+include_directories(${PROJECT_SOURCE_DIR}/src)
+include_directories(${PROJECT_SOURCE_DIR}/src/server)
+include_directories(${PROJECT_SOURCE_DIR}/plugins)
+include_directories(${PROJECT_BINARY_DIR}/src_generated)
+
+remove_definitions(-std=c99 -Wmissing-prototypes -Wstrict-prototypes)
+
+
+if(NOT "x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang")
+    MESSAGE(FATAL_ERROR "To build fuzzing, you need to use Clang as the compiler")
+endif()
+
+if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)
+    MESSAGE(WARNING "You should use at least clang version 5.0 for fuzzing support")
+endif()
+
+if(NOT $ENV{LIB_FUZZER_DIR} STREQUAL "")
+    # specific settings for travis
+    link_directories($ENV{LIB_FUZZER_DIR})
+endif()
+
+set(LIBS Fuzzer ${open62541_LIBRARIES})
+
+#############################
+# Compiled binaries folders #
+#############################
+
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/fuzz)
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=trace-pc-guard")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=trace-pc-guard")
+
+
+# Use different plugins for testing
+set(fuzzing_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/ua_network_tcp.c
+        ${PROJECT_SOURCE_DIR}/plugins/ua_clock.c
+        ${PROJECT_SOURCE_DIR}/plugins/ua_log_stdout.c
+        ${PROJECT_SOURCE_DIR}/plugins/ua_config_standard.c
+        ${PROJECT_SOURCE_DIR}/plugins/ua_accesscontrol_default.c)
+
+add_library(open62541-fuzzplugins OBJECT ${fuzzing_plugin_sources})
+add_dependencies(open62541-fuzzplugins open62541)
+
+
+# the fuzzer test are built directly on the open62541 object files. so they can
+# access symbols that are hidden/not exported to the shared library
+
+add_executable(fuzz_binary_message fuzz_binary_message.cc $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-fuzzplugins>)
+target_include_directories(fuzz_binary_message PRIVATE ${PROJECT_SOURCE_DIR}/src/server)
+target_link_libraries(fuzz_binary_message ${LIBS})
+
+add_custom_target(
+        run_fuzzer
+        COMMAND ${CMAKE_BINARY_DIR}/bin/fuzz/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_Browse.bin
+        COMMAND ${CMAKE_BINARY_DIR}/bin/fuzz/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_CLO.bin
+        COMMAND ${CMAKE_BINARY_DIR}/bin/fuzz/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_CreateActivateSession.bin
+        COMMAND ${CMAKE_BINARY_DIR}/bin/fuzz/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_HELOPN.bin
+        COMMAND ${CMAKE_BINARY_DIR}/bin/fuzz/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_Read.bin
+        COMMAND ${CMAKE_BINARY_DIR}/bin/fuzz/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_Write.bin
+        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+        DEPENDS fuzz_binary_message
+        ${MAYBE_USES_TERMINAL})

+ 5 - 4
tests/fuzz/fuzz_binary_message.c

@@ -9,17 +9,18 @@
 ** Main entry point.  The fuzzer invokes this function with each
 ** fuzzed input.
 */
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
     UA_Connection c = createDummyConnection();
     UA_ServerConfig config = UA_ServerConfig_standard;
     config.logger = UA_Log_Stdout;
     UA_Server *server = UA_Server_new(config);
-    UA_ByteString msg;
+    UA_ByteString msg = {
+			.length = size,
+			.data = const_cast<UA_Byte*>(data)
+	};
 
     config.logger = UA_Log_Stdout;
-    msg.length = size;
-    msg.data = data;
     UA_Boolean reallocated = UA_FALSE;
     UA_StatusCode retval = UA_Connection_completeMessages(&c, &msg, &reallocated);
     if(retval == UA_STATUSCODE_GOOD && msg.length > 0)

+ 1 - 1
tests/fuzz/fuzz_common.h

@@ -14,7 +14,7 @@
 
 static UA_StatusCode
 dummyGetSendBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
-    buf->data = malloc(length);
+    buf->data = (UA_Byte*)malloc(length);
     buf->length = length;
     return UA_STATUSCODE_GOOD;
 }

+ 0 - 16
tests/fuzz/hex2bin.sh

@@ -1,16 +0,0 @@
-#!/bin/bash
-
-# Convert the .hex files from tests/dumps to binary files so that they can be fed into the fuzzer as corpus
-
-# Read either the first argument or from stdin (http://stackoverflow.com/questions/6980090/bash-read-from-file-or-stdin)
-cat "${1:-/dev/stdin}" | \
-# Strip out comments starting with #
-sed -E 's/#.*$//' | \
-# Strip out comments starting with //
-sed -E 's/\/\/.*$//' | \
-# Strip out multi-line comments /* ... */
-perl -0777 -pe 's{/\*.*?\*/}{}gs' | \
-# Strip out all non hexadecimal characters
-sed -E 's/[^0-9a-fA-F]*//g' | \
-# Convert hex to binary using xxd's reverser in plain hexdump style
-xxd -r -ps

+ 13 - 3
tools/travis/travis_linux_before_install.sh

@@ -1,15 +1,25 @@
 #!/bin/bash
 set -ev
 
+
+if ! [ -z ${FUZZER+x} ]; then
+	# we need libfuzzer 5.0, all the older versions do not work on travis.
+	sudo apt-get --yes install git
+	git clone https://github.com/google/fuzzer-test-suite.git FTS
+	./FTS/tutorial/install-deps.sh  # Get deps
+	./FTS/tutorial/install-clang.sh # Get fresh clang binaries
+	# Get libFuzzer sources and build it
+	svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
+	Fuzzer/build.sh
+	exit 0
+fi
+
 if [ -z ${DOCKER+x} ]; then
 	# Only on non-docker builds required
 
 	echo "=== Installing from external package sources ===" && echo -en 'travis_fold:start:before_install.external\\r'
-	wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
-	echo "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-3.9 main" | sudo tee -a /etc/apt/sources.list
 	sudo add-apt-repository -y ppa:lttng/ppa
 	sudo apt-get update -qq
-	sudo apt-get install -y clang-3.9 clang-tidy-3.9
 	sudo apt-get install -y liburcu4 liburcu-dev
 	echo -en 'travis_fold:end:script.before_install.external\\r'
 

+ 15 - 0
tools/travis/travis_linux_script.sh

@@ -11,6 +11,20 @@ if ! [ -z ${DOCKER+x} ]; then
     exit 0
 fi
 
+# Fuzzer build test
+if ! [ -z ${FUZZER+x} ]; then
+	mkdir -p build && cd build
+	export CC=$TRAVIS_BUILD_DIR/third_party/llvm-build/Release+Asserts/bin/clang
+	export CXX=$TRAVIS_BUILD_DIR/third_party/llvm-build/Release+Asserts/bin/clang++
+	# libFuzzer.a is in the build dir.
+	export LIB_FUZZER_DIR=$TRAVIS_BUILD_DIR
+	cmake -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=ON -DUA_BUILD_FUZZING=ON ..
+	make VERBOSE=1 && make run_fuzzer
+	if [ $? -ne 0 ] ; then exit 1 ; fi
+	cd .. && rm build -rf
+    exit 0
+fi
+
 if [ $ANALYZE = "true" ]; then
     echo "=== Running static code analysis ===" && echo -en 'travis_fold:start:script.analyze\\r'
     if [ "$CC" = "clang" ]; then
@@ -201,4 +215,5 @@ else
         echo -en 'travis_fold:end:script.build.coveralls\\r'
     fi
     cd .. && rm build -rf
+
 fi