From cbe8af0a8b75399f3fe909ee8b838eeedd6fae40 Mon Sep 17 00:00:00 2001 From: Evan Huus Date: Thu, 17 Oct 2013 12:24:25 +0000 Subject: 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 --- epan/proto.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) (limited to 'epan/proto.c') 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 -- cgit v1.2.3