From 277d7fd34d4155bf5225ade4458912873b174ce7 Mon Sep 17 00:00:00 2001
From: John Thacker <johnthacker@gmail.com>
Date: Sun, 12 Apr 2026 10:28:37 -0400
Subject: [PATCH] RPKI RTR: Check for overflow in the unknown PDU type case

When the PDU type is unknown, since no field is added to the tree,
the dissector must check for overflow when adding a 32 bit unsigned
integer to the offset and throw the same ReportedBoundsError that
would be thrown in the cases where something is added to the tree.

Fix #21186

AI-Assisted: no
(backported from commit 65c4e3e0ea8f6b7cab1e1194f81f685903a47a38)
---
 epan/dissectors/packet-rpki-rtr.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

Index: wireshark-3.6.24/epan/dissectors/packet-rpki-rtr.c
===================================================================
--- wireshark-3.6.24.orig/epan/dissectors/packet-rpki-rtr.c
+++ wireshark-3.6.24/epan/dissectors/packet-rpki-rtr.c
@@ -19,6 +19,7 @@
 #include "packet-tcp.h"
 #include "packet-tls.h"
 #include <epan/expert.h>
+#include <epan/exceptions.h>
 #include <epan/asn1.h>
 #include "packet-x509af.h"
 
@@ -64,6 +65,7 @@ static expert_field ei_rpkirtr_bad_lengt
 
 static dissector_handle_t rpkirtr_handle;
 
+#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))
 
 /* http://www.iana.org/assignments/rpki/rpki.xml#rpki-rtr-pdu */
 #define RPKI_RTR_SERIAL_NOTIFY_PDU   0
@@ -134,7 +136,7 @@ static int dissect_rpkirtr_pdu(tvbuff_t
 
     proto_item *ti = NULL, *ti_flags, *ti_type;
     proto_tree *rpkirtr_tree = NULL, *flags_tree = NULL;
-    int offset = 0;
+    unsigned offset = 0;
     guint8 pdu_type, version;
     guint length;
 
@@ -154,8 +156,6 @@ static int dissect_rpkirtr_pdu(tvbuff_t
         proto_item_append_text(ti, " (%s)", val_to_str(pdu_type, rtr_pdu_type_vals, "Unknown %d"));
         offset += 1;
 
-        length = tvb_get_ntohl(tvb, offset);
-
         switch (pdu_type) {
             case RPKI_RTR_SERIAL_NOTIFY_PDU: /* Serial Notify (0) */
             case RPKI_RTR_SERIAL_QUERY_PDU:  /* Serial Query (1)  */
@@ -293,12 +293,19 @@ static int dissect_rpkirtr_pdu(tvbuff_t
             break;
             default:
                 /* No default ? At least sanity check the length*/
+                offset += 2; // Depends on the PDU type
+                proto_tree_add_item_ret_uint(rpkirtr_tree, hf_rpkirtr_length,           tvb, offset, 4, ENC_BIG_ENDIAN, &length);
                 if (length > tvb_reported_length(tvb)) {
+                    /* XXX - I don't believe this ever gets called, because
+                     * tcp_dissect_pdus and get_rpkirtr_pdu_len guarantee
+                     * that the tvb reported length matches the field here. */
                     expert_add_info(pinfo, ti_type, &ei_rpkirtr_bad_length);
                     return tvb_reported_length(tvb);
                 }
-
-                offset += length;
+                /* Since we don't add a field to the tree... */
+                if (ckd_add(&offset, offset, length)) {
+                    THROW(ReportedBoundsError);
+                }
                 break;
         }
     }
