From 48fbc0305c93e3058ba9c72b675c9c2854e3b31d Mon Sep 17 00:00:00 2001
From: John Thacker <johnthacker@gmail.com>
Date: Fri, 10 Apr 2026 21:59:05 -0400
Subject: [PATCH] GeoNetworking: catch overflow in packet offset calculation.

Do a checked add.

Move common code out of the switch statement while we're at it.

Fix #21177.

AI-assisted: no


(cherry picked from commit dae485a918efe044aff6775f5b8d07860656ac61)

Co-authored-by: Guy Harris <gharris@sonic.net>
---
 epan/dissectors/packet-geonw.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

Index: wireshark-3.6.24/epan/dissectors/packet-geonw.c
===================================================================
--- wireshark-3.6.24.orig/epan/dissectors/packet-geonw.c
+++ wireshark-3.6.24/epan/dissectors/packet-geonw.c
@@ -67,6 +67,7 @@
 #include <epan/conversation.h>
 #include <epan/tap.h>
 #include <epan/etypes.h>
+#include <epan/exceptions.h>
 
 #include <wsutil/utf8_entities.h>
 
@@ -84,6 +85,8 @@ void proto_register_btpa(void);
 void proto_reg_handoff_geonw(void);
 void proto_register_geonw(void);
 
+#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))
+
 /*
  * Constants
  */
@@ -1912,27 +1915,25 @@ dissect_sec_payload(tvbuff_t *tvb, gint
         field_tree = proto_item_add_subtree(ti, ett_sgeonw_field);
         proto_tree_add_item(field_tree, hf_sgeonw_payload_field_type, tvb, *offset, 1, ENC_BIG_ENDIAN);
         *offset += 1;
+        param_len = dissect_sec_var_len(tvb, offset, pinfo, field_tree);
         switch(tmp_val) {
             case unsecured:
             case signed_pl:
-                param_len = dissect_sec_var_len(tvb, offset, pinfo, field_tree);
                 if (param_len) {
                     tvbuff_t *next_tvb = tvb_new_subset_length(tvb, *offset, param_len);
                     p_add_proto_data(pinfo->pool, pinfo, proto_geonw, SEC_TVB_KEY, next_tvb);
                 }
-                *offset += param_len;
                 break;
             case encrypted:
             case signed_and_encrypted:
-                param_len = dissect_sec_var_len(tvb, offset, pinfo, field_tree);
                 proto_tree_add_item(field_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA);
-                *offset += param_len;
                 break;
             default:
                 // Opaque
-                param_len = dissect_sec_var_len(tvb, offset, pinfo, field_tree);
                 proto_tree_add_item(field_tree, hf_sgeonw_opaque, tvb, *offset, param_len, ENC_NA);
-                *offset += param_len;
+        }
+        if (ckd_add(offset, *offset, param_len)) {
+            THROW(ReportedBoundsError);
         }
         proto_item_set_end(ti, tvb, *offset);
     }
