aboutsummaryrefslogtreecommitdiffstats
path: root/epan/proto.c
diff options
context:
space:
mode:
authorEvan Huus <eapache@gmail.com>2013-10-17 12:24:25 +0000
committerEvan Huus <eapache@gmail.com>2013-10-17 12:24:25 +0000
commitcbe8af0a8b75399f3fe909ee8b838eeedd6fae40 (patch)
treef4c94c87c5cfc34faa14769b5a41908918c6db2a /epan/proto.c
parent744f47107e28a8632cf79fde901713f73fd0e349 (diff)
Revert the optimization in r52578. As Jakub predicted, it caused at least one
infinite loop to pop up. We're just going to have to eat the performance hit. (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9282) svn path=/trunk/; revision=52660
Diffstat (limited to 'epan/proto.c')
-rw-r--r--epan/proto.c52
1 files changed, 44 insertions, 8 deletions
diff --git a/epan/proto.c b/epan/proto.c
index 46039b1425..28d83ed1d5 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -1750,6 +1750,45 @@ 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, const guint encoding)
+{
+ 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, encoding);
+ if (n > size + n) {
+ /* If n > size + n then we have an integer overflow, so
+ * set size to -1, which will force the
+ * tvb_ensure_bytes_exist call below to throw a
+ * ReportedBoundsError
+ */
+ size = -1;
+ }
+ else {
+ size += n;
+ }
+ } else if (hfinfo->type == FT_STRINGZ) {
+ /* If we're fetching until the end of the TVB, only validate
+ * that the offset is within range.
+ */
+ if (length == -1)
+ size = 0;
+ }
+
+ 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 *
@@ -1761,13 +1800,11 @@ proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *t
DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
- if (tvb) {
- tvb_ensure_offset_exists(tvb, start);
- }
+ get_hfi_length(hfinfo, tvb, start, &length, &item_length);
+ test_length(hfinfo, tree, tvb, start, item_length, encoding);
TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
- get_hfi_length(hfinfo, tvb, start, &length, &item_length);
new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
if (new_fi == NULL)
@@ -6959,15 +6996,14 @@ proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
const guint encoding)
{
header_field_info *hfinfo;
+ gint octet_length;
gint octet_offset;
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+ octet_length = (no_of_bits + 7) >> 3;
octet_offset = bit_offset >> 3;
-
- if (tvb) {
- tvb_ensure_offset_exists(tvb, octet_offset);
- }
+ test_length(hfinfo, tree, tvb, octet_offset, octet_length, encoding);
/* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
* but only after doing a bunch more work (which we can, in the common