瀏覽代碼

Merge pull request #1143 from open62541/feature/fuzz_binary_decode

Fuzz UA_binaryDecode
Stefan Profanter 7 年之前
父節點
當前提交
a88a49fcc7
共有 4 個文件被更改,包括 80 次插入7 次删除
  1. 3 0
      src/ua_types_encoding_binary.c
  2. 8 0
      src/ua_types_encoding_binary.h
  3. 17 7
      tests/fuzz/CMakeLists.txt
  4. 52 0
      tests/fuzz/fuzz_binary_decode.cc

+ 3 - 0
src/ua_types_encoding_binary.c

@@ -789,7 +789,10 @@ ExpandedNodeId_decodeBinary(UA_ExpandedNodeId *dst, const UA_DataType *_) {
     /* Mask out the encoding byte on the stream to decode the NodeId only */
     *pos = encoding & (UA_Byte)~(UA_EXPANDEDNODEID_NAMESPACEURI_FLAG |
                                  UA_EXPANDEDNODEID_SERVERINDEX_FLAG);
+    UA_Byte *oldPos = pos;
     UA_StatusCode retval = NodeId_decodeBinary(&dst->nodeId, NULL);
+    // revert the changes since pos is const
+    *oldPos = encoding;
 
     /* Decode the NamespaceUri */
     if(encoding & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {

+ 8 - 0
src/ua_types_encoding_binary.h

@@ -5,6 +5,10 @@
 #ifndef UA_TYPES_ENCODING_BINARY_H_
 #define UA_TYPES_ENCODING_BINARY_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "ua_types.h"
 
 typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos, const UA_Byte **bufEnd);
@@ -21,4 +25,8 @@ UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
 
 size_t UA_calcSizeBinary(void *p, const UA_DataType *type);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* UA_TYPES_ENCODING_BINARY_H_ */

+ 17 - 7
tests/fuzz/CMakeLists.txt

@@ -20,8 +20,8 @@ if (NOT UA_BUILD_OSS_FUZZ)
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
     else()
-        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp")
-        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp")
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp")
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize-address-use-after-scope -fsanitize-coverage=trace-pc-guard,trace-cmp")
     endif()
     set(LIBS Fuzzer)
     set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
@@ -29,7 +29,7 @@ else()
     set(LIBS $ENV{LIB_FUZZING_ENGINE})
     set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $ENV{OUT})
 endif()
-list(APPEND $LIBS ${open62541_LIBRARIES})
+list(APPEND LIBS "${open62541_LIBRARIES}")
 
 
 # Use different plugins for testing
@@ -46,9 +46,19 @@ 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})
+set(FUZZER_TARGETS)
+
+macro(add_fuzzer FUZZER_NAME FUZZER_SOURCE)
+    add_executable(${FUZZER_NAME} $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-fuzzplugins> ${FUZZER_SOURCE} ${ARGN})
+    target_link_libraries(${FUZZER_NAME} ${LIBS})
+    target_include_directories(${FUZZER_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/src/server)
+    assign_source_group(${FUZZER_SOURCE})
+    list(APPEND FUZZER_TARGETS ${FUZZER_NAME})
+endmacro()
+
+# Add new fuzzers here
+add_fuzzer(fuzz_binary_message fuzz_binary_message.cc)
+add_fuzzer(fuzz_binary_decode fuzz_binary_decode.cc)
 
 add_custom_target(
         run_fuzzer
@@ -59,5 +69,5 @@ add_custom_target(
         COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_Read.bin
         COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/fuzz_binary_message ${CMAKE_CURRENT_SOURCE_DIR}/fuzz_binary_message_corpus/client_Write.bin
         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-        DEPENDS fuzz_binary_message
+        DEPENDS ${FUZZER_TARGETS}
         ${MAYBE_USES_TERMINAL})

+ 52 - 0
tests/fuzz/fuzz_binary_decode.cc

@@ -0,0 +1,52 @@
+/* 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/. */
+
+#include <ua_types.h>
+#include "ua_server_internal.h"
+#include "ua_config_standard.h"
+#include "ua_log_stdout.h"
+#include "ua_types_encoding_binary.h"
+
+/*
+** Main entry point.  The fuzzer invokes this function with each
+** fuzzed input.
+*/
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+	if (size == 0)
+		return 0;
+
+	const uint8_t *ptr = data;
+	size_t ptrSize = size;
+
+	// get some random type
+	uint8_t typeIndex = ptr[0];
+	ptr++;
+	ptrSize--;
+
+	if (typeIndex >= UA_TYPES_COUNT)
+		return 0;
+
+	size_t offset = 0;
+	if (ptrSize >= sizeof(size_t)) {
+		offset = (*ptr);
+		ptr += sizeof(size_t);
+		ptrSize -= sizeof(size_t);
+	}
+
+	void *dst = UA_new(&UA_TYPES[typeIndex]);
+
+	const UA_ByteString binary = {
+			ptrSize, //length
+			(UA_Byte *)(void *)ptr //data
+	};
+
+	UA_StatusCode ret = UA_decodeBinary(&binary, &offset, dst, &UA_TYPES[typeIndex], 0, nullptr);
+	if (ret == UA_STATUSCODE_GOOD) {
+		//do nothing
+	}
+	UA_delete(dst, &UA_TYPES[typeIndex]);
+
+	return 0;
+}