From 4e54dae7f0d7840836ee6d5ce1e688f152ab2978 Mon Sep 17 00:00:00 2001
From: Pascal Quantin <pascal.quantin@gmail.com>
Date: Mon, 19 Jun 2017 20:40:52 +0200
Subject: [PATCH] MQ: check fragment length before trying to perform reassembly

Bug: 13792
Change-Id: Id0c116655288c5a3347911281a932ae80250c24f
Reviewed-on: https://code.wireshark.org/review/22233
Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
Petri-Dish: Pascal Quantin <pascal.quantin@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
(cherry picked from commit bb58b3a2643ab81560d84b00be3a9b9e86f0393c)
Reviewed-on: https://code.wireshark.org/review/22252
Reviewed-by: Michael Mann <mmann78@netscape.net>
---
 epan/dissectors/packet-mq.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/epan/dissectors/packet-mq.c b/epan/dissectors/packet-mq.c
index 612a45d..a0c5b51 100644
--- a/epan/dissectors/packet-mq.c
+++ b/epan/dissectors/packet-mq.c
@@ -71,7 +71,7 @@
 #include <epan/ptvcursor.h>
 #include <epan/exceptions.h>
 #include <epan/reassemble.h>
-
+#include <epan/expert.h>
 #include <epan/prefs.h>
 #include <epan/strutil.h>
 
@@ -949,6 +949,8 @@ static gint ett_mq_notif = -1;
 
 static gint ett_mq_structid = -1;
 
+static expert_field ei_mq_reassembly_error = EI_INIT;
+
 static dissector_handle_t mq_handle;
 static dissector_handle_t mq_spx_handle;
 static dissector_handle_t mqpcf_handle;
@@ -3900,6 +3902,7 @@ static int reassemble_mq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo
                 fragment_head *fd_head;
                 guint32 iConnectionId = (pinfo->srcport + pinfo->destport);
                 iHdrL = 28 + iMulS;
+                gboolean reassembly_error = FALSE;
 
                 /* Get the MQ Handle of the Object */
                 iHdl = tvb_get_guint32(tvb, iHdrL + 4, iEnco);
@@ -3933,10 +3936,16 @@ static int reassemble_mq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo
                 */
                 iBegL = (bSeg1st) ? 0 : iNxtP;
 
-                fd_head = fragment_add_seq_next(&mq_reassembly_table,
-                    tvb, iBegL,
-                    pinfo, iConnectionId, NULL,
-                    iSegL - iBegL, bMore);
+                if (iSegL <= iBegL) {
+                    /* negative or null fragment length - something is wrong; skip reassembly */
+                    fd_head = NULL;
+                    reassembly_error = TRUE;
+                } else {
+                    fd_head = fragment_add_seq_next(&mq_reassembly_table,
+                        tvb, iBegL,
+                        pinfo, iConnectionId, NULL,
+                        iSegL - iBegL, bMore);
+                }
 
                 if (tree)
                 {
@@ -3957,6 +3966,11 @@ static int reassemble_mq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo
                         proto_item_append_text(ti, " Hdl=0x%04x GlbMsgIdx=%d, SegIdx=%d, SegLen=%d",
                             iHdl, iGlbMsgIdx, iSegmIndex, iSegLength);
                     }
+                    if (reassembly_error)
+                    {
+                        expert_add_info_format(pinfo, ti, &ei_mq_reassembly_error,
+                                               "Wrong fragment length (%d) - skipping reassembly", iSegL - iBegL);
+                    }
                     mq_tree = proto_item_add_subtree(ti, ett_mq_reaasemb);
                 }
                 else
@@ -4751,11 +4765,20 @@ void proto_register_mq(void)
     };
 
     module_t *mq_module;
+    expert_module_t *expert_mq;
+
+    static ei_register_info ei[] = {
+        { &ei_mq_reassembly_error, { "mq.reassembly_error",
+          PI_REASSEMBLE, PI_ERROR, "Reassembly error", EXPFILL }}
+    };
 
     proto_mq = proto_register_protocol("WebSphere MQ", "MQ", "mq");
     proto_register_field_array(proto_mq, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
 
+    expert_mq = expert_register_protocol(proto_mq);
+    expert_register_field_array(expert_mq, ei, array_length(ei));
+
     mq_heur_subdissector_list = register_heur_dissector_list("mq", proto_mq);
     register_init_routine(mq_init);
     register_cleanup_routine(mq_cleanup);
-- 
2.7.4

