From 5e949867190ab33b36797a2c8a58a7af6f0476af Mon Sep 17 00:00:00 2001
From: Gerald Combs <gerald@wireshark.org>
Date: Sun, 31 Dec 2023 15:06:40 -0800
Subject: [PATCH] asn2wrs: Add recursion checks

Origin: https://gitlab.com/wireshark/wireshark/-/merge_requests/13869

Add a recursion depth check whenever we have cyclic dependencies.
Regenerate our dissectors.

Fixes #19501

(cherry picked from commit 8f797db63ca44875a07d0d8a5d298a79d09b44ec)

Conflicts:
	epan/dissectors/asn1/x509sat/packet-x509sat-template.c
	epan/dissectors/packet-cmip.c
	epan/dissectors/packet-cmp.c
	epan/dissectors/packet-dap.c
	epan/dissectors/packet-disp.c
	epan/dissectors/packet-e2ap.c
	epan/dissectors/packet-glow.c
	epan/dissectors/packet-goose.c
	epan/dissectors/packet-h225.c
	epan/dissectors/packet-h245.c
	epan/dissectors/packet-h248.c
	epan/dissectors/packet-ieee1609dot2.c
	epan/dissectors/packet-ldap.c
	epan/dissectors/packet-mms.c
	epan/dissectors/packet-p22.c
	epan/dissectors/packet-p7.c
	epan/dissectors/packet-x509if.c
	epan/dissectors/packet-x509sat.c
	epan/dissectors/packet-z3950.c
---
 .../asn1/cmip/packet-cmip-template.c          |  1 +
 .../dissectors/asn1/cmp/packet-cmp-template.c |  1 +
 .../dissectors/asn1/dap/packet-dap-template.c |  1 +
 .../asn1/disp/packet-disp-template.c          |  1 +
 .../asn1/glow/packet-glow-template.c          |  1 +
 .../asn1/goose/packet-goose-template.c        |  1 +
 .../asn1/h245/packet-h245-template.c          |  1 +
 .../asn1/h248/packet-h248-template.c          |  1 +
 .../asn1/ldap/packet-ldap-template.c          |  1 +
 .../dissectors/asn1/p22/packet-p22-template.c |  1 +
 epan/dissectors/asn1/p7/packet-p7-template.c  |  1 +
 .../asn1/x509if/packet-x509if-template.c      |  1 +
 .../asn1/x509sat/packet-x509sat-template.c    |  1 +
 epan/dissectors/packet-cmip.c                 | 24 +++++---
 epan/dissectors/packet-cmp.c                  | 20 +++++--
 epan/dissectors/packet-dap.c                  | 44 ++++++++++++---
 epan/dissectors/packet-disp.c                 | 26 +++++++--
 epan/dissectors/packet-glow.c                 | 30 ++++++++--
 epan/dissectors/packet-goose.c                | 18 ++++--
 epan/dissectors/packet-h225.c                 | 13 +++++
 epan/dissectors/packet-h245.c                 | 56 +++++++++++++++++--
 epan/dissectors/packet-h248.c                 | 18 ++++--
 epan/dissectors/packet-ieee1609dot2.c         |  7 +++
 epan/dissectors/packet-its.c                  | 17 ++++--
 epan/dissectors/packet-ldap.c                 | 20 +++++--
 epan/dissectors/packet-mms.c                  | 25 +++++++++
 epan/dissectors/packet-p22.c                  | 40 ++++++++++---
 epan/dissectors/packet-p7.c                   | 28 ++++++----
 epan/dissectors/packet-sv.c                   | 10 ++--
 epan/dissectors/packet-x509if.c               | 32 +++++++++--
 epan/dissectors/packet-x509sat.c              | 22 +++++---
 epan/dissectors/packet-z3950.c                | 19 +++++++
 tools/asn2wrs.py                              | 36 ++++++++++++
 33 files changed, 422 insertions(+), 96 deletions(-)

diff --git a/epan/dissectors/asn1/cmip/packet-cmip-template.c b/epan/dissectors/asn1/cmip/packet-cmip-template.c
index dbac6c6b546..53caeb034eb 100644
--- a/epan/dissectors/asn1/cmip/packet-cmip-template.c
+++ b/epan/dissectors/asn1/cmip/packet-cmip-template.c
@@ -15,6 +15,7 @@
 #include <epan/expert.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
diff --git a/epan/dissectors/asn1/cmp/packet-cmp-template.c b/epan/dissectors/asn1/cmp/packet-cmp-template.c
index 21e3b27ed44..d9c02452260 100644
--- a/epan/dissectors/asn1/cmp/packet-cmp-template.c
+++ b/epan/dissectors/asn1/cmp/packet-cmp-template.c
@@ -18,6 +18,7 @@
 
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include "packet-ber.h"
 #include "packet-cmp.h"
 #include "packet-crmf.h"
diff --git a/epan/dissectors/asn1/dap/packet-dap-template.c b/epan/dissectors/asn1/dap/packet-dap-template.c
index c5884becd66..8c14a03ba36 100644
--- a/epan/dissectors/asn1/dap/packet-dap-template.c
+++ b/epan/dissectors/asn1/dap/packet-dap-template.c
@@ -16,6 +16,7 @@
 #include <epan/expert.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
diff --git a/epan/dissectors/asn1/disp/packet-disp-template.c b/epan/dissectors/asn1/disp/packet-disp-template.c
index a28aa4e8e3d..b76959de22a 100644
--- a/epan/dissectors/asn1/disp/packet-disp-template.c
+++ b/epan/dissectors/asn1/disp/packet-disp-template.c
@@ -16,6 +16,7 @@
 #include <epan/prefs.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
diff --git a/epan/dissectors/asn1/glow/packet-glow-template.c b/epan/dissectors/asn1/glow/packet-glow-template.c
index af6f16fb209..088d3c53332 100644
--- a/epan/dissectors/asn1/glow/packet-glow-template.c
+++ b/epan/dissectors/asn1/glow/packet-glow-template.c
@@ -13,6 +13,7 @@
 # include "config.h"
 
 #include <epan/packet.h>
+#include <epan/proto_data.h>
 #include "packet-ber.h"
 
 #define PNAME  "Glow"
diff --git a/epan/dissectors/asn1/goose/packet-goose-template.c b/epan/dissectors/asn1/goose/packet-goose-template.c
index 142a272ee02..9a78db4c256 100644
--- a/epan/dissectors/asn1/goose/packet-goose-template.c
+++ b/epan/dissectors/asn1/goose/packet-goose-template.c
@@ -16,6 +16,7 @@
 
 #include <epan/packet.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/etypes.h>
 #include <epan/expert.h>
 
diff --git a/epan/dissectors/asn1/h245/packet-h245-template.c b/epan/dissectors/asn1/h245/packet-h245-template.c
index b71edc7288d..1ee778cf9a0 100644
--- a/epan/dissectors/asn1/h245/packet-h245-template.c
+++ b/epan/dissectors/asn1/h245/packet-h245-template.c
@@ -28,6 +28,7 @@
 #include <epan/t35.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/tap.h>
 #include <wsutil/pint.h>
 #include "packet-tpkt.h"
diff --git a/epan/dissectors/asn1/h248/packet-h248-template.c b/epan/dissectors/asn1/h248/packet-h248-template.c
index af1a2ba83cc..514c899396d 100644
--- a/epan/dissectors/asn1/h248/packet-h248-template.c
+++ b/epan/dissectors/asn1/h248/packet-h248-template.c
@@ -18,6 +18,7 @@
 #include <epan/exceptions.h>
 #include <epan/tap.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/prefs.h>
 #include <epan/exported_pdu.h>
 #include <epan/address_types.h>
diff --git a/epan/dissectors/asn1/ldap/packet-ldap-template.c b/epan/dissectors/asn1/ldap/packet-ldap-template.c
index b9313819996..0021c5641e0 100644
--- a/epan/dissectors/asn1/ldap/packet-ldap-template.c
+++ b/epan/dissectors/asn1/ldap/packet-ldap-template.c
@@ -80,6 +80,7 @@
 #include <epan/strutil.h>
 #include <epan/show_exception.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/expert.h>
 #include <epan/uat.h>
 #include <wsutil/str_util.h>
diff --git a/epan/dissectors/asn1/p22/packet-p22-template.c b/epan/dissectors/asn1/p22/packet-p22-template.c
index f0cf69afbda..fe7d4d2ddee 100644
--- a/epan/dissectors/asn1/p22/packet-p22-template.c
+++ b/epan/dissectors/asn1/p22/packet-p22-template.c
@@ -14,6 +14,7 @@
 #include <epan/packet.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
diff --git a/epan/dissectors/asn1/p7/packet-p7-template.c b/epan/dissectors/asn1/p7/packet-p7-template.c
index 4df623bac03..621aa9b0392 100644
--- a/epan/dissectors/asn1/p7/packet-p7-template.c
+++ b/epan/dissectors/asn1/p7/packet-p7-template.c
@@ -15,6 +15,7 @@
 #include <epan/prefs.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
diff --git a/epan/dissectors/asn1/x509if/packet-x509if-template.c b/epan/dissectors/asn1/x509if/packet-x509if-template.c
index cc75f93a7bc..10de0ec8eb3 100644
--- a/epan/dissectors/asn1/x509if/packet-x509if-template.c
+++ b/epan/dissectors/asn1/x509if/packet-x509if-template.c
@@ -14,6 +14,7 @@
 #include <epan/packet.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/strutil.h>
 
 #include "packet-ber.h"
diff --git a/epan/dissectors/asn1/x509sat/packet-x509sat-template.c b/epan/dissectors/asn1/x509sat/packet-x509sat-template.c
index 1166e33ba48..d2640228a5c 100644
--- a/epan/dissectors/asn1/x509sat/packet-x509sat-template.c
+++ b/epan/dissectors/asn1/x509sat/packet-x509sat-template.c
@@ -14,6 +14,7 @@
 #include <epan/packet.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-p1.h"
diff --git a/epan/dissectors/packet-cmip.c b/epan/dissectors/packet-cmip.c
index 56277dc8404..eeb8deeb027 100644
--- a/epan/dissectors/packet-cmip.c
+++ b/epan/dissectors/packet-cmip.c
@@ -23,6 +23,7 @@
 #include <epan/expert.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
@@ -328,7 +329,7 @@ static int hf_cmip_T_daysOfWeek_friday = -1;
 static int hf_cmip_T_daysOfWeek_saturday = -1;
 
 /*--- End of included file: packet-cmip-hf.c ---*/
-#line 43 "./asn1/cmip/packet-cmip-template.c"
+#line 44 "./asn1/cmip/packet-cmip-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_cmip = -1;
@@ -458,7 +459,7 @@ static gint ett_cmip_T_modificationList = -1;
 static gint ett_cmip_T_modificationList_item = -1;
 
 /*--- End of included file: packet-cmip-ett.c ---*/
-#line 47 "./asn1/cmip/packet-cmip-template.c"
+#line 48 "./asn1/cmip/packet-cmip-template.c"
 
 static expert_field ei_wrong_spdu_type = EI_INIT;
 
@@ -521,7 +522,7 @@ static const value_string cmip_error_code_vals[] = {
 
 
 /*--- End of included file: packet-cmip-table.c ---*/
-#line 58 "./asn1/cmip/packet-cmip-template.c"
+#line 59 "./asn1/cmip/packet-cmip-template.c"
 
 static int opcode_type;
 #define OPCODE_INVOKE        1
@@ -620,7 +621,7 @@ static const char *object_identifier_id;
 #define noInvokeId                     NULL
 
 /*--- End of included file: packet-cmip-val.h ---*/
-#line 68 "./asn1/cmip/packet-cmip-template.c"
+#line 69 "./asn1/cmip/packet-cmip-template.c"
 
 /*--- Included file: packet-cmip-fn.c ---*/
 #line 1 "./asn1/cmip/packet-cmip-fn.c"
@@ -631,6 +632,7 @@ static const char *object_identifier_id;
 static int dissect_cmip_CMISFilter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -1050,10 +1052,16 @@ static const ber_choice_t CMISFilter_choice[] = {
 
 static int
 dissect_cmip_CMISFilter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  CMISFilter_choice, hf_index, ett_cmip_CMISFilter,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -4454,7 +4462,7 @@ static int dissect_WeekMask_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto
 
 
 /*--- End of included file: packet-cmip-fn.c ---*/
-#line 69 "./asn1/cmip/packet-cmip-template.c"
+#line 70 "./asn1/cmip/packet-cmip-template.c"
 
 
 
@@ -5635,7 +5643,7 @@ void proto_register_cmip(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-cmip-hfarr.c ---*/
-#line 145 "./asn1/cmip/packet-cmip-template.c"
+#line 146 "./asn1/cmip/packet-cmip-template.c"
   };
 
   /* List of subtrees */
@@ -5767,7 +5775,7 @@ void proto_register_cmip(void) {
     &ett_cmip_T_modificationList_item,
 
 /*--- End of included file: packet-cmip-ettarr.c ---*/
-#line 151 "./asn1/cmip/packet-cmip-template.c"
+#line 152 "./asn1/cmip/packet-cmip-template.c"
   };
 
   static ei_register_info ei[] = {
@@ -5862,7 +5870,7 @@ void proto_register_cmip(void) {
 
 
 /*--- End of included file: packet-cmip-dis-tab.c ---*/
-#line 170 "./asn1/cmip/packet-cmip-template.c"
+#line 171 "./asn1/cmip/packet-cmip-template.c"
     oid_add_from_string("discriminatorId(1)","2.9.3.2.7.1");
 
   attribute_id_dissector_table = register_dissector_table("cmip.attribute_id", "CMIP Attribute Id", proto_cmip, FT_UINT32, BASE_DEC);
diff --git a/epan/dissectors/packet-cmp.c b/epan/dissectors/packet-cmp.c
index 6f6febdaf51..f6b3ac3fb18 100644
--- a/epan/dissectors/packet-cmp.c
+++ b/epan/dissectors/packet-cmp.c
@@ -26,6 +26,7 @@
 
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include "packet-ber.h"
 #include "packet-cmp.h"
 #include "packet-crmf.h"
@@ -224,7 +225,7 @@ static int hf_cmp_PKIFailureInfo_systemFailure = -1;
 static int hf_cmp_PKIFailureInfo_duplicateCertReq = -1;
 
 /*--- End of included file: packet-cmp-hf.c ---*/
-#line 56 "./asn1/cmp/packet-cmp-template.c"
+#line 57 "./asn1/cmp/packet-cmp-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_cmp = -1;
@@ -280,7 +281,7 @@ static gint ett_cmp_PollRepContent = -1;
 static gint ett_cmp_PollRepContent_item = -1;
 
 /*--- End of included file: packet-cmp-ett.c ---*/
-#line 60 "./asn1/cmp/packet-cmp-template.c"
+#line 61 "./asn1/cmp/packet-cmp-template.c"
 
 /*--- Included file: packet-cmp-fn.c ---*/
 #line 1 "./asn1/cmp/packet-cmp-fn.c"
@@ -290,6 +291,7 @@ static gint ett_cmp_PollRepContent_item = -1;
 /*int dissect_cmp_PKIMessage(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);*/
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 static const value_string cmp_CMPCertificate_vals[] = {
   {   0, "x509v3PKCert" },
@@ -1106,9 +1108,15 @@ static const ber_sequence_t PKIMessage_sequence[] = {
 
 int
 dissect_cmp_PKIMessage(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 5;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
                                    PKIMessage_sequence, hf_index, ett_cmp_PKIMessage);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1463,7 +1471,7 @@ static int dissect_SuppLangTagsValue_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _
 
 
 /*--- End of included file: packet-cmp-fn.c ---*/
-#line 61 "./asn1/cmp/packet-cmp-template.c"
+#line 62 "./asn1/cmp/packet-cmp-template.c"
 
 static int
 dissect_cmp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
@@ -2342,7 +2350,7 @@ void proto_register_cmp(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-cmp-hfarr.c ---*/
-#line 303 "./asn1/cmp/packet-cmp-template.c"
+#line 304 "./asn1/cmp/packet-cmp-template.c"
 	};
 
 	/* List of subtrees */
@@ -2400,7 +2408,7 @@ void proto_register_cmp(void) {
     &ett_cmp_PollRepContent_item,
 
 /*--- End of included file: packet-cmp-ettarr.c ---*/
-#line 309 "./asn1/cmp/packet-cmp-template.c"
+#line 310 "./asn1/cmp/packet-cmp-template.c"
 	};
 	module_t *cmp_module;
 
@@ -2487,7 +2495,7 @@ void proto_reg_handoff_cmp(void) {
 
 
 /*--- End of included file: packet-cmp-dis-tab.c ---*/
-#line 374 "./asn1/cmp/packet-cmp-template.c"
+#line 375 "./asn1/cmp/packet-cmp-template.c"
 		inited = TRUE;
 	}
 
diff --git a/epan/dissectors/packet-dap.c b/epan/dissectors/packet-dap.c
index af21d0f31d3..e2e2ec8c81c 100644
--- a/epan/dissectors/packet-dap.c
+++ b/epan/dissectors/packet-dap.c
@@ -24,6 +24,7 @@
 #include <epan/expert.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
@@ -463,7 +464,7 @@ static int hf_dap_SearchControlOptions_separateFamilyMembers = -1;
 static int hf_dap_SearchControlOptions_searchFamily = -1;
 
 /*--- End of included file: packet-dap-hf.c ---*/
-#line 49 "./asn1/dap/packet-dap-template.c"
+#line 50 "./asn1/dap/packet-dap-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_dap = -1;
@@ -642,7 +643,7 @@ static gint ett_dap_UpdateError = -1;
 static gint ett_dap_T_signedUpdateError = -1;
 
 /*--- End of included file: packet-dap-ett.c ---*/
-#line 53 "./asn1/dap/packet-dap-template.c"
+#line 54 "./asn1/dap/packet-dap-template.c"
 
 static expert_field ei_dap_anonymous = EI_INIT;
 
@@ -669,7 +670,7 @@ static expert_field ei_dap_anonymous = EI_INIT;
 #define id_errcode_dsaReferral         9
 
 /*--- End of included file: packet-dap-val.h ---*/
-#line 57 "./asn1/dap/packet-dap-template.c"
+#line 58 "./asn1/dap/packet-dap-template.c"
 
 
 /*--- Included file: packet-dap-table.c ---*/
@@ -707,7 +708,7 @@ static const value_string dap_err_code_string_vals[] = {
 
 
 /*--- End of included file: packet-dap-table.c ---*/
-#line 59 "./asn1/dap/packet-dap-template.c"
+#line 60 "./asn1/dap/packet-dap-template.c"
 
 
 /*--- Included file: packet-dap-fn.c ---*/
@@ -730,6 +731,7 @@ static int dissect_dap_ListResultData(gboolean implicit_tag _U_, tvbuff_t *tvb _
 static int dissect_dap_SearchResultData(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 const value_string dap_FamilyGrouping_vals[] = {
   {   1, "entryOnly" },
@@ -1294,9 +1296,15 @@ static const ber_sequence_t FamilyEntries_sequence[] = {
 
 static int
 dissect_dap_FamilyEntries(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 5;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
                                    FamilyEntries_sequence, hf_index, ett_dap_FamilyEntries);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1492,10 +1500,16 @@ static const ber_choice_t Filter_choice[] = {
 
 int
 dissect_dap_Filter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  Filter_choice, hf_index, ett_dap_Filter,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -2948,10 +2962,16 @@ static const ber_choice_t ListResultData_choice[] = {
 
 static int
 dissect_dap_ListResultData(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  ListResultData_choice, hf_index, ett_dap_ListResultData,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -3333,10 +3353,16 @@ static const ber_choice_t SearchResultData_choice[] = {
 
 static int
 dissect_dap_SearchResultData(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  SearchResultData_choice, hf_index, ett_dap_SearchResultData,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -4754,7 +4780,7 @@ static int dissect_UpdateError_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, pr
 
 
 /*--- End of included file: packet-dap-fn.c ---*/
-#line 61 "./asn1/dap/packet-dap-template.c"
+#line 62 "./asn1/dap/packet-dap-template.c"
 
 
 /*--- Included file: packet-dap-table11.c ---*/
@@ -4786,7 +4812,7 @@ static const ros_opr_t dap_opr_tab[] = {
 
 
 /*--- End of included file: packet-dap-table11.c ---*/
-#line 63 "./asn1/dap/packet-dap-template.c"
+#line 64 "./asn1/dap/packet-dap-template.c"
 
 /*--- Included file: packet-dap-table21.c ---*/
 #line 1 "./asn1/dap/packet-dap-table21.c"
@@ -4815,7 +4841,7 @@ static const ros_err_t dap_err_tab[] = {
 
 
 /*--- End of included file: packet-dap-table21.c ---*/
-#line 64 "./asn1/dap/packet-dap-template.c"
+#line 65 "./asn1/dap/packet-dap-template.c"
 
 static const ros_info_t dap_ros_info = {
   "DAP",
@@ -6455,7 +6481,7 @@ void proto_register_dap(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-dap-hfarr.c ---*/
-#line 83 "./asn1/dap/packet-dap-template.c"
+#line 84 "./asn1/dap/packet-dap-template.c"
   };
 
   /* List of subtrees */
@@ -6636,7 +6662,7 @@ void proto_register_dap(void) {
     &ett_dap_T_signedUpdateError,
 
 /*--- End of included file: packet-dap-ettarr.c ---*/
-#line 89 "./asn1/dap/packet-dap-template.c"
+#line 90 "./asn1/dap/packet-dap-template.c"
   };
 
   static ei_register_info ei[] = {
diff --git a/epan/dissectors/packet-disp.c b/epan/dissectors/packet-disp.c
index 31ace80695f..e3c52719db6 100644
--- a/epan/dissectors/packet-disp.c
+++ b/epan/dissectors/packet-disp.c
@@ -24,6 +24,7 @@
 #include <epan/prefs.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
@@ -165,7 +166,7 @@ static int hf_disp_signedShadowError = -1;        /* T_signedShadowError */
 static int hf_disp_shadowError = -1;              /* ShadowErrorData */
 
 /*--- End of included file: packet-disp-hf.c ---*/
-#line 49 "./asn1/disp/packet-disp-template.c"
+#line 50 "./asn1/disp/packet-disp-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_disp = -1;
@@ -228,7 +229,7 @@ static gint ett_disp_ShadowError = -1;
 static gint ett_disp_T_signedShadowError = -1;
 
 /*--- End of included file: packet-disp-ett.c ---*/
-#line 53 "./asn1/disp/packet-disp-template.c"
+#line 54 "./asn1/disp/packet-disp-template.c"
 
 static expert_field ei_disp_unsupported_opcode = EI_INIT;
 static expert_field ei_disp_unsupported_errcode = EI_INIT;
@@ -249,6 +250,7 @@ static int dissect_disp_Subtree(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, in
 static int dissect_disp_IncrementalStepRefresh(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -1066,9 +1068,15 @@ static const ber_sequence_t Subtree_sequence[] = {
 
 static int
 dissect_disp_Subtree(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
                                    Subtree_sequence, hf_index, ett_disp_Subtree);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1224,9 +1232,15 @@ static const ber_sequence_t IncrementalStepRefresh_sequence[] = {
 
 static int
 dissect_disp_IncrementalStepRefresh(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
                                    IncrementalStepRefresh_sequence, hf_index, ett_disp_IncrementalStepRefresh);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1467,7 +1481,7 @@ static int dissect_ShadowingAgreementInfo_PDU(tvbuff_t *tvb _U_, packet_info *pi
 
 
 /*--- End of included file: packet-disp-fn.c ---*/
-#line 62 "./asn1/disp/packet-disp-template.c"
+#line 63 "./asn1/disp/packet-disp-template.c"
 
 /*
 * Dissect DISP PDUs inside a ROS PDUs
@@ -2025,7 +2039,7 @@ void proto_register_disp(void) {
         "ShadowErrorData", HFILL }},
 
 /*--- End of included file: packet-disp-hfarr.c ---*/
-#line 187 "./asn1/disp/packet-disp-template.c"
+#line 188 "./asn1/disp/packet-disp-template.c"
   };
 
   /* List of subtrees */
@@ -2090,7 +2104,7 @@ void proto_register_disp(void) {
     &ett_disp_T_signedShadowError,
 
 /*--- End of included file: packet-disp-ettarr.c ---*/
-#line 193 "./asn1/disp/packet-disp-template.c"
+#line 194 "./asn1/disp/packet-disp-template.c"
   };
 
   static ei_register_info ei[] = {
@@ -2139,7 +2153,7 @@ void proto_reg_handoff_disp(void) {
 
 
 /*--- End of included file: packet-disp-dis-tab.c ---*/
-#line 231 "./asn1/disp/packet-disp-template.c"
+#line 232 "./asn1/disp/packet-disp-template.c"
 
   /* APPLICATION CONTEXT */
 
diff --git a/epan/dissectors/packet-glow.c b/epan/dissectors/packet-glow.c
index 96792b432a9..3adc905fd75 100644
--- a/epan/dissectors/packet-glow.c
+++ b/epan/dissectors/packet-glow.c
@@ -21,6 +21,7 @@
 # include "config.h"
 
 #include <epan/packet.h>
+#include <epan/proto_data.h>
 #include "packet-ber.h"
 
 #define PNAME  "Glow"
@@ -131,7 +132,7 @@ static int hf_glow_qualifiedFunction = -1;        /* QualifiedFunction */
 static int hf_glow_qualifiedTemplate = -1;        /* QualifiedTemplate */
 
 /*--- End of included file: packet-glow-hf.c ---*/
-#line 28 "./asn1/glow/packet-glow-template.c"
+#line 29 "./asn1/glow/packet-glow-template.c"
 
 /* Initialize the subtree pointers */
 static int ett_glow = -1;
@@ -183,7 +184,7 @@ static gint ett_glow_SEQUENCE_OF_RootElement = -1;
 static gint ett_glow_RootElement = -1;
 
 /*--- End of included file: packet-glow-ett.c ---*/
-#line 33 "./asn1/glow/packet-glow-template.c"
+#line 34 "./asn1/glow/packet-glow-template.c"
 
 
 /*--- Included file: packet-glow-fn.c ---*/
@@ -202,6 +203,7 @@ static int dissect_glow_ElementCollection(gboolean implicit_tag _U_, tvbuff_t *t
 static int dissect_glow_Template(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -1102,9 +1104,15 @@ dissect_glow_SEQUENCE_OF_Element(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, i
 
 static int
 dissect_glow_ElementCollection(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 6;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
                                       hf_index, BER_CLASS_APP, 4, TRUE, dissect_glow_SEQUENCE_OF_Element);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1128,9 +1136,15 @@ dissect_glow_Parameter_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offse
 
 static int
 dissect_glow_Parameter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 6;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
                                       hf_index, BER_CLASS_APP, 1, TRUE, dissect_glow_Parameter_U);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1180,9 +1194,15 @@ dissect_glow_Template_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset
 
 static int
 dissect_glow_Template(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 9;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
                                       hf_index, BER_CLASS_APP, 24, TRUE, dissect_glow_Template_U);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1492,7 +1512,7 @@ static int dissect_Root_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tre
 
 
 /*--- End of included file: packet-glow-fn.c ---*/
-#line 35 "./asn1/glow/packet-glow-template.c"
+#line 36 "./asn1/glow/packet-glow-template.c"
 
 static int
 dissect_glow(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
@@ -1898,7 +1918,7 @@ void proto_register_glow(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-glow-hfarr.c ---*/
-#line 60 "./asn1/glow/packet-glow-template.c"
+#line 61 "./asn1/glow/packet-glow-template.c"
   };
 
   /* List of subtrees */
@@ -1951,7 +1971,7 @@ void proto_register_glow(void) {
     &ett_glow_RootElement,
 
 /*--- End of included file: packet-glow-ettarr.c ---*/
-#line 66 "./asn1/glow/packet-glow-template.c"
+#line 67 "./asn1/glow/packet-glow-template.c"
   };
 
 
diff --git a/epan/dissectors/packet-goose.c b/epan/dissectors/packet-goose.c
index 9937af7314a..43b061e1fdb 100644
--- a/epan/dissectors/packet-goose.c
+++ b/epan/dissectors/packet-goose.c
@@ -24,6 +24,7 @@
 
 #include <epan/packet.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/etypes.h>
 #include <epan/expert.h>
 
@@ -158,7 +159,7 @@ static int hf_goose_mMSString = -1;               /* MMSString */
 static int hf_goose_utc_time = -1;                /* UtcTime */
 
 /*--- End of included file: packet-goose-hf.c ---*/
-#line 90 "./asn1/goose/packet-goose-template.c"
+#line 91 "./asn1/goose/packet-goose-template.c"
 
 /* Initialize the subtree pointers */
 static int ett_r_goose = -1;
@@ -193,7 +194,7 @@ static gint ett_goose_SEQUENCE_OF_Data = -1;
 static gint ett_goose_Data = -1;
 
 /*--- End of included file: packet-goose-ett.c ---*/
-#line 103 "./asn1/goose/packet-goose-template.c"
+#line 104 "./asn1/goose/packet-goose-template.c"
 
 
 /*--- Included file: packet-goose-fn.c ---*/
@@ -204,6 +205,7 @@ static gint ett_goose_Data = -1;
 static int dissect_goose_Data(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -733,10 +735,16 @@ static const ber_choice_t Data_choice[] = {
 
 static int
 dissect_goose_Data(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  Data_choice, hf_index, ett_goose_Data,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -783,7 +791,7 @@ dissect_goose_GOOSEpdu(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset
 
 
 /*--- End of included file: packet-goose-fn.c ---*/
-#line 105 "./asn1/goose/packet-goose-template.c"
+#line 106 "./asn1/goose/packet-goose-template.c"
 
 static dissector_handle_t goose_handle = NULL;
 static dissector_handle_t ositp_handle = NULL;
@@ -1485,7 +1493,7 @@ void proto_register_goose(void) {
         "UtcTime", HFILL }},
 
 /*--- End of included file: packet-goose-hfarr.c ---*/
-#line 566 "./asn1/goose/packet-goose-template.c"
+#line 567 "./asn1/goose/packet-goose-template.c"
 	};
 
 	/* List of subtrees */
@@ -1521,7 +1529,7 @@ void proto_register_goose(void) {
     &ett_goose_Data,
 
 /*--- End of included file: packet-goose-ettarr.c ---*/
-#line 580 "./asn1/goose/packet-goose-template.c"
+#line 581 "./asn1/goose/packet-goose-template.c"
 	};
 
 	static ei_register_info ei[] = {
diff --git a/epan/dissectors/packet-h225.c b/epan/dissectors/packet-h225.c
index 222aa4c9ea3..6c74e3d86e1 100644
--- a/epan/dissectors/packet-h225.c
+++ b/epan/dissectors/packet-h225.c
@@ -1275,6 +1275,7 @@ static int dissect_h225_EnumeratedParameter(tvbuff_t *tvb _U_, int offset _U_, a
 /*int dissect_h225_GenericData(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);*/
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -4019,6 +4020,11 @@ static const per_sequence_t EnumeratedParameter_sequence[] = {
 
 static int
 dissect_h225_EnumeratedParameter(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 864 "./asn1/h225/h225.cnf"
   gef_ctx_t *parent_gefx;
 
@@ -4028,6 +4034,7 @@ dissect_h225_EnumeratedParameter(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *
   offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
                                    ett_h225_EnumeratedParameter, EnumeratedParameter_sequence);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
 #line 869 "./asn1/h225/h225.cnf"
   actx->private_data = parent_gefx;
 
@@ -4043,6 +4050,11 @@ static const per_sequence_t GenericData_sequence[] = {
 
 int
 dissect_h225_GenericData(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 6;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 850 "./asn1/h225/h225.cnf"
   void *priv_data = actx->private_data;
   gef_ctx_t *gefx;
@@ -4057,6 +4069,7 @@ dissect_h225_GenericData(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_
   offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
                                    ett_h225_GenericData, GenericData_sequence);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
 #line 860 "./asn1/h225/h225.cnf"
   actx->private_data = priv_data;
 
diff --git a/epan/dissectors/packet-h245.c b/epan/dissectors/packet-h245.c
index cb523c2f1d8..2990488283e 100644
--- a/epan/dissectors/packet-h245.c
+++ b/epan/dissectors/packet-h245.c
@@ -36,6 +36,7 @@
 #include <epan/t35.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/tap.h>
 #include <wsutil/pint.h>
 #include "packet-tpkt.h"
@@ -202,7 +203,7 @@ typedef enum _IndicationMessage_enum {
 } IndicationMessage_enum;
 
 /*--- End of included file: packet-h245-val.h ---*/
-#line 75 "./asn1/h245/packet-h245-template.c"
+#line 76 "./asn1/h245/packet-h245-template.c"
 
 static const value_string h245_RequestMessage_short_vals[] = {
 	{ RequestMessage_nonStandard              ,	"NSM" },
@@ -1909,7 +1910,7 @@ static int hf_h245_encrypted = -1;                /* OCTET_STRING */
 static int hf_h245_encryptedAlphanumeric = -1;    /* EncryptedAlphanumeric */
 
 /*--- End of included file: packet-h245-hf.c ---*/
-#line 375 "./asn1/h245/packet-h245-template.c"
+#line 376 "./asn1/h245/packet-h245-template.c"
 
 /* Initialize the subtree pointers */
 static int ett_h245 = -1;
@@ -2410,7 +2411,7 @@ static gint ett_h245_FlowControlIndication = -1;
 static gint ett_h245_MobileMultilinkReconfigurationIndication = -1;
 
 /*--- End of included file: packet-h245-ett.c ---*/
-#line 380 "./asn1/h245/packet-h245-template.c"
+#line 381 "./asn1/h245/packet-h245-template.c"
 
 /* Forward declarations */
 static int dissect_h245_MultimediaSystemControlMessage(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
@@ -2449,6 +2450,7 @@ static int dissect_h245_AudioMode(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t
 static int dissect_h245_ModeElementType(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -3921,9 +3923,15 @@ static const per_sequence_t GenericParameter_sequence[] = {
 
 static int
 dissect_h245_GenericParameter(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
                                    ett_h245_GenericParameter, GenericParameter_sequence);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -5738,6 +5746,11 @@ static const per_choice_t VideoCapability_choice[] = {
 
 static int
 dissect_h245_VideoCapability(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 457 "./asn1/h245/h245.cnf"
   gint32 value;
 
@@ -5749,6 +5762,7 @@ dissect_h245_VideoCapability(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx
 
 
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -6056,6 +6070,11 @@ static const per_choice_t AudioCapability_choice[] = {
 
 static int
 dissect_h245_AudioCapability(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 450 "./asn1/h245/h245.cnf"
   gint32 value;
 
@@ -6066,6 +6085,7 @@ dissect_h245_AudioCapability(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx
         codec_type = val_to_str(value, h245_AudioCapability_short_vals, "<unknown>");
 
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -7236,6 +7256,11 @@ static const per_choice_t DataType_choice[] = {
 
 static int
 dissect_h245_DataType(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 5;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 1007 "./asn1/h245/h245.cnf"
 gint choice_index;
 
@@ -7254,6 +7279,7 @@ if (upcoming_channel){
 
 
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -9018,6 +9044,11 @@ static const per_sequence_t MultiplexElement_sequence[] = {
 
 static int
 dissect_h245_MultiplexElement(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 82 "./asn1/h245/h245.cnf"
   /*MultiplexElement*/
   h223_mux_element* me = wmem_new(wmem_file_scope(), h223_mux_element);
@@ -9028,6 +9059,7 @@ dissect_h245_MultiplexElement(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *act
   offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
                                    ett_h245_MultiplexElement, MultiplexElement_sequence);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -9655,6 +9687,11 @@ static const per_choice_t AudioMode_choice[] = {
 
 static int
 dissect_h245_AudioMode(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 472 "./asn1/h245/h245.cnf"
   gint32 value;
 
@@ -9665,6 +9702,7 @@ dissect_h245_AudioMode(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_,
   codec_type = val_to_str(value, h245_AudioMode_vals, "<unknown>");
 
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -10012,10 +10050,16 @@ static const per_choice_t ModeElementType_choice[] = {
 
 static int
 dissect_h245_ModeElementType(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 6;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
                                  ett_h245_ModeElementType, ModeElementType_choice,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -14497,7 +14541,7 @@ static int dissect_OpenLogicalChannel_PDU(tvbuff_t *tvb _U_, packet_info *pinfo
 
 
 /*--- End of included file: packet-h245-fn.c ---*/
-#line 389 "./asn1/h245/packet-h245-template.c"
+#line 390 "./asn1/h245/packet-h245-template.c"
 
 static int
 dissect_h245(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
@@ -20196,7 +20240,7 @@ void proto_register_h245(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-h245-hfarr.c ---*/
-#line 475 "./asn1/h245/packet-h245-template.c"
+#line 476 "./asn1/h245/packet-h245-template.c"
   };
 
   /* List of subtrees */
@@ -20699,7 +20743,7 @@ void proto_register_h245(void) {
     &ett_h245_MobileMultilinkReconfigurationIndication,
 
 /*--- End of included file: packet-h245-ettarr.c ---*/
-#line 482 "./asn1/h245/packet-h245-template.c"
+#line 483 "./asn1/h245/packet-h245-template.c"
   };
   module_t *h245_module;
 
diff --git a/epan/dissectors/packet-h248.c b/epan/dissectors/packet-h248.c
index 32c11e5b4ff..57d33c4c044 100644
--- a/epan/dissectors/packet-h248.c
+++ b/epan/dissectors/packet-h248.c
@@ -26,6 +26,7 @@
 #include <epan/exceptions.h>
 #include <epan/tap.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/prefs.h>
 #include <epan/exported_pdu.h>
 #include <epan/address_types.h>
@@ -392,7 +393,7 @@ static int hf_h248_NotifyCompletion_otherReason = -1;
 static int hf_h248_NotifyCompletion_onIteration = -1;
 
 /*--- End of included file: packet-h248-hf.c ---*/
-#line 69 "./asn1/h248/packet-h248-template.c"
+#line 70 "./asn1/h248/packet-h248-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_h248 = -1;
@@ -560,7 +561,7 @@ static gint ett_h248_EventParameterV1 = -1;
 static gint ett_h248_SigParameterV1 = -1;
 
 /*--- End of included file: packet-h248-ett.c ---*/
-#line 89 "./asn1/h248/packet-h248-template.c"
+#line 90 "./asn1/h248/packet-h248-template.c"
 
 static expert_field ei_h248_errored_command = EI_INIT;
 static expert_field ei_h248_transactionId64 = EI_INIT;
@@ -2636,6 +2637,7 @@ static int dissect_h248_MtpAddress(gboolean implicit_tag, tvbuff_t *tvb, int off
 static int dissect_h248_SecondEventsDescriptor(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -4292,9 +4294,15 @@ static const ber_sequence_t SecondEventsDescriptor_sequence[] = {
 
 static int
 dissect_h248_SecondEventsDescriptor(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 7;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
                                    SecondEventsDescriptor_sequence, hf_index, ett_h248_SecondEventsDescriptor);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -6078,7 +6086,7 @@ dissect_h248_SigParameterV1(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int of
 
 
 /*--- End of included file: packet-h248-fn.c ---*/
-#line 2156 "./asn1/h248/packet-h248-template.c"
+#line 2157 "./asn1/h248/packet-h248-template.c"
 
 static int dissect_h248_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
     dissect_tpkt_encap(tvb, pinfo, tree, h248_desegment, h248_handle);
@@ -7503,7 +7511,7 @@ void proto_register_h248(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-h248-hfarr.c ---*/
-#line 2324 "./asn1/h248/packet-h248-template.c"
+#line 2325 "./asn1/h248/packet-h248-template.c"
 
         GCP_HF_ARR_ELEMS("h248",h248_arrel)
 
@@ -7669,7 +7677,7 @@ void proto_register_h248(void) {
     &ett_h248_SigParameterV1,
 
 /*--- End of included file: packet-h248-ettarr.c ---*/
-#line 2342 "./asn1/h248/packet-h248-template.c"
+#line 2343 "./asn1/h248/packet-h248-template.c"
     };
 
     static ei_register_info ei[] = {
diff --git a/epan/dissectors/packet-ieee1609dot2.c b/epan/dissectors/packet-ieee1609dot2.c
index 031bf48bc53..a5d5e7051cb 100644
--- a/epan/dissectors/packet-ieee1609dot2.c
+++ b/epan/dissectors/packet-ieee1609dot2.c
@@ -318,6 +318,7 @@ ieee1609dot2_set_next_default_psid(packet_info *pinfo, guint32 psid)
 static int dissect_ieee1609dot2_SignedDataPayload(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -2086,9 +2087,15 @@ static const oer_sequence_t SignedDataPayload_sequence[] = {
 
 static int
 dissect_ieee1609dot2_SignedDataPayload(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 6;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_oer_sequence(tvb, offset, actx, tree, hf_index,
                                    ett_ieee1609dot2_SignedDataPayload, SignedDataPayload_sequence);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
diff --git a/epan/dissectors/packet-its.c b/epan/dissectors/packet-its.c
index 0b35d1516ac..de27694fc62 100644
--- a/epan/dissectors/packet-its.c
+++ b/epan/dissectors/packet-its.c
@@ -1925,7 +1925,7 @@ static int hf_cpm_node_Z5 = -1;                   /* Offset_B14 */
 static int hf_cpm_node_Z6 = -1;                   /* Offset_B16 */
 
 /*--- End of included file: packet-its-hf.c ---*/
-#line 288 "./asn1/its/packet-its-template.c"
+#line 289 "./asn1/its/packet-its-template.c"
 
 // CauseCode/SubCauseCode management
 static int hf_its_trafficConditionSubCauseCode = -1;
@@ -2526,7 +2526,7 @@ static gint ett_cpm_OffsetPoint = -1;
 static gint ett_cpm_NodeOffsetPointZ = -1;
 
 /*--- End of included file: packet-its-ett.c ---*/
-#line 318 "./asn1/its/packet-its-template.c"
+#line 319 "./asn1/its/packet-its-template.c"
 
 // Deal with cause/subcause code management
 struct { CauseCodeType_enum cause; int* hf; } cause_to_subcause[] = {
@@ -11038,6 +11038,7 @@ static int dissect_AddGrpC_SignalStatusPackage_addGrpC_PDU(tvbuff_t *tvb _U_, pa
 static int dissect_gdd_GddStructure(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -11962,9 +11963,15 @@ static const per_sequence_t gdd_GddStructure_sequence[] = {
 
 static int
 dissect_gdd_GddStructure(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 9;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
                                    ett_gdd_GddStructure, gdd_GddStructure_sequence);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -18561,7 +18568,7 @@ static int dissect_cpm_CollectivePerceptionMessage_PDU(tvbuff_t *tvb _U_, packet
 
 
 /*--- End of included file: packet-its-fn.c ---*/
-#line 360 "./asn1/its/packet-its-template.c"
+#line 361 "./asn1/its/packet-its-template.c"
 
 static void
 its_latitude_fmt(gchar *s, guint32 v)
@@ -25364,7 +25371,7 @@ void proto_register_its(void)
         "Offset_B16", HFILL }},
 
 /*--- End of included file: packet-its-hfarr.c ---*/
-#line 835 "./asn1/its/packet-its-template.c"
+#line 836 "./asn1/its/packet-its-template.c"
 
     { &hf_its_roadworksSubCauseCode,
       { "roadworksSubCauseCode", "its.subCauseCode",
@@ -26138,7 +26145,7 @@ void proto_register_its(void)
     &ett_cpm_NodeOffsetPointZ,
 
 /*--- End of included file: packet-its-ettarr.c ---*/
-#line 1038 "./asn1/its/packet-its-template.c"
+#line 1039 "./asn1/its/packet-its-template.c"
     };
 
     static ei_register_info ei[] = {
diff --git a/epan/dissectors/packet-ldap.c b/epan/dissectors/packet-ldap.c
index 33c7a31dba9..c9427e60311 100644
--- a/epan/dissectors/packet-ldap.c
+++ b/epan/dissectors/packet-ldap.c
@@ -88,6 +88,7 @@
 #include <epan/strutil.h>
 #include <epan/show_exception.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/expert.h>
 #include <epan/uat.h>
 #include <wsutil/str_util.h>
@@ -336,7 +337,7 @@ static int hf_ldap_graceAuthNsRemaining = -1;     /* INTEGER_0_maxInt */
 static int hf_ldap_error = -1;                    /* T_error */
 
 /*--- End of included file: packet-ldap-hf.c ---*/
-#line 186 "./asn1/ldap/packet-ldap-template.c"
+#line 187 "./asn1/ldap/packet-ldap-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_ldap = -1;
@@ -408,7 +409,7 @@ static gint ett_ldap_PasswordPolicyResponseValue = -1;
 static gint ett_ldap_T_warning = -1;
 
 /*--- End of included file: packet-ldap-ett.c ---*/
-#line 198 "./asn1/ldap/packet-ldap-template.c"
+#line 199 "./asn1/ldap/packet-ldap-template.c"
 
 static expert_field ei_ldap_exceeded_filter_length = EI_INIT;
 static expert_field ei_ldap_too_many_filter_elements = EI_INIT;
@@ -1130,6 +1131,7 @@ ldap_match_call_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gu
 static int dissect_ldap_Filter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -2246,6 +2248,11 @@ static const ber_choice_t Filter_choice[] = {
 
 static int
 dissect_ldap_Filter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 661 "./asn1/ldap/ldap.cnf"
   proto_tree *tr;
   proto_item *it;
@@ -2273,6 +2280,7 @@ dissect_ldap_Filter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_
 
 
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -3815,7 +3823,7 @@ static int dissect_PasswordPolicyResponseValue_PDU(tvbuff_t *tvb _U_, packet_inf
 
 
 /*--- End of included file: packet-ldap-fn.c ---*/
-#line 909 "./asn1/ldap/packet-ldap-template.c"
+#line 910 "./asn1/ldap/packet-ldap-template.c"
 static int dissect_LDAPMessage_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ldap_conv_info_t *ldap_info) {
 
   int offset = 0;
@@ -5632,7 +5640,7 @@ void proto_register_ldap(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-ldap-hfarr.c ---*/
-#line 2157 "./asn1/ldap/packet-ldap-template.c"
+#line 2158 "./asn1/ldap/packet-ldap-template.c"
   };
 
   /* List of subtrees */
@@ -5706,7 +5714,7 @@ void proto_register_ldap(void) {
     &ett_ldap_T_warning,
 
 /*--- End of included file: packet-ldap-ettarr.c ---*/
-#line 2171 "./asn1/ldap/packet-ldap-template.c"
+#line 2172 "./asn1/ldap/packet-ldap-template.c"
   };
   /* UAT for header fields */
   static uat_field_t custom_attribute_types_uat_fields[] = {
@@ -5917,7 +5925,7 @@ proto_reg_handoff_ldap(void)
 
 
 /*--- End of included file: packet-ldap-dis-tab.c ---*/
-#line 2365 "./asn1/ldap/packet-ldap-template.c"
+#line 2366 "./asn1/ldap/packet-ldap-template.c"
 
  dissector_add_uint_range_with_preference("tcp.port", TCP_PORT_RANGE_LDAP, ldap_handle);
 
diff --git a/epan/dissectors/packet-mms.c b/epan/dissectors/packet-mms.c
index 233bbb835c6..e7cbeb7aeae 100644
--- a/epan/dissectors/packet-mms.c
+++ b/epan/dissectors/packet-mms.c
@@ -1057,6 +1057,7 @@ static int dissect_mms_AlternateAccess(gboolean implicit_tag _U_, tvbuff_t *tvb
 static int dissect_mms_Data(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -1578,10 +1579,16 @@ static const ber_choice_t TypeSpecification_choice[] = {
 
 static int
 dissect_mms_TypeSpecification(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  TypeSpecification_choice, hf_index, ett_mms_TypeSpecification,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1763,9 +1770,15 @@ static const ber_sequence_t AlternateAccess_sequence_of[1] = {
 
 static int
 dissect_mms_AlternateAccess(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 5;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset,
                                       AlternateAccess_sequence_of, hf_index, ett_mms_AlternateAccess);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1819,10 +1832,16 @@ static const ber_choice_t VariableSpecification_choice[] = {
 
 static int
 dissect_mms_VariableSpecification(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  VariableSpecification_choice, hf_index, ett_mms_VariableSpecification,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -2108,10 +2127,16 @@ static const ber_choice_t Data_choice[] = {
 
 static int
 dissect_mms_Data(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  Data_choice, hf_index, ett_mms_Data,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
diff --git a/epan/dissectors/packet-p22.c b/epan/dissectors/packet-p22.c
index f446ab88f4c..fb9aeb29c95 100644
--- a/epan/dissectors/packet-p22.c
+++ b/epan/dissectors/packet-p22.c
@@ -22,6 +22,7 @@
 #include <epan/packet.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
@@ -323,7 +324,7 @@ static const value_string charsetreg_vals [] = {
 #define ub_telephone_number            32
 
 /*--- End of included file: packet-p22-val.h ---*/
-#line 67 "./asn1/p22/packet-p22-template.c"
+#line 68 "./asn1/p22/packet-p22-template.c"
 
 
 /*--- Included file: packet-p22-hf.c ---*/
@@ -708,7 +709,7 @@ static int hf_p22_RecipientSecurityRequest_ipn_non_repudiation = -1;
 static int hf_p22_RecipientSecurityRequest_ipn_proof = -1;
 
 /*--- End of included file: packet-p22-hf.c ---*/
-#line 69 "./asn1/p22/packet-p22-template.c"
+#line 70 "./asn1/p22/packet-p22-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_p22 = -1;
@@ -842,7 +843,7 @@ static gint ett_p22_T_body_part_token_choice = -1;
 static gint ett_p22_T_choice = -1;
 
 /*--- End of included file: packet-p22-ett.c ---*/
-#line 73 "./asn1/p22/packet-p22-template.c"
+#line 74 "./asn1/p22/packet-p22-template.c"
 
 
 /*--- Included file: packet-p22-fn.c ---*/
@@ -862,6 +863,7 @@ static int dissect_p22_BodyPartTokens(gboolean implicit_tag _U_, tvbuff_t *tvb _
 static int dissect_p22_ForwardedContentToken(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -1834,6 +1836,11 @@ static const ber_sequence_t IPM_sequence[] = {
 
 int
 dissect_p22_IPM(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 7;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
 #line 243 "./asn1/p22/p22.cnf"
 
  col_append_str(actx->pinfo->cinfo, COL_INFO, " Message");
@@ -1845,6 +1852,7 @@ dissect_p22_IPM(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, as
 
 
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -3557,9 +3565,15 @@ static const ber_sequence_t IPMSynopsis_sequence_of[1] = {
 
 static int
 dissect_p22_IPMSynopsis(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence_of(implicit_tag, actx, tree, tvb, offset,
                                       IPMSynopsis_sequence_of, hf_index, ett_p22_IPMSynopsis);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -4017,9 +4031,15 @@ static const ber_sequence_t BodyPartTokens_set_of[1] = {
 
 static int
 dissect_p22_BodyPartTokens(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_set_of(implicit_tag, actx, tree, tvb, offset,
                                  BodyPartTokens_set_of, hf_index, ett_p22_BodyPartTokens);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -4067,9 +4087,15 @@ static const ber_sequence_t ForwardedContentToken_set_of[1] = {
 
 static int
 dissect_p22_ForwardedContentToken(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_set_of(implicit_tag, actx, tree, tvb, offset,
                                  ForwardedContentToken_set_of, hf_index, ett_p22_ForwardedContentToken);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -4659,7 +4685,7 @@ static int dissect_ForwardedContentToken_PDU(tvbuff_t *tvb _U_, packet_info *pin
 
 
 /*--- End of included file: packet-p22-fn.c ---*/
-#line 75 "./asn1/p22/packet-p22-template.c"
+#line 76 "./asn1/p22/packet-p22-template.c"
 
 /*
 * Dissect P22 PDUs inside a PPDU.
@@ -6205,7 +6231,7 @@ void proto_register_p22(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-p22-hfarr.c ---*/
-#line 108 "./asn1/p22/packet-p22-template.c"
+#line 109 "./asn1/p22/packet-p22-template.c"
   };
 
   /* List of subtrees */
@@ -6341,7 +6367,7 @@ void proto_register_p22(void) {
     &ett_p22_T_choice,
 
 /*--- End of included file: packet-p22-ettarr.c ---*/
-#line 114 "./asn1/p22/packet-p22-template.c"
+#line 115 "./asn1/p22/packet-p22-template.c"
   };
 
   /* Register protocol */
@@ -6461,7 +6487,7 @@ void proto_reg_handoff_p22(void) {
 
 
 /*--- End of included file: packet-p22-dis-tab.c ---*/
-#line 130 "./asn1/p22/packet-p22-template.c"
+#line 131 "./asn1/p22/packet-p22-template.c"
 
   register_ber_oid_dissector("2.6.1.10.0", dissect_p22, proto_p22, "InterPersonal Message (1984)");
   register_ber_oid_dissector("2.6.1.10.1", dissect_p22, proto_p22, "InterPersonal Message (1988)");
diff --git a/epan/dissectors/packet-p7.c b/epan/dissectors/packet-p7.c
index e9c24366e03..64bd635486a 100644
--- a/epan/dissectors/packet-p7.c
+++ b/epan/dissectors/packet-p7.c
@@ -23,6 +23,7 @@
 #include <epan/prefs.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-acse.h"
@@ -104,7 +105,7 @@ static int proto_p7 = -1;
 #define ub_ua_restrictions             16
 
 /*--- End of included file: packet-p7-val.h ---*/
-#line 41 "./asn1/p7/packet-p7-template.c"
+#line 42 "./asn1/p7/packet-p7-template.c"
 
 
 /*--- Included file: packet-p7-hf.c ---*/
@@ -476,7 +477,7 @@ static int hf_p7_T_entry_class_problem_entry_class_not_subscribed = -1;
 static int hf_p7_T_entry_class_problem_inappropriate_entry_class = -1;
 
 /*--- End of included file: packet-p7-hf.c ---*/
-#line 43 "./asn1/p7/packet-p7-template.c"
+#line 44 "./asn1/p7/packet-p7-template.c"
 
 /* Initialize the subtree pointers */
 static gint ett_p7 = -1;
@@ -618,7 +619,7 @@ static gint ett_p7_RTSE_apdus = -1;
 static gint ett_p7_RTABapdu = -1;
 
 /*--- End of included file: packet-p7-ett.c ---*/
-#line 47 "./asn1/p7/packet-p7-template.c"
+#line 48 "./asn1/p7/packet-p7-template.c"
 
 
 /*--- Included file: packet-p7-table.c ---*/
@@ -661,7 +662,7 @@ static const value_string p7_err_code_string_vals[] = {
 
 
 /*--- End of included file: packet-p7-table.c ---*/
-#line 49 "./asn1/p7/packet-p7-template.c"
+#line 50 "./asn1/p7/packet-p7-template.c"
 
 
 /*--- Included file: packet-p7-fn.c ---*/
@@ -673,6 +674,7 @@ static const value_string p7_err_code_string_vals[] = {
 static int dissect_p7_Filter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -1587,10 +1589,16 @@ static const ber_choice_t Filter_choice[] = {
 
 static int
 dissect_p7_Filter(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  Filter_choice, hf_index, ett_p7_Filter,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -4106,7 +4114,7 @@ static int dissect_RTSE_apdus_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, pro
 
 
 /*--- End of included file: packet-p7-fn.c ---*/
-#line 51 "./asn1/p7/packet-p7-template.c"
+#line 52 "./asn1/p7/packet-p7-template.c"
 
 
 /*--- Included file: packet-p7-table11.c ---*/
@@ -4138,7 +4146,7 @@ static const ros_opr_t p7_opr_tab[] = {
 
 
 /*--- End of included file: packet-p7-table11.c ---*/
-#line 53 "./asn1/p7/packet-p7-template.c"
+#line 54 "./asn1/p7/packet-p7-template.c"
 
 /*--- Included file: packet-p7-table21.c ---*/
 #line 1 "./asn1/p7/packet-p7-table21.c"
@@ -4177,7 +4185,7 @@ static const ros_err_t p7_err_tab[] = {
 
 
 /*--- End of included file: packet-p7-table21.c ---*/
-#line 54 "./asn1/p7/packet-p7-template.c"
+#line 55 "./asn1/p7/packet-p7-template.c"
 
 static const ros_info_t p7_ros_info = {
   "P7",
@@ -5657,7 +5665,7 @@ void proto_register_p7(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-p7-hfarr.c ---*/
-#line 73 "./asn1/p7/packet-p7-template.c"
+#line 74 "./asn1/p7/packet-p7-template.c"
   };
 
   /* List of subtrees */
@@ -5801,7 +5809,7 @@ void proto_register_p7(void) {
     &ett_p7_RTABapdu,
 
 /*--- End of included file: packet-p7-ettarr.c ---*/
-#line 79 "./asn1/p7/packet-p7-template.c"
+#line 80 "./asn1/p7/packet-p7-template.c"
   };
   module_t *p7_module;
 
@@ -5860,7 +5868,7 @@ void proto_reg_handoff_p7(void) {
 
 
 /*--- End of included file: packet-p7-dis-tab.c ---*/
-#line 105 "./asn1/p7/packet-p7-template.c"
+#line 106 "./asn1/p7/packet-p7-template.c"
 
   /* APPLICATION CONTEXT */
 
diff --git a/epan/dissectors/packet-sv.c b/epan/dissectors/packet-sv.c
index 88caa0fbc62..ab5e8b30b5a 100644
--- a/epan/dissectors/packet-sv.c
+++ b/epan/dissectors/packet-sv.c
@@ -118,7 +118,7 @@ static int hf_sv_smpMod = -1;                     /* T_smpMod */
 static int hf_sv_gmidData = -1;                   /* GmidData */
 
 /*--- End of included file: packet-sv-hf.c ---*/
-#line 94 "./asn1/sv/packet-sv-template.c"
+#line 95 "./asn1/sv/packet-sv-template.c"
 
 /* Initialize the subtree pointers */
 static int ett_sv = -1;
@@ -137,7 +137,7 @@ static gint ett_sv_SEQUENCE_OF_ASDU = -1;
 static gint ett_sv_ASDU = -1;
 
 /*--- End of included file: packet-sv-ett.c ---*/
-#line 104 "./asn1/sv/packet-sv-template.c"
+#line 105 "./asn1/sv/packet-sv-template.c"
 
 static expert_field ei_sv_mal_utctime = EI_INIT;
 static expert_field ei_sv_zero_pdu = EI_INIT;
@@ -491,7 +491,7 @@ dissect_sv_SampledValues(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offse
 
 
 /*--- End of included file: packet-sv-fn.c ---*/
-#line 187 "./asn1/sv/packet-sv-template.c"
+#line 199 "./asn1/sv/packet-sv-template.c"
 
 /*
 * Dissect SV PDUs inside a PPDU.
@@ -684,7 +684,7 @@ void proto_register_sv(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-sv-hfarr.c ---*/
-#line 319 "./asn1/sv/packet-sv-template.c"
+#line 331 "./asn1/sv/packet-sv-template.c"
 	};
 
 	/* List of subtrees */
@@ -703,7 +703,7 @@ void proto_register_sv(void) {
     &ett_sv_ASDU,
 
 /*--- End of included file: packet-sv-ettarr.c ---*/
-#line 329 "./asn1/sv/packet-sv-template.c"
+#line 341 "./asn1/sv/packet-sv-template.c"
 	};
 
 	static ei_register_info ei[] = {
diff --git a/epan/dissectors/packet-x509if.c b/epan/dissectors/packet-x509if.c
index 50320220a0e..65c3c1ac7e6 100644
--- a/epan/dissectors/packet-x509if.c
+++ b/epan/dissectors/packet-x509if.c
@@ -22,6 +22,7 @@
 #include <epan/packet.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 #include <epan/strutil.h>
 
 #include "packet-ber.h"
@@ -201,7 +202,7 @@ static int hf_x509if_AllowedSubset_oneLevel = -1;
 static int hf_x509if_AllowedSubset_wholeSubtree = -1;
 
 /*--- End of included file: packet-x509if-hf.c ---*/
-#line 37 "./asn1/x509if/packet-x509if-template.c"
+#line 38 "./asn1/x509if/packet-x509if-template.c"
 
 /* Initialize the subtree pointers */
 
@@ -282,7 +283,7 @@ static gint ett_x509if_SEQUENCE_SIZE_1_MAX_OF_AttributeType = -1;
 static gint ett_x509if_SET_SIZE_1_MAX_OF_DirectoryString = -1;
 
 /*--- End of included file: packet-x509if-ett.c ---*/
-#line 40 "./asn1/x509if/packet-x509if-template.c"
+#line 41 "./asn1/x509if/packet-x509if-template.c"
 
 static proto_tree *top_of_dn = NULL;
 static proto_tree *top_of_rdn = NULL;
@@ -336,6 +337,7 @@ x509if_frame_end(void)
 /*int dissect_x509if_AttributeCombination(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);*/
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -1096,10 +1098,16 @@ static const ber_choice_t Refinement_choice[] = {
 
 int
 dissect_x509if_Refinement(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  Refinement_choice, hf_index, ett_x509if_Refinement,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1541,10 +1549,16 @@ static const ber_choice_t ContextCombination_choice[] = {
 
 int
 dissect_x509if_ContextCombination(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  ContextCombination_choice, hf_index, ett_x509if_ContextCombination,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1662,10 +1676,16 @@ static const ber_choice_t AttributeCombination_choice[] = {
 
 int
 dissect_x509if_AttributeCombination(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  AttributeCombination_choice, hf_index, ett_x509if_AttributeCombination,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -2090,7 +2110,7 @@ static int dissect_HierarchyBelow_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
 
 
 /*--- End of included file: packet-x509if-fn.c ---*/
-#line 76 "./asn1/x509if/packet-x509if-template.c"
+#line 77 "./asn1/x509if/packet-x509if-template.c"
 
 const char * x509if_get_last_dn(void)
 {
@@ -2756,7 +2776,7 @@ void proto_register_x509if(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-x509if-hfarr.c ---*/
-#line 121 "./asn1/x509if/packet-x509if-template.c"
+#line 122 "./asn1/x509if/packet-x509if-template.c"
   };
 
   /* List of subtrees */
@@ -2839,7 +2859,7 @@ void proto_register_x509if(void) {
     &ett_x509if_SET_SIZE_1_MAX_OF_DirectoryString,
 
 /*--- End of included file: packet-x509if-ettarr.c ---*/
-#line 126 "./asn1/x509if/packet-x509if-template.c"
+#line 127 "./asn1/x509if/packet-x509if-template.c"
   };
 
   /* Register protocol */
@@ -2897,6 +2917,6 @@ void proto_reg_handoff_x509if(void) {
 
 
 /*--- End of included file: packet-x509if-dis-tab.c ---*/
-#line 145 "./asn1/x509if/packet-x509if-template.c"
+#line 146 "./asn1/x509if/packet-x509if-template.c"
 }
 
diff --git a/epan/dissectors/packet-x509sat.c b/epan/dissectors/packet-x509sat.c
index 876b9831ca3..8c533081847 100644
--- a/epan/dissectors/packet-x509sat.c
+++ b/epan/dissectors/packet-x509sat.c
@@ -22,6 +22,7 @@
 #include <epan/packet.h>
 #include <epan/oids.h>
 #include <epan/asn1.h>
+#include <epan/proto_data.h>
 
 #include "packet-ber.h"
 #include "packet-p1.h"
@@ -207,7 +208,7 @@ static int hf_x509sat_T_bitNamedDays_friday = -1;
 static int hf_x509sat_T_bitNamedDays_saturday = -1;
 
 /*--- End of included file: packet-x509sat-hf.c ---*/
-#line 33 "./asn1/x509sat/packet-x509sat-template.c"
+#line 34 "./asn1/x509sat/packet-x509sat-template.c"
 
 /* Initialize the subtree pointers */
 
@@ -262,7 +263,7 @@ static gint ett_x509sat_T_between = -1;
 static gint ett_x509sat_LocaleContextSyntax = -1;
 
 /*--- End of included file: packet-x509sat-ett.c ---*/
-#line 36 "./asn1/x509sat/packet-x509sat-template.c"
+#line 37 "./asn1/x509sat/packet-x509sat-template.c"
 
 
 /*--- Included file: packet-x509sat-fn.c ---*/
@@ -274,6 +275,7 @@ static gint ett_x509sat_LocaleContextSyntax = -1;
 /*int dissect_x509sat_Criteria(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);*/
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -448,10 +450,16 @@ static const ber_choice_t Criteria_choice[] = {
 
 int
 dissect_x509sat_Criteria(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  Criteria_choice, hf_index, ett_x509sat_Criteria,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -1906,7 +1914,7 @@ static int dissect_GUID_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tre
 
 
 /*--- End of included file: packet-x509sat-fn.c ---*/
-#line 38 "./asn1/x509sat/packet-x509sat-template.c"
+#line 39 "./asn1/x509sat/packet-x509sat-template.c"
 
 
 /*--- proto_register_x509sat ----------------------------------------------*/
@@ -2575,7 +2583,7 @@ void proto_register_x509sat(void) {
         NULL, HFILL }},
 
 /*--- End of included file: packet-x509sat-hfarr.c ---*/
-#line 46 "./asn1/x509sat/packet-x509sat-template.c"
+#line 47 "./asn1/x509sat/packet-x509sat-template.c"
   };
 
   /* List of subtrees */
@@ -2632,7 +2640,7 @@ void proto_register_x509sat(void) {
     &ett_x509sat_LocaleContextSyntax,
 
 /*--- End of included file: packet-x509sat-ettarr.c ---*/
-#line 51 "./asn1/x509sat/packet-x509sat-template.c"
+#line 52 "./asn1/x509sat/packet-x509sat-template.c"
   };
 
   /* Register protocol */
@@ -2685,7 +2693,7 @@ void proto_register_x509sat(void) {
   register_ber_syntax_dissector("X121Address", proto_x509sat, dissect_X121Address_PDU);
 
 /*--- End of included file: packet-x509sat-syn-reg.c ---*/
-#line 61 "./asn1/x509sat/packet-x509sat-template.c"
+#line 62 "./asn1/x509sat/packet-x509sat-template.c"
 
 }
 
@@ -2878,7 +2886,7 @@ void proto_reg_handoff_x509sat(void) {
 
 
 /*--- End of included file: packet-x509sat-dis-tab.c ---*/
-#line 68 "./asn1/x509sat/packet-x509sat-template.c"
+#line 69 "./asn1/x509sat/packet-x509sat-template.c"
 
   /* OBJECT CLASSES */
 
diff --git a/epan/dissectors/packet-z3950.c b/epan/dissectors/packet-z3950.c
index 3ad54b0ee10..e25a2e7c1e8 100644
--- a/epan/dissectors/packet-z3950.c
+++ b/epan/dissectors/packet-z3950.c
@@ -2088,6 +2088,7 @@ static int dissect_z3950_ElementInfo(gboolean implicit_tag _U_, tvbuff_t *tvb _U
 static int dissect_z3950_TaggedElement(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
 
 
+#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.
 
 
 static int
@@ -3067,10 +3068,16 @@ static const ber_choice_t RPNStructure_choice[] = {
 
 static int
 dissect_z3950_RPNStructure(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 3;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_choice(actx, tree, tvb, offset,
                                  RPNStructure_choice, hf_index, ett_z3950_RPNStructure,
                                  NULL);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -6584,9 +6591,15 @@ static const ber_sequence_t ElementInfo_sequence[] = {
 
 static int
 dissect_z3950_ElementInfo(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
                                    ElementInfo_sequence, hf_index, ett_z3950_ElementInfo);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
@@ -8059,9 +8072,15 @@ static const ber_sequence_t TaggedElement_sequence[] = {
 
 static int
 dissect_z3950_TaggedElement(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = 4;
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
                                    TaggedElement_sequence, hf_index, ett_z3950_TaggedElement);
 
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
   return offset;
 }
 
diff --git a/tools/asn2wrs.py b/tools/asn2wrs.py
index db199b6a253..9f50738a3b4 100755
--- a/tools/asn2wrs.py
+++ b/tools/asn2wrs.py
@@ -1548,6 +1548,23 @@ class EthCtx:
         if self.conform.check_item('PDU', tname):
             out += self.output_proto_root()
 
+        cycle_size = 0
+        if self.eth_dep_cycle:
+            for cur_cycle in self.eth_dep_cycle:
+                t = self.type[cur_cycle[0]]['ethname']
+                if t == tname:
+                    cycle_size = len(cur_cycle)
+                    break
+
+        if cycle_size > 0:
+            out += f'''\
+  const int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_tail(actx->pinfo->layers)));
+  const unsigned cycle_size = {cycle_size};
+  unsigned recursion_depth = p_get_proto_depth(actx->pinfo, proto_id);
+  DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth + cycle_size);
+'''
+
         if self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
             out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_HDR')
         return out
@@ -1558,6 +1575,20 @@ class EthCtx:
         #if self.conform.get_fn_presence(tname):
         #  out += self.conform.get_fn_text(tname, 'FN_FTR')
         #el
+
+        add_recursion_check = False
+        if self.eth_dep_cycle:
+            for cur_cycle in self.eth_dep_cycle:
+                t = self.type[cur_cycle[0]]['ethname']
+                if t == tname:
+                    add_recursion_check = True
+                    break
+
+        if add_recursion_check:
+            out += '''\
+  p_set_proto_depth(actx->pinfo, proto_id, recursion_depth - cycle_size);
+'''
+
         if self.conform.get_fn_presence(self.eth_type[tname]['ref'][0]):
             out += self.conform.get_fn_text(self.eth_type[tname]['ref'][0], 'FN_FTR')
         out += "  return offset;\n"
@@ -1825,12 +1856,15 @@ class EthCtx:
                     fx.write(self.eth_out_pdu_decl(f))
             if not first_decl:
                 fx.write('\n')
+
+        add_depth_define = False
         if self.eth_dep_cycle:
             fx.write('/*--- Cyclic dependencies ---*/\n\n')
             i = 0
             while i < len(self.eth_dep_cycle):
                 t = self.type[self.eth_dep_cycle[i][0]]['ethname']
                 if self.dep_cycle_eth_type[t][0] != i: i += 1; continue
+                add_depth_define = True
                 fx.write(''.join(['/* %s */\n' % ' -> '.join(self.eth_dep_cycle[i]) for i in self.dep_cycle_eth_type[t]]))
                 if not self.eth_type[t]['export'] & EF_TYPE:
                     fx.write(self.eth_type_fn_h(t))
@@ -1839,6 +1873,8 @@ class EthCtx:
                 fx.write('\n')
                 i += 1
             fx.write('\n')
+        if add_depth_define:
+            fx.write('#define MAX_RECURSION_DEPTH 100 // Arbitrarily chosen.\n')
         for t in self.eth_type_ord1:
             if self.eth_type[t]['import']:
                 continue
-- 
GitLab

