Blob Blame History Raw
diff --git a/plugins/epan/opcua/opcua.c b/plugins/epan/opcua/opcua.c
index fc26d9f30d..4ca68a9e83 100644
--- a/plugins/epan/opcua/opcua.c
+++ b/plugins/epan/opcua/opcua.c
@@ -38,7 +38,7 @@ void proto_reg_handoff_opcua(void);
 /* declare parse function pointer */
 typedef int (*FctParse)(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset);
 
-static int proto_opcua = -1;
+int proto_opcua = -1;
 static dissector_handle_t opcua_handle;
 /** Official IANA registered port for OPC UA Binary Protocol. */
 #define OPCUA_PORT_RANGE "4840"
diff --git a/plugins/epan/opcua/opcua_simpletypes.c b/plugins/epan/opcua/opcua_simpletypes.c
index a787f21c35..ab006b7552 100644
--- a/plugins/epan/opcua/opcua_simpletypes.c
+++ b/plugins/epan/opcua/opcua_simpletypes.c
@@ -20,6 +20,7 @@
 #include <epan/packet.h>
 #include <epan/expert.h>
 #include <epan/dissectors/packet-windows-common.h>
+#include <epan/proto_data.h>
 #include "opcua_simpletypes.h"
 #include "opcua_hfindeces.h"
 #include "opcua_statuscode.h"
@@ -80,6 +81,7 @@
 
 /* Chosen arbitrarily */
 #define MAX_ARRAY_LEN 10000
+#define MAX_NESTING_DEPTH 100
 
 static int hf_opcua_diag_mask = -1;
 static int hf_opcua_diag_mask_symbolicflag = -1;
@@ -168,6 +170,9 @@ int hf_opcua_resultMask_displayname = -1;
 int hf_opcua_resultMask_typedefinition = -1;
 
 static expert_field ei_array_length = EI_INIT;
+static expert_field ei_nesting_depth = EI_INIT;
+
+extern int proto_opcua;
 
 /** NodeId encoding mask table */
 static const value_string g_nodeidmasks[] = {
@@ -526,6 +531,7 @@ void registerSimpleTypes(int proto)
 
     static ei_register_info ei[] = {
         { &ei_array_length, { "opcua.array.length", PI_UNDECODED, PI_ERROR, "Max array length exceeded", EXPFILL }},
+        { &ei_nesting_depth, { "opcua.nestingdepth", PI_UNDECODED, PI_ERROR, "Max nesting depth exceeded", EXPFILL }},
     };
 
     proto_register_field_array(proto, hf, array_length(hf));
@@ -802,9 +808,19 @@ void parseDiagnosticInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gi
     guint8      EncodingMask;
     proto_tree *subtree;
     proto_item *ti;
+    guint       opcua_nested_count;
 
     subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_diagnosticinfo, &ti, "%s: DiagnosticInfo", szFieldName);
 
+    /* prevent a too high nesting depth */
+    opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0));
+    if (++opcua_nested_count > MAX_NESTING_DEPTH)
+    {
+        expert_add_info(pinfo, ti, &ei_nesting_depth);
+        return;
+    }
+    p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count));
+
     /* parse encoding mask */
     EncodingMask = tvb_get_guint8(tvb, iOffset);
     proto_tree_add_bitmask(subtree, tvb, iOffset, hf_opcua_diag_mask, ett_opcua_diagnosticinfo_encodingmask, diag_mask, ENC_LITTLE_ENDIAN);
@@ -912,6 +928,16 @@ void parseVariant(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOf
     gint    iOffset = *pOffset;
     guint8  EncodingMask;
     gint32  ArrayDimensions = 0;
+    guint   opcua_nested_count;
+
+    /* prevent a too high nesting depth */
+    opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0));
+    if (++opcua_nested_count > MAX_NESTING_DEPTH)
+    {
+        expert_add_info(pinfo, ti, &ei_nesting_depth);
+        return;
+    }
+    p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count));
 
     EncodingMask = tvb_get_guint8(tvb, iOffset);
     proto_tree_add_item(subtree, hf_opcua_variant_encodingmask, tvb, iOffset, 1, ENC_LITTLE_ENDIAN);
@@ -1167,10 +1193,20 @@ void parseExtensionObject(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, g
     guint32 TypeId;
     proto_tree *extobj_tree;
     proto_item *ti;
+    guint       opcua_nested_count;
 
     /* add extension object subtree */
     extobj_tree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_extensionobject, &ti, "%s: ExtensionObject", szFieldName);
 
+    /* prevent a too high nesting depth */
+    opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0));
+    if (++opcua_nested_count > MAX_NESTING_DEPTH)
+    {
+        expert_add_info(pinfo, ti, &ei_nesting_depth);
+        return;
+    }
+    p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count));
+
     /* add nodeid subtree */
     TypeId = getExtensionObjectType(tvb, &iOffset);
     parseExpandedNodeId(extobj_tree, tvb, pinfo, &iOffset, "TypeId");