Browse Source

Fuzz: Add fuzzer test for parseEndpoint and ua_util methods

Stefan Profanter 6 years ago
parent
commit
884237dbff

+ 1 - 0
tests/fuzz/CMakeLists.txt

@@ -91,6 +91,7 @@ endmacro()
 # Add new fuzzers here
 add_fuzzer(fuzz_binary_message fuzz_binary_message.cc)
 add_fuzzer(fuzz_binary_decode fuzz_binary_decode.cc)
+add_fuzzer(fuzz_src_ua_util fuzz_src_ua_util.cc)
 
 file(GLOB CORPUS_FILES ${PROJECT_SOURCE_DIR}/tests/fuzz/fuzz_binary_message_corpus/generated/*)
 

+ 16 - 0
tests/fuzz/dicts/endpoints.dict

@@ -0,0 +1,16 @@
+#
+# AFL dictionary for OPC UA Endpoints
+# -----------------------------
+#
+#
+# Stefan Profanter <git@s.profanter.me>
+#
+
+endpoint_http="opc.http"
+endpoint_tcp="opc.tcp"
+endpoint_udp="opc.udp"
+endpoint_udp="opc.eth"
+endpoint_proto="://"
+endpoint_host="localhost"
+endpoint_delim="/"
+endpoint_port=":123"

+ 62 - 0
tests/fuzz/fuzz_src_ua_util.cc

@@ -0,0 +1,62 @@
+/* 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_util.h>
+#include "custom_memory_manager.h"
+
+
+static int tortureParseEndpointUrl(const uint8_t *data, size_t size) {
+    const UA_String endpointUrl = {
+        size, (UA_Byte* )(void*)data
+    };
+
+    UA_String hostname;
+    UA_UInt16 port;
+    UA_String path;
+    UA_parseEndpointUrl(&endpointUrl, &hostname, &port, &path);
+    return 0;
+}
+
+static int tortureParseEndpointUrlEthernet(const uint8_t *data, size_t size) {
+    const UA_String endpointUrl = {
+        size, (UA_Byte* )(void*)data
+    };
+
+    UA_String target;
+    UA_UInt16 vid;
+    UA_Byte prid;
+    UA_parseEndpointUrlEthernet(&endpointUrl, &target, &vid, &prid);
+    return 0;
+}
+
+/*
+** Main entry point.  The fuzzer invokes this function with each
+** fuzzed input.
+*/
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+    if (!UA_memoryManager_setLimitFromLast4Bytes(data, size))
+        return 0;
+    size -= 4;
+
+    if (size == 0)
+        return 0;
+
+    // use first byte to decide which function should be fuzzed
+
+    const uint8_t select = data[0];
+
+    const uint8_t *newData = &data[1];
+    size_t  newSize = size-1;
+
+    switch(select) {
+        case 0:
+            return tortureParseEndpointUrl(newData, newSize);
+        case 1:
+            return tortureParseEndpointUrlEthernet(newData, newSize);
+        default:
+            return 0;
+    }
+
+}

+ 2 - 0
tests/fuzz/fuzz_src_ua_util.options

@@ -0,0 +1,2 @@
+[libfuzzer]
+dict = endpoints.dict