Browse Source

Add fuzz corpus generator from unit tests and integrate into CI

Stefan Profanter 6 years ago
parent
commit
32fc345337
54 changed files with 339 additions and 298 deletions
  1. 1 7
      CMakeLists.txt
  2. 19 63
      tests/CMakeLists.txt
  3. 0 8
      tests/dumps/client_Browse.hex
  4. 0 5
      tests/dumps/client_CLO.hex
  5. 0 19
      tests/dumps/client_CreateActivateSession.hex
  6. 0 13
      tests/dumps/client_HELOPN.hex
  7. 0 8
      tests/dumps/client_Read.hex
  8. 0 7
      tests/dumps/client_Write.hex
  9. 20 2
      tests/fuzz/CMakeLists.txt
  10. 35 0
      tests/fuzz/README.md
  11. 6 144
      tools/corpus_generator/corpus_generator.c
  12. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00001_hel.bin
  13. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00002_opn.bin
  14. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00003_msg_GetEndpointsRequest.bin
  15. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00004_msg_CreateSessionRequest.bin
  16. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00005_msg_ActivateSessionRequest.bin
  17. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00006_msg_FindServersRequest.bin
  18. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00007_msg_FindServersOnNetworkRequest.bin
  19. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00008_msg_RegisterServerRequest.bin
  20. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00009_msg_RegisterServer2Request.bin
  21. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00010_msg_BrowseRequest.bin
  22. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00011_msg_BrowseNextRequest.bin
  23. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00012_msg_BrowseNextRequest.bin
  24. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00013_msg_BrowseNextRequest.bin
  25. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00014_msg_RegisterNodesRequest.bin
  26. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00015_msg_UnregisterNodesRequest.bin
  27. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00016_msg_TranslateBrowsePathsToNodeIdsRequest.bin
  28. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00017_msg_CreateSubscriptionRequest.bin
  29. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00018_msg_ModifySubscriptionRequest.bin
  30. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00019_msg_SetPublishingModeRequest.bin
  31. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00020_msg_CreateMonitoredItemsRequest.bin
  32. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00021_msg_PublishRequest.bin
  33. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00022_msg_RepublishRequest.bin
  34. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00023_msg_ModifyMonitoredItemsRequest.bin
  35. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00024_msg_SetMonitoringModeRequest.bin
  36. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00025_msg_DeleteMonitoredItemsRequest.bin
  37. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00026_msg_DeleteSubscriptionsRequest.bin
  38. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00027_msg_CallRequest.bin
  39. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00028_msg_AddNodesRequest.bin
  40. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00029_msg_AddReferencesRequest.bin
  41. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00030_msg_DeleteReferencesRequest.bin
  42. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00031_msg_DeleteNodesRequest.bin
  43. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00032_msg_CloseSessionRequest.bin
  44. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00033_clo.bin
  45. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00034_hel.bin
  46. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00035_opn.bin
  47. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00036_msg_GetEndpointsRequest.bin
  48. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00037_msg_CreateSessionRequest.bin
  49. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00038_msg_ActivateSessionRequest.bin
  50. BIN
      tests/fuzz/fuzz_binary_message_corpus/generated/00039_clo.bin
  51. 64 0
      tests/fuzz/generate_corpus.sh
  52. 189 0
      tests/fuzz/ua_debug_dump_pkgs_file.c
  53. 0 17
      tools/corpus_generator/CMakeLists.txt
  54. 5 5
      tools/travis/travis_linux_script.sh

+ 1 - 7
CMakeLists.txt

@@ -643,19 +643,13 @@ if(UA_BUILD_UNIT_TESTS)
     add_subdirectory(tests)
 endif()
 
-if(UA_BUILD_FUZZING OR UA_BUILD_OSS_FUZZ)
+if(UA_BUILD_FUZZING OR UA_BUILD_OSS_FUZZ OR UA_BUILD_FUZZING_CORPUS)
     # Force enable discovery, to also fuzzy-test this code
     set(UA_ENABLE_DISCOVERY ON CACHE STRING "" FORCE)
     set(UA_ENABLE_DISCOVERY_MULTICAST ON CACHE STRING "" FORCE)
     add_subdirectory(tests/fuzz)
 endif()
 
-
-if(UA_BUILD_FUZZING_CORPUS)
-    add_subdirectory(tools/corpus_generator)
-endif()
-
-
 ############################
 # Linting run (clang-tidy) #
 ############################

+ 19 - 63
tests/CMakeLists.txt

@@ -67,6 +67,11 @@ macro(add_test_valgrind TEST_NAME)
     else()
         add_test(${TEST_NAME} ${ARGN})
     endif()
+    if (UA_BUILD_FUZZING_CORPUS)
+        target_sources(check_${TEST_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/tests/fuzz/ua_debug_dump_pkgs_file.c)
+        file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/corpus/${TEST_NAME})
+        target_compile_definitions(check_${TEST_NAME} PRIVATE UA_CORPUS_OUTPUT_DIR="${PROJECT_BINARY_DIR}/corpus/${TEST_NAME}")
+    endif()
 endmacro()
 
 add_custom_target(test-verbose COMMAND ${CMAKE_CTEST_COMMAND} --verbose)
@@ -96,13 +101,13 @@ add_test_valgrind(chunking ${TESTS_BINARY_DIR}/check_chunking)
 
 add_executable(check_utils check_utils.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_utils ${LIBS})
-add_test_valgrind(check_utils ${TESTS_BINARY_DIR}/check_utils)
+add_test_valgrind(utils ${TESTS_BINARY_DIR}/check_utils)
 
 # Test Server
 
 add_executable(check_accesscontrol server/check_accesscontrol.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_accesscontrol ${LIBS})
-add_test_valgrind(check_accesscontrol ${TESTS_BINARY_DIR}/check_accesscontrol)
+add_test_valgrind(accesscontrol ${TESTS_BINARY_DIR}/check_accesscontrol)
 
 add_executable(check_services_view server/check_services_view.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_services_view ${LIBS})
@@ -118,7 +123,7 @@ add_test_valgrind(services_nodemanagement ${TESTS_BINARY_DIR}/check_services_nod
 
 add_executable(check_services_subscriptions server/check_services_subscriptions.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_services_subscriptions ${LIBS})
-add_test_valgrind(check_services_subscriptions ${TESTS_BINARY_DIR}/check_services_subscriptions)
+add_test_valgrind(services_subscriptions ${TESTS_BINARY_DIR}/check_services_subscriptions)
 
 add_executable(check_nodestore server/check_nodestore.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_nodestore ${LIBS})
@@ -130,15 +135,15 @@ add_test_valgrind(session ${TESTS_BINARY_DIR}/check_session)
 
 add_executable(check_server_jobs server/check_server_jobs.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_server_jobs ${LIBS})
-add_test_valgrind(check_server_jobs ${TESTS_BINARY_DIR}/check_server_jobs)
+add_test_valgrind(server_jobs ${TESTS_BINARY_DIR}/check_server_jobs)
 
 add_executable(check_server_userspace server/check_server_userspace.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_server_userspace ${LIBS})
-add_test_valgrind(check_server_userspace ${TESTS_BINARY_DIR}/check_server_userspace)
+add_test_valgrind(server_userspace ${TESTS_BINARY_DIR}/check_server_userspace)
 
 add_executable(check_node_inheritance server/check_node_inheritance.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_node_inheritance ${LIBS})
-add_test_valgrind(check_node_inheritance ${TESTS_BINARY_DIR}/check_node_inheritance)
+add_test_valgrind(node_inheritance ${TESTS_BINARY_DIR}/check_node_inheritance)
 
 if(UA_ENABLE_DISCOVERY)
     add_executable(check_discovery server/check_discovery.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
@@ -149,78 +154,29 @@ endif()
 # Readspeed server
 add_executable(check_server_readspeed server/check_server_readspeed.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_server_readspeed ${LIBS})
-add_test_valgrind(check_server_readspeed ${TESTS_BINARY_DIR}/check_server_readspeed)
-
-# Test server with network dumps from files
-
-add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin
-                          ${CMAKE_CURRENT_BINARY_DIR}/client_CLO.bin
-                          ${CMAKE_CURRENT_BINARY_DIR}/client_CreateActivateSession.bin
-                          ${CMAKE_CURRENT_BINARY_DIR}/client_Browse.bin
-                          ${CMAKE_CURRENT_BINARY_DIR}/client_Read.bin
-                          ${CMAKE_CURRENT_BINARY_DIR}/client_Write.bin
-                  PRE_BUILD
-                  COMMAND python ${PROJECT_SOURCE_DIR}/tools/hex2bin.py
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_HELOPN.hex
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_CLO.hex
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_CreateActivateSession.hex
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_Browse.hex
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_Read.hex
-                                 ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_Write.hex
-                  DEPENDS ${PROJECT_SOURCE_DIR}/tools/hex2bin.py
-                          ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_HELOPN.hex
-                          ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_CLO.hex
-                          ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_CreateActivateSession.hex
-                          ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_Browse.hex
-                          ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_Read.hex
-                          ${CMAKE_CURRENT_SOURCE_DIR}/dumps/client_Write.hex)
-add_custom_target(client_HELOPN.bin DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin")
-add_custom_target(client_CreateActivateSession.bin DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/client_CreateActivateSession.bin")
-
-add_executable(check_server_binary_messages server/check_server_binary_messages.c testing-plugins/testing_networklayers.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
-target_include_directories(check_server_binary_messages PRIVATE ${PROJECT_SOURCE_DIR}/src/server)
-target_link_libraries(check_server_binary_messages ${LIBS})
-add_dependencies(check_server_binary_messages client_HELOPN.bin)
-
-add_test_valgrind(check_server_binary_messages_browse ${TESTS_BINARY_DIR}/check_server_binary_messages
-                                             ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin
-                                             ${CMAKE_CURRENT_BINARY_DIR}/client_CreateActivateSession.bin
-                                             ${CMAKE_CURRENT_BINARY_DIR}/client_Browse.bin
-                                             ${CMAKE_CURRENT_BINARY_DIR}/client_CLO.bin)
-
-add_test_valgrind(check_server_binary_messages_read ${TESTS_BINARY_DIR}/check_server_binary_messages
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_CreateActivateSession.bin
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_Read.bin
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_CLO.bin)
-
-add_test_valgrind(check_server_binary_messages_write ${TESTS_BINARY_DIR}/check_server_binary_messages
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_HELOPN.bin
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_CreateActivateSession.bin
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_Write.bin
-                                           ${CMAKE_CURRENT_BINARY_DIR}/client_CLO.bin)
+add_test_valgrind(server_readspeed ${TESTS_BINARY_DIR}/check_server_readspeed)
 
 # Test Client
 
 add_executable(check_client client/check_client.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client ${LIBS})
-add_test_valgrind(check_client ${TESTS_BINARY_DIR}/check_client)
+add_test_valgrind(client ${TESTS_BINARY_DIR}/check_client)
 
 add_executable(check_client_securechannel client/check_client_securechannel.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client_securechannel ${LIBS})
-add_test_valgrind(check_client_securechannel ${TESTS_BINARY_DIR}/check_client_securechannel)
+add_test_valgrind(client_securechannel ${TESTS_BINARY_DIR}/check_client_securechannel)
 
 add_executable(check_client_async client/check_client_async.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client_async ${LIBS})
-add_test_valgrind(check_client_async ${TESTS_BINARY_DIR}/check_client_async)
+add_test_valgrind(client_async ${TESTS_BINARY_DIR}/check_client_async)
 
 add_executable(check_client_subscriptions client/check_client_subscriptions.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client_subscriptions ${LIBS})
-add_test_valgrind(check_client_subscriptions ${TESTS_BINARY_DIR}/check_client_subscriptions)
+add_test_valgrind(client_subscriptions ${TESTS_BINARY_DIR}/check_client_subscriptions)
 
 add_executable(check_client_highlevel client/check_client_highlevel.c $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
 target_link_libraries(check_client_highlevel ${LIBS})
-add_test_valgrind(check_client_highlevel ${TESTS_BINARY_DIR}/check_client_highlevel)
+add_test_valgrind(client_highlevel ${TESTS_BINARY_DIR}/check_client_highlevel)
 
 #############################
 #                           #
@@ -362,7 +318,7 @@ if (UA_ENABLE_FULL_NS0)
                    $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
     add_dependencies(check_nodeset_compiler_adi open62541-generator-tests-ns-adi)
     target_link_libraries(check_nodeset_compiler_adi ${LIBS})
-    add_test_valgrind(check_nodeset_compiler_adi ${TESTS_BINARY_DIR}/check_nodeset_compiler_adi)
+    add_test_valgrind(nodeset_compiler_adi ${TESTS_BINARY_DIR}/check_nodeset_compiler_adi)
 
     add_executable(check_nodeset_compiler_plc
                    server/check_nodeset_compiler_plc.c
@@ -372,5 +328,5 @@ if (UA_ENABLE_FULL_NS0)
                    $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-testplugins>)
     add_dependencies(check_nodeset_compiler_plc open62541-generator-tests-ns-plc)
     target_link_libraries(check_nodeset_compiler_plc ${LIBS})
-    add_test_valgrind(check_nodeset_compiler_plc ${TESTS_BINARY_DIR}/check_nodeset_compiler_plc)
+    add_test_valgrind(nodeset_compiler_plc ${TESTS_BINARY_DIR}/check_nodeset_compiler_plc)
 endif()

+ 0 - 8
tests/dumps/client_Browse.hex

@@ -1,8 +0,0 @@
-4d 53 47 46 71 00 00 00 01 00 00 00 01 00 00 00  /* MSGFq........... */
-04 00 00 00 04 00 00 00 01 00 0f 02 04 01 00 e3  /* ...............H */
-77 d7 1c 90 95 e2 a4 6d b6 4b e4 0e e0 9e b9 9e  /* ....4~..~.l.q.k. */
-90 25 6a 81 bf d1 01 05 00 00 00 00 00 00 00 ff  /* .%j............. */
-ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00  /* ................ */
-00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00  /* ................ */
-00 55 00 00 00 00 00 00 00 00 00 00 00 3f 00 00  /* .U...........?.. */
-00                                               /* . */

+ 0 - 5
tests/dumps/client_CLO.hex

@@ -1,5 +0,0 @@
-43 4c 4f 46 39 00 00 00 01 00 00 00 01 00 00 00  /* CLOF9........... */
-05 00 00 00 05 00 00 00 01 00 c4 01 04 01 00 e3  /* ...............H */
-77 d7 1c 90 95 e2 a4 6d b6 4b e4 0e e0 9e b9 9e  /* ....4~..~.l.q.k. */
-90 25 6a 81 bf d1 01 05 00 00 00 00 00 00 00 ff  /* .%j............. */
-ff ff ff 00 00 00 00 00 00 00 00                 /* ...........      */

+ 0 - 19
tests/dumps/client_CreateActivateSession.hex

@@ -1,19 +0,0 @@
-4d 53 47 46 72 00 00 00 01 00 00 00 01 00 00 00  /* MSGFr........... */
-02 00 00 00 02 00 00 00 01 00 cd 01 00 00 92 6a  /* ...............j */
-25 6a 81 bf d1 01 02 00 00 00 00 00 00 00 ff ff  /* %j.............. */
-ff ff 10 27 00 00 00 00 00 ff ff ff ff ff ff ff  /* ...'............ */
-ff 00 00 00 00 00 ff ff ff ff ff ff ff ff ff ff  /* ................ */
-ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  /* ................ */
-ff ff ff ff ff ff 00 00 00 00 80 4f 32 41 ff ff  /* ...........O2A.. */
-ff 7f                                            /* .. */
-4d 53 47 46 a1 00 00 00 01 00 00 00 01 00 00 00  /* MSGF............ */
-03 00 00 00 03 00 00 00 01 00 d3 01 04 01 00 e3  /* ...............H */
-77 d7 1c 90 95 e2 a4 6d b6 4b e4 0e e0 9e b9 84  /* ....4~..~.l.q.k. */
-78 25 6a 81 bf d1 01 04 00 00 00 00 00 00 00 ff  /* x%j............. */
-ff ff ff c0 27 09 00 00 00 00 ff ff ff ff ff ff  /* ....'........... */
-ff ff ff ff ff ff ff ff ff ff 01 00 44 01 01 36  /* ............D..6 */
-00 00 00 19 00 00 00 6f 70 65 6e 36 32 35 34 31  /* .......open62541 */
-2d 75 73 65 72 6e 61 6d 65 2d 70 6f 6c 69 63 79  /* -username-policy */
-05 00 00 00 75 73 65 72 31 08 00 00 00 70 61 73  /* ....user1....pas */
-73 77 6f 72 64 ff ff ff ff ff ff ff ff ff ff ff  /* sword........... */
-ff                                               /* . */

+ 0 - 13
tests/dumps/client_HELOPN.hex

@@ -1,13 +0,0 @@
-48 45 4c 46 38 00 00 00 00 00 00 00 00 00 01 00  /* HELF8........... */
-00 00 01 00 00 00 00 01 88 13 00 00 18 00 00 00  /* ................ */
-6f 70 63 2e 74 63 70 3a 2f 2f 6c 6f 63 61 6c 68  /* opc.tcp://localh */
-6f 73 74 3a 34 38 34 32                          /* ost:4842         */
-4f 50 4e 46 85 00 00 00 00 00 00 00 2f 00 00 00  /* OPNF......../... */
-68 74 74 70 3a 2f 2f 6f 70 63 66 6f 75 6e 64 61  /* http://opcfounda */
-74 69 6f 6e 2e 6f 72 67 2f 55 41 2f 53 65 63 75  /* tion.org/UA/Secu */
-72 69 74 79 50 6f 6c 69 63 79 23 4e 6f 6e 65 ff  /* rityPolicy#None. */
-ff ff ff ff ff ff ff 01 00 00 00 01 00 00 00 01  /* .......3........ */
-00 be 01 00 00 97 db 02 02 a8 d2 ce 01 00 00 00  /* ................ */
-00 00 00 00 00 ff ff ff ff 00 00 00 00 00 00 00  /* ................ */
-00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00  /* ................ */
-00 e0 93 04 00                                   /* .....            */

+ 0 - 8
tests/dumps/client_Read.hex

@@ -1,8 +0,0 @@
-4d 53 47 46 79 00 00 00 01 00 00 00 01 00 00 00  /* MSGFq........... */
-04 00 00 00 04 00 00 00 01 00 77 02 04 01 00 e3  /* ...............H */
-77 d7 1c 90 95 e2 a4 6d b6 4b e4 0e e0 9e b9 9e  /* ....4~..~.l.q.k. */
-90 25 6a 81 bf d1 01 05 00 00 00 00 00 00 00 ff  /* .%j............. */
-ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00  /* ................ */
-00 00 00 00 00 00 01 00 00 00 03 01 00 0a 00 00  /* ................ */
-00 74 68 65 2e 61 6e 73 77 65 72 0d 00 00 00 ff  /* .the.answer..... */
-ff ff ff 00 00 ff ff ff ff                       /* ......... */

+ 0 - 7
tests/dumps/client_Write.hex

@@ -1,7 +0,0 @@
-4d 53 47 46 6d 00 00 00 01 00 00 00 01 00 00 00  /* MSGFm........... */
-04 00 00 00 04 00 00 00 01 00 a1 02 04 01 00 e3  /* ...............H */
-77 d7 1c 90 95 e2 a4 6d b6 4b e4 0e e0 9e b9 ba  /* ....4~..~.l.q.k. */
-0f 26 6a 81 bf d1 01 0b 00 00 00 00 00 00 00 ff  /* .&j............. */
-ff ff ff 00 00 00 00 00 00 00 01 00 00 00 03 01  /* ................ */
-00 0a 00 00 00 74 68 65 2e 61 6e 73 77 65 72 0d  /* .....the.answer. */
-00 00 00 ff ff ff ff 01 06 2b 00 00 00           /* .........+...    */

+ 20 - 2
tests/fuzz/CMakeLists.txt

@@ -6,6 +6,24 @@ include_directories(${PROJECT_SOURCE_DIR}/plugins)
 include_directories(${PROJECT_SOURCE_DIR}/tests/testing-plugins)
 include_directories(${PROJECT_BINARY_DIR}/src_generated)
 
+
+
+if (UA_BUILD_FUZZING_CORPUS)
+    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
+    add_definitions(-DUA_CORPUS_OUTPUT_DIR="${PROJECT_BINARY_DIR}/corpus/custom")
+    file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/corpus/custom)
+
+    add_executable(corpus_generator ua_debug_dump_pkgs_file.c corpus_generator.c)
+    target_link_libraries(corpus_generator open62541 ${open62541_LIBRARIES})
+    assign_source_group(corpus_generator)
+    add_dependencies(corpus_generator open62541-amalgamation-header)
+    set_target_properties(corpus_generator PROPERTIES FOLDER "open62541/corpus_generator")
+    set_target_properties(corpus_generator PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+    return()
+endif()
+
+
 remove_definitions(-std=c99 -Wmissing-prototypes -Wstrict-prototypes)
 set (CMAKE_CXX_STANDARD 11)
 
@@ -62,7 +80,7 @@ endmacro()
 add_fuzzer(fuzz_binary_message fuzz_binary_message.cc)
 add_fuzzer(fuzz_binary_decode fuzz_binary_decode.cc)
 
-file(GLOB CORPUS_FILES ${PROJECT_SOURCE_DIR}/tests/fuzz/fuzz_binary_message_corpus/generated/*.bin)
+file(GLOB CORPUS_FILES ${PROJECT_SOURCE_DIR}/tests/fuzz/fuzz_binary_message_corpus/generated/*)
 
 set(CORPUS_CMDS)
 
@@ -76,4 +94,4 @@ add_custom_target(
         ${CORPUS_CMDS}
         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
         DEPENDS ${FUZZER_TARGETS}
-        ${MAYBE_USES_TERMINAL})
+        ${MAYBE_USES_TERMINAL})

+ 35 - 0
tests/fuzz/README.md

@@ -0,0 +1,35 @@
+I Can haz fuzz
+==============
+
+open62541 is continuously tested with the awesome oss-fuzz project from Google:
+https://github.com/google/oss-fuzz
+
+Currently tested is processing of binary messages and encoding/decoding of
+binary encoded data.
+
+# Status
+
+* [Build status](https://oss-fuzz-build-logs.storage.googleapis.com/index.html)
+* [Open issues](https://bugs.chromium.org/p/oss-fuzz/issues/list?q=label:Proj-open62541)
+
+# Update the corpus
+
+To update the current corpus used for fuzzing you need to follow these steps.
+It will execute all the unit tests, dump the received data packages to a directory
+and then update and merge the corpus.
+
+1. The script will create two directories: `open62541/build_fuzz` and `open62541/build_corpus`.
+   Make sure that these directories are not existing or do not contain any important data.
+
+2. Run the generate script:
+
+   `open62541/tests/fuzz/generate_corpus.sh`
+   
+   This script will build all the unit tests, dump the packages and then merge the current 
+   corpus with the new packages. 
+    
+3. If there is new coverage with the generated data there will be new files in the directory:
+
+   `open62541/fuzz/fuzz_binary_message_corpus/generated`
+   
+   Commit the new files and then you can delete the build directories created in step 1.

+ 6 - 144
tools/corpus_generator/corpus_generator.c

@@ -21,152 +21,11 @@
 #include <sys/stat.h>
 #include <server/ua_server_internal.h>
 #include <dirent.h>
-#include <src_generated/ua_types_generated.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <ua_client_highlevel.h>
 
-#include "ua_server.h"
-#include "ua_client.h"
 #include "ua_config_default.h"
-#include "ua_client_highlevel.h"
-#include "ua_network_tcp.h"
-#include "ua_transport_generated.h"
-#include "ua_transport_generated_encoding_binary.h"
-#include "ua_securechannel.h"
-#include "ua_types_generated_encoding_binary.h"
-#include "server/ua_services.h"
-
-unsigned int chunkCount = 0;
-
-char dumpOutputFile[255];
-
-char *messageTypes[] = {"ack", "hel", "msg", "opn", "clo", "err", "unk"};
-char *messageTypePrefix = NULL;
-char requestServiceName[200];
-
-void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection, UA_ByteString *messageBuffer);
-
-static void setMessageTypePrefix(UA_UInt32 messageType) {
-    switch(messageType & 0x00ffffff) {
-        case UA_MESSAGETYPE_ACK:
-            messageTypePrefix = messageTypes[0];
-            break;
-        case UA_MESSAGETYPE_HEL:
-            messageTypePrefix = messageTypes[1];
-            break;
-        case UA_MESSAGETYPE_MSG:
-            messageTypePrefix = messageTypes[2];
-            break;
-        case UA_MESSAGETYPE_OPN:
-            messageTypePrefix = messageTypes[3];
-            break;
-        case UA_MESSAGETYPE_CLO:
-            messageTypePrefix = messageTypes[4];
-            break;
-        case UA_MESSAGETYPE_ERR:
-            messageTypePrefix = messageTypes[5];
-            break;
-        default:
-            messageTypePrefix = messageTypes[6];
-    }
-}
-
-
-static UA_StatusCode setRequestedServiceName(const UA_ByteString *msg) {
-    /* At 0, the nodeid starts... */
-    size_t offset = 0;
-
-    /* Decode the nodeid */
-    UA_NodeId requestTypeId;
-    UA_StatusCode retval = UA_NodeId_decodeBinary(msg, &offset, &requestTypeId);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-    if(requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC || requestTypeId.namespaceIndex != 0) {
-        snprintf(requestServiceName, 200, "invalid_request_id");
-        return UA_STATUSCODE_BADUNEXPECTEDERROR;
-    }
-
-    const UA_DataType *requestType = NULL;
-
-    for (size_t i=0; i<UA_TYPES_COUNT; i++) {
-        if (UA_TYPES[i].binaryEncodingId == requestTypeId.identifier.numeric) {
-            requestType = &UA_TYPES[i];
-            break;
-        }
-    }
-    if (requestType == NULL) {
-        snprintf(requestServiceName, 200, "invalid_request_no_type");
-        return UA_STATUSCODE_BADUNEXPECTEDERROR;
-    }
-
-    snprintf(requestServiceName, 200, "_%s", requestType->typeName);
-    return UA_STATUSCODE_GOOD;
-}
-
-static UA_StatusCode
-processCompleteChunkWithoutChannel(UA_Server *server, UA_Connection *connection,
-                                   UA_ByteString *message) {
-    size_t offset = 0;
-    UA_TcpMessageHeader tcpMessageHeader;
-    UA_StatusCode retval =
-            UA_TcpMessageHeader_decodeBinary(message, &offset, &tcpMessageHeader);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-
-    setMessageTypePrefix(tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff);
-
-    if ((tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff) == UA_MESSAGETYPE_MSG) {
-        // this should not happen in normal operation
-        UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER, "Got MSG package without channel.");
-        return UA_STATUSCODE_BADUNEXPECTEDERROR;
-    }
-    return UA_STATUSCODE_GOOD;
-}
-
-/* Takes decoded messages starting at the nodeid of the content type. */
-static UA_StatusCode
-processSecureChannelMessage(void *application, UA_SecureChannel *channel,
-                            UA_MessageType messagetype, UA_UInt32 requestId,
-                            const UA_ByteString *message) {
-    //UA_Server *server = (UA_Server*)application;
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    setMessageTypePrefix(messagetype);
-    if (messagetype == UA_MESSAGETYPE_MSG) {
-        setRequestedServiceName(message);
-    }
-    return retval;
-}
-
-
-void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection, UA_ByteString *messageBuffer) {
-
-    messageTypePrefix = NULL;
-    requestServiceName[0] = 0;
-
-    UA_StatusCode retval;
-    if(!connection->channel)
-        retval = processCompleteChunkWithoutChannel(server, connection, messageBuffer);
-    else {
-        // make a backup of the sequence number and reset it, because processChunk increases it
-        UA_UInt32 seqBackup = connection->channel->receiveSequenceNumber;
-        retval = UA_SecureChannel_processChunk(connection->channel, messageBuffer,
-                                               processSecureChannelMessage,
-                                               server);
-        connection->channel->receiveSequenceNumber = seqBackup;
-    }
-
-    snprintf(dumpOutputFile, 255, "%s/%05d_%s%s.bin", UA_CORPUS_OUTPUT_DIR, ++chunkCount, messageTypePrefix ? messageTypePrefix : "", requestServiceName);
-    UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER, "Dumping package %s", dumpOutputFile);
-
-    FILE *write_ptr;
-
-    write_ptr = fopen(dumpOutputFile, "ab");
-
-    fwrite(messageBuffer->data, messageBuffer->length, 1, write_ptr); // write 10 bytes from our buffer
-    fclose(write_ptr);
-}
-
 
 UA_Server *server;
 UA_ServerConfig *config;
@@ -276,7 +135,7 @@ static void initUaRegisterServer(UA_RegisteredServer *requestServer) {
     // create the semaphore
     int fd = open("/tmp/open62541-corpus-semaphore", O_RDWR|O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
     close(fd);
-    requestServer->semaphoreFilePath = UA_STRING_ALLOC("/tmp/open62541-corpus-semaphore");
+    requestServer->semaphoreFilePath = UA_STRING("/tmp/open62541-corpus-semaphore");
 
     requestServer->serverNames = &server->config.applicationDescription.applicationName;
     requestServer->serverNamesSize = 1;
@@ -352,6 +211,8 @@ static UA_StatusCode registerServer2Request(UA_Client *client) {
     UA_free(request.server.discoveryUrls);
     UA_ExtensionObject_delete(request.discoveryConfiguration);
 
+    UA_RegisterServer2Response_deleteMembers(&response);
+
     return UA_STATUSCODE_GOOD;
 }
 
@@ -540,7 +401,7 @@ static UA_StatusCode subscriptionRequests(UA_Client *client) {
     UA_UInt32 monId;
     ASSERT_GOOD(UA_Client_Subscriptions_addMonitoredItem(client, subId, UA_NODEID_NUMERIC(0, 2259),
                                                       UA_ATTRIBUTEID_VALUE, monitoredItemHandler,
-                                                      NULL, &monId));
+                                                      NULL, &monId, 250));
 
     // publishRequest
     ASSERT_GOOD(UA_Client_Subscriptions_manuallySendPublishRequest(client));
@@ -623,6 +484,7 @@ static UA_StatusCode callRequest(UA_Client *client) {
     ASSERT_GOOD(response.responseHeader.serviceResult);
 
     UA_CallResponse_deleteMembers(&response);
+    UA_Variant_deleteMembers(&input);
 
     return UA_STATUSCODE_GOOD;
 }
@@ -701,7 +563,7 @@ int main(void) {
     if (retval != UA_STATUSCODE_GOOD) {
         printf("\n--------- AN ERROR OCCURED ----------\nStatus = %s\n", UA_StatusCode_name(retval));
     } else {
-        printf("\n--------- SUCCESS -------\nThe corpus is stored in %s\nYou manually need to copy them into the direcotry tests/fuss/fuzz_binary_message_corpus/generated", UA_CORPUS_OUTPUT_DIR);
+        printf("\n--------- SUCCESS -------\nThe corpus is stored in %s", UA_CORPUS_OUTPUT_DIR);
     }
     return (int) retval;
 }

BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00001_hel.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00002_opn.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00003_msg_GetEndpointsRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00004_msg_CreateSessionRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00005_msg_ActivateSessionRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00006_msg_FindServersRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00007_msg_FindServersOnNetworkRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00008_msg_RegisterServerRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00009_msg_RegisterServer2Request.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00010_msg_BrowseRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00011_msg_BrowseNextRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00012_msg_BrowseNextRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00013_msg_BrowseNextRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00014_msg_RegisterNodesRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00015_msg_UnregisterNodesRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00016_msg_TranslateBrowsePathsToNodeIdsRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00017_msg_CreateSubscriptionRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00018_msg_ModifySubscriptionRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00019_msg_SetPublishingModeRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00020_msg_CreateMonitoredItemsRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00021_msg_PublishRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00022_msg_RepublishRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00023_msg_ModifyMonitoredItemsRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00024_msg_SetMonitoringModeRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00025_msg_DeleteMonitoredItemsRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00026_msg_DeleteSubscriptionsRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00027_msg_CallRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00028_msg_AddNodesRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00029_msg_AddReferencesRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00030_msg_DeleteReferencesRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00031_msg_DeleteNodesRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00032_msg_CloseSessionRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00033_clo.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00034_hel.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00035_opn.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00036_msg_GetEndpointsRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00037_msg_CreateSessionRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00038_msg_ActivateSessionRequest.bin


BIN
tests/fuzz/fuzz_binary_message_corpus/generated/00039_clo.bin


+ 64 - 0
tests/fuzz/generate_corpus.sh

@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+
+set -e
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+BASE_DIR="$( cd "$DIR/../../" && pwd )"
+
+BUILD_DIR_FUZZ_MODE="$DIR/../../build_fuzz"
+if [ ! -d "$BUILD_DIR_FUZZ_MODE" ]; then
+    mkdir $BUILD_DIR_FUZZ_MODE
+fi
+BUILD_DIR_FUZZ_MODE="$( cd "$DIR/../../build_fuzz" && pwd )"
+
+BUILD_DIR_CORPUS="$DIR/../../build_corpus"
+if [ ! -d "$BUILD_DIR_CORPUS" ]; then
+    mkdir $BUILD_DIR_CORPUS
+fi
+BUILD_DIR_CORPUS="$( cd "$DIR/../../build_corpus" && pwd )"
+
+cd $BUILD_DIR_CORPUS
+if [ -d "$BUILD_DIR_CORPUS/corpus" ]; then
+    rm -rf "$BUILD_DIR_CORPUS/corpus"
+fi
+
+if [ $TRAVIS = true ]; then
+	export CC=clang-3.9
+	export CXX=clang++-3.9
+else
+	export CC=clang-5.0
+	export CXX=clang++-5.0
+fi
+# First build and run the unit tests without any specific fuzz settings
+cmake -DUA_BUILD_FUZZING_CORPUS=ON -DUA_BUILD_UNIT_TESTS=ON ..
+make -j && make test ARGS="-V"
+if [ $? -ne 0 ] ; then exit 1 ; fi
+# Run our special generator
+$BUILD_DIR_CORPUS/bin/corpus_generator
+if [ $? -ne 0 ] ; then exit 1 ; fi
+
+# Now build the fuzzer executables
+cd $BUILD_DIR_FUZZ_MODE
+cmake -DUA_BUILD_FUZZING=ON ..
+make -j
+if [ $? -ne 0 ] ; then exit 1 ; fi
+
+merge_corpus() {
+    local fuzzer="$1"
+    local corpus_existing="$2"
+    local corpus_new="$3"
+
+
+    if [ -d "$corpus_existing" ]; then
+        echo "Merging ${corpus_existing} into ${corpus_new}"
+        "$fuzzer" -merge=1 "$corpus_existing" "${corpus_new}"
+    else
+        echo "Copying ${corpus_new} into ${corpus_existing}"
+        cp -r ${corpus_new} ${corpus_existing}
+    fi
+}
+
+
+merge_corpus $BUILD_DIR_FUZZ_MODE/bin/fuzz_binary_message $BASE_DIR/tests/fuzz/fuzz_binary_message_corpus/generated $BUILD_DIR_CORPUS/corpus
+if [ $? -ne 0 ] ; then exit 1 ; fi

+ 189 - 0
tests/fuzz/ua_debug_dump_pkgs_file.c

@@ -0,0 +1,189 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * This code is used to generate a binary file for every request type
+ * which can be sent from a client to the server.
+ * These files form the basic corpus for fuzzing the server.
+ */
+
+#ifndef UA_DEBUG_DUMP_PKGS_FILE
+#error UA_DEBUG_DUMP_PKGS_FILE must be defined
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ua_types.h>
+#include <server/ua_server_internal.h>
+#include <unistd.h>
+
+#include "ua_transport_generated_encoding_binary.h"
+#include "ua_types_generated_encoding_binary.h"
+
+unsigned int UA_dump_chunkCount = 0;
+
+char *UA_dump_messageTypes[] = {"ack", "hel", "msg", "opn", "clo", "err", "unk"};
+
+struct UA_dump_filename {
+    const char *messageType;
+    char serviceName[100];
+};
+
+void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection, UA_ByteString *messageBuffer);
+
+/**
+ * Gets a pointer to the string representing the given message type from UA_dump_messageTypes.
+ * Used for naming the dumped file.
+ */
+static const char * UA_debug_dumpGetMessageTypePrefix(UA_UInt32 messageType) {
+    switch(messageType & 0x00ffffff) {
+        case UA_MESSAGETYPE_ACK:
+            return UA_dump_messageTypes[0];
+        case UA_MESSAGETYPE_HEL:
+            return UA_dump_messageTypes[1];
+        case UA_MESSAGETYPE_MSG:
+            return UA_dump_messageTypes[2];
+        case UA_MESSAGETYPE_OPN:
+            return UA_dump_messageTypes[3];
+        case UA_MESSAGETYPE_CLO:
+            return UA_dump_messageTypes[4];
+        case UA_MESSAGETYPE_ERR:
+            return UA_dump_messageTypes[5];
+        default:
+            return UA_dump_messageTypes[6];
+    }
+}
+
+/**
+ * Decode the request message type from the given byte string and
+ * set the global requestServiceName variable to the name of the request.
+ * E.g. `GetEndpointsRequest`
+ */
+static UA_StatusCode UA_debug_dumpSetServiceName(const UA_ByteString *msg, char serviceNameTarget[100]) {
+    /* At 0, the nodeid starts... */
+    size_t offset = 0;
+
+    /* Decode the nodeid */
+    UA_NodeId requestTypeId;
+    UA_StatusCode retval = UA_NodeId_decodeBinary(msg, &offset, &requestTypeId);
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
+    if(requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC || requestTypeId.namespaceIndex != 0) {
+        snprintf(serviceNameTarget, 100, "invalid_request_id");
+        return UA_STATUSCODE_BADUNEXPECTEDERROR;
+    }
+
+    const UA_DataType *requestType = NULL;
+
+    for (size_t i=0; i<UA_TYPES_COUNT; i++) {
+        if (UA_TYPES[i].binaryEncodingId == requestTypeId.identifier.numeric) {
+            requestType = &UA_TYPES[i];
+            break;
+        }
+    }
+    if (requestType == NULL) {
+        snprintf(serviceNameTarget, 100, "invalid_request_no_type");
+        return UA_STATUSCODE_BADUNEXPECTEDERROR;
+    }
+
+    snprintf(serviceNameTarget, 100, "_%s", requestType->typeName);
+    return UA_STATUSCODE_GOOD;
+}
+
+/**
+ * We need to decode the given binary message to get the name of the called service.
+ * This method is used if the connection has no channel yet.
+ */
+static UA_StatusCode
+UA_debug_dump_setName_withoutChannel(UA_Server *server, UA_Connection *connection,
+                                   UA_ByteString *message, struct UA_dump_filename* dump_filename) {
+    size_t offset = 0;
+    UA_TcpMessageHeader tcpMessageHeader;
+    UA_StatusCode retval =
+            UA_TcpMessageHeader_decodeBinary(message, &offset, &tcpMessageHeader);
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
+
+    dump_filename->messageType = UA_debug_dumpGetMessageTypePrefix(tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff);
+
+    if ((tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff) == UA_MESSAGETYPE_MSG) {
+        // this should not happen in normal operation
+        UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER, "Got MSG package without channel.");
+        return UA_STATUSCODE_BADUNEXPECTEDERROR;
+    }
+    return UA_STATUSCODE_GOOD;
+}
+
+
+/**
+ * We need to decode the given binary message to get the name of the called service.
+ * This method is used if the connection an established secure channel.
+ *
+ * message is the decoded message starting at the nodeid of the content type.
+ */
+static UA_StatusCode
+UA_debug_dump_setName_withChannel(void *application, UA_SecureChannel *channel,
+                            UA_MessageType messagetype, UA_UInt32 requestId,
+                            const UA_ByteString *message) {
+    struct UA_dump_filename *dump_filename = (struct UA_dump_filename *)application;
+    UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    dump_filename->messageType = UA_debug_dumpGetMessageTypePrefix(messagetype);
+    if (messagetype == UA_MESSAGETYPE_MSG) {
+        UA_debug_dumpSetServiceName(message, dump_filename->serviceName);
+    }
+    return retval;
+}
+
+/**
+ * Called in processCompleteChunk for every complete chunk which is received by the server.
+ *
+ * It will first try to decode the message to get the name of the called service.
+ * When we have a name the message is dumped as binary to that file.
+ * If the file already exists a new file will be created with a counter at the end.
+ */
+void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection, UA_ByteString *messageBuffer) {
+
+    struct UA_dump_filename dump_filename;
+    dump_filename.messageType = NULL;
+    dump_filename.serviceName[0] = 0;
+
+    UA_StatusCode retval;
+    if(!connection->channel)
+        retval = UA_debug_dump_setName_withoutChannel(server, connection, messageBuffer, &dump_filename);
+    else {
+        // make a backup of the sequence number and reset it, because processChunk increases it
+        UA_UInt32 seqBackup = connection->channel->receiveSequenceNumber;
+        retval = UA_SecureChannel_processChunk(connection->channel, messageBuffer,
+                                               UA_debug_dump_setName_withChannel,
+                                               &dump_filename);
+        connection->channel->receiveSequenceNumber = seqBackup;
+    }
+
+    char fileName[250];
+    snprintf(fileName, 255, "%s/%05d_%s%s", UA_CORPUS_OUTPUT_DIR, ++UA_dump_chunkCount, dump_filename.messageType ? dump_filename.messageType : "", dump_filename.serviceName);
+
+
+
+    char dumpOutputFile[255];
+    snprintf(dumpOutputFile, 255, "%s.bin", fileName);
+    {
+        // check if file exists and if yes create a counting filename to avoid overwriting
+        unsigned cnt = 1;
+        while ( access( dumpOutputFile, F_OK ) != -1 ) {
+            snprintf(dumpOutputFile, 255, "%s_%d.bin", fileName, cnt);
+            cnt++;
+        }
+    }
+
+    UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER, "Dumping package %s", dumpOutputFile);
+
+    FILE *write_ptr;
+
+    write_ptr = fopen(dumpOutputFile, "ab");
+
+    fwrite(messageBuffer->data, messageBuffer->length, 1, write_ptr); // write 10 bytes from our buffer
+    fclose(write_ptr);
+}
+
+

+ 0 - 17
tools/corpus_generator/CMakeLists.txt

@@ -1,17 +0,0 @@
-include_directories(${PROJECT_SOURCE_DIR}/src)
-
-#############################
-# Compiled binaries folders #
-#############################
-
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/corpus_generator)
-
-add_definitions(-DUA_CORPUS_OUTPUT_DIR="${PROJECT_BINARY_DIR}/corpus")
-file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/corpus)
-
-add_executable(corpus_generator corpus_generator.c)
-target_link_libraries(corpus_generator open62541 ${open62541_LIBRARIES})
-assign_source_group(corpus_generator)
-add_dependencies(corpus_generator open62541-amalgamation-header)
-set_target_properties(corpus_generator PROPERTIES FOLDER "open62541/corpus_generator")
-set_target_properties(corpus_generator PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/bin/corpus_generator")

+ 5 - 5
tools/travis/travis_linux_script.sh

@@ -13,13 +13,13 @@ fi
 
 # Fuzzer build test
 if ! [ -z ${FUZZER+x} ]; then
-	mkdir -p build && cd build
-	export CC=clang-3.9
-	export CXX=clang++-3.9
-	cmake -DUA_ENABLE_DISCOVERY=ON -DUA_ENABLE_DISCOVERY_MULTICAST=ON -DUA_BUILD_FUZZING=ON ..
+    # Test the corpus generator and use new corpus for fuzz test
+    ./tests/fuzz/generate_corpus.sh
+	if [ $? -ne 0 ] ; then exit 1 ; fi
+
+	cd build_fuzz
 	make && make run_fuzzer
 	if [ $? -ne 0 ] ; then exit 1 ; fi
-	cd .. && rm build -rf
     exit 0
 fi