(Finally!) check in part of Didier's patch to fix
authorJeff Morriss <jeff.morriss.ws@gmail.com>
Fri, 31 May 2013 01:46:28 +0000 (01:46 -0000)
committerJeff Morriss <jeff.morriss.ws@gmail.com>
Fri, 31 May 2013 01:46:28 +0000 (01:46 -0000)
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=3290
(TRY_TO_FAKE_THIS_ITEM disables bounds errors):

Before calling TRY_TO_FAKE_THIS_ITEM() check if the length given (or, in
the case of FT_UINT_{STRING,BYTES}, the length we retrieve from the TVB)
exceeds what's left in the TVB.

Do this only for proto_tree_add_item() for now (it's the most commonly used
and thus the biggest trouble maker in this area).

Similar changes for other APIs will come later (if nothing blows up).  Despite
the fuzz failures this bug has caused I'm not sure about back-porting it...

svn path=/trunk/; revision=49644

epan/proto.c

index 20bc024fc4f116665f078894a9e4f145bfb6605c..1e7e5b54d9ee2bc39957a6c6e503ba8192f34341 100644 (file)
@@ -1786,6 +1786,28 @@ ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
                offset, length, encoding);
 }
 
+/*
+ * Validates that field length bytes are available starting from
+ * start (pos/neg). Throws an exception if they aren't.
+ */
+static void
+test_length(header_field_info *hfinfo, proto_tree *tree, tvbuff_t *tvb,
+           gint start, gint length, gboolean little_endian)
+{
+       gint size = length;
+
+       if (!tvb)
+           return;
+
+       if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
+           guint32 n;
+
+           n = get_uint_value(tree, tvb, start, length, little_endian);
+           size += n;
+       }
+       tvb_ensure_bytes_exist(tvb, start, size);
+}
+
 /* Add an item to a proto_tree, using the text label registered to that item;
    the item is extracted from the tvbuff handed to it. */
 proto_item *
@@ -1794,16 +1816,19 @@ proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
 {
        field_info        *new_fi;
        header_field_info *hfinfo;
+       gint              item_length;
+
+       hfinfo = get_hfi_and_length(hfindex, tvb, start, &length, &item_length);
+       test_length(hfinfo, tree, tvb, start, item_length, encoding);
 
        TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
 
-       new_fi = alloc_field_info(tree, hfindex, tvb, start, &length);
+       new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
 
        if (new_fi == NULL)
                return NULL;
 
-       return proto_tree_new_item(new_fi, tree, tvb, start,
-               length, encoding);
+       return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
 }
 
 /* Add a FT_NONE to a proto_tree */