Use the messageLength field to indicate the message length.
authorGuy Harris <guy@alum.mit.edu>
Mon, 22 Dec 2014 03:33:10 +0000 (19:33 -0800)
committerGuy Harris <guy@alum.mit.edu>
Mon, 22 Dec 2014 03:33:42 +0000 (03:33 +0000)
Check it for sanity (and report errors), and use it to set the length of
the PTP packet tvbuff and the PTP top-level protocol item.

Bug: 10611
Change-Id: I9af6aad5f07d405ebb14885dc986a73e430d7bdb
Reviewed-on: https://code.wireshark.org/review/5967
Reviewed-by: Guy Harris <guy@alum.mit.edu>
epan/dissectors/packet-ptp.c

index de871ee1bd0fee0ef995074c8f317401b9fb57c8..b09c9a8c9b9480f4687a00e1313c132749090e54 100644 (file)
@@ -49,7 +49,8 @@
 
 #include <epan/packet.h>
 #include <epan/etypes.h>
-
+#include <epan/expert.h>
+#include <epan/exceptions.h>
 
 /**********************************************************/
 /* Port definition's for PTP                              */
@@ -1557,6 +1558,9 @@ static gint ett_ptp_as_sig_tlv_flags = -1;
 static gint ett_ptp_v2_priority = -1; */
 static gint ett_ptp_v2_transportspecific = -1;
 
+static expert_field ei_ptp_v2_msg_len_too_large = EI_INIT;
+static expert_field ei_ptp_v2_msg_len_too_small = EI_INIT;
+
 /* END Definitions and fields for PTPv2 dissection. */
 
 
@@ -2356,7 +2360,7 @@ dissect_ptp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean ptp
     guint16 temp;
 
     /* Set up structures needed to add the protocol subtree and manage it */
-    proto_item  *ti, *transportspecific_ti, *flags_ti, *managementData_ti, *clockType_ti, *protocolAddress_ti;
+    proto_item  *ti = NULL, *msg_len_item = NULL, *transportspecific_ti, *flags_ti, *managementData_ti, *clockType_ti, *protocolAddress_ti;
     proto_tree  *ptp_tree, *ptp_transportspecific_tree, *ptp_flags_tree, *ptp_managementData_tree,
                 *ptp_clockType_tree, *ptp_protocolAddress_tree;
 
@@ -2369,6 +2373,8 @@ dissect_ptp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean ptp
     /* Get control field (what kind of message is this? (Sync, DelayReq, ...) */
     ptp_v2_messageid = 0x0F & tvb_get_guint8 (tvb, PTP_V2_TRANSPORT_SPECIFIC_MESSAGE_ID_OFFSET);
 
+    msg_len = tvb_get_ntohs(tvb, PTP_V2_MESSAGE_LENGTH_OFFSET);
+
     /* Extend  Info column with managementId */
     /* Create and set the string for "Info" column */
     if ( ptp_v2_messageid == PTP_V2_MANAGEMENT_MESSAGE )
@@ -2439,9 +2445,31 @@ dissect_ptp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean ptp
         proto_tree_add_item(ptp_tree,
             hf_ptp_v2_versionptp, tvb, PTP_V2_VERSIONPTP_OFFSET, 1, ENC_BIG_ENDIAN);
 
-        msg_len = tvb_get_ntohs(tvb, PTP_V2_MESSAGE_LENGTH_OFFSET);
-        proto_tree_add_item(ptp_tree,
+        msg_len_item = proto_tree_add_item(ptp_tree,
             hf_ptp_v2_messagelength, tvb, PTP_V2_MESSAGE_LENGTH_OFFSET, 2, ENC_BIG_ENDIAN);
+   }
+
+   /*
+    * Sanity-check the message length.
+    */
+   if (msg_len > tvb_reported_length(tvb)) {
+       /* Bogus message length - runs past the end of the packet */
+       expert_add_info(pinfo, msg_len_item, &ei_ptp_v2_msg_len_too_large);
+       msg_len = tvb_reported_length(tvb);
+   } else if (msg_len < PTP_V2_MESSAGE_LENGTH_OFFSET + 2) {
+       /* Bogus message length - not long enough to include the message length field */
+       expert_add_info(pinfo, msg_len_item, &ei_ptp_v2_msg_len_too_small);
+       THROW(ReportedBoundsError);
+   } else {
+       /*
+        * Set the length of this tvbuff to the message length, chopping
+        * off extra data.
+        */
+       set_actual_length(tvb, msg_len);
+       proto_item_set_len(ti, msg_len);
+   }
+
+   if (tree) {
 
         proto_tree_add_item(ptp_tree,
             hf_ptp_v2_domainnumber, tvb, PTP_V2_DOMAIN_NUMBER_OFFSET, 1, ENC_BIG_ENDIAN);
@@ -5930,6 +5958,13 @@ proto_register_ptp(void)
         &ett_ptp_as_sig_tlv_flags,
     };
 
+    static ei_register_info ei[] = {
+        { &ei_ptp_v2_msg_len_too_large, { "ptp.v2.msg_len_too_large", PI_MALFORMED, PI_ERROR, "Message length goes past the end of the packet", EXPFILL }},
+        { &ei_ptp_v2_msg_len_too_small, { "ptp.v2.msg_len_too_small", PI_MALFORMED, PI_ERROR, "Message length too short to include the message length field", EXPFILL }},
+    };
+
+    expert_module_t* expert_ptp;
+
 /* Register the protocol name and description */
     proto_ptp = proto_register_protocol("Precision Time Protocol (IEEE1588)",
                                         "PTP", "ptp");
@@ -5937,6 +5972,9 @@ proto_register_ptp(void)
 /* Required function calls to register the header fields and subtrees used */
     proto_register_field_array(proto_ptp, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
+
+    expert_ptp = expert_register_protocol(proto_ptp);
+    expert_register_field_array(expert_ptp, ei, array_length(ei));
 }
 
 void