From 19c45892461da6f1767190c86c62dab02db8a2e3 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Mon, 14 May 2018 00:22:44 +0200 Subject: proto: handle split bits covering more than 32 bits proto_tree_add_split_bits_item_ret_val can handle bits from an arbitrary sized buffer, as long as it covers no more than 64 bits. If the octet-aligned mask covers up to 32 bits, then this mask is also shown. If this mask was larger than 64 bits, then undefined behavior could occur, so check for that. For larger masks, instead of "= GmPRS Terminal Type: Unknown (96)", display "7 bits = GmPRS Terminal Type: Unknown (96)" instead. Bug: 13613 Change-Id: I111cf6a0705f999e42d83bfe57ac84f414946d0b Link: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1158 Reviewed-on: https://code.wireshark.org/review/27517 Petri-Dish: Peter Wu Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- epan/proto.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/epan/proto.c b/epan/proto.c index 95298bfb80..20d075098d 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -11393,13 +11393,13 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbu guint64 crumb_mask, crumb_value; guint8 crumb_end_bit_offset; - DISSECTOR_ASSERT(i < 64); crumb_value = tvb_get_bits64(tvb, bit_offset + crumb_spec[i].crumb_bit_offset, crumb_spec[i].crumb_bit_length, ENC_BIG_ENDIAN); value += crumb_value; no_of_bits += crumb_spec[i].crumb_bit_length; + DISSECTOR_ASSERT_HINT(no_of_bits <= 64, "a value larger than 64 bits cannot be represented"); /* The bitmask is 64 bit, left-aligned, starting at the first bit of the octet containing the initial offset. @@ -11415,8 +11415,13 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbu if (crumb_end_bit_offset > mask_greatest_bit_offset) { mask_greatest_bit_offset = crumb_end_bit_offset; } - composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset)); - composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset)); + /* Currently the bitmap of the crumbs are only shown if + * smaller than 32 bits. Do not bother calculating the + * mask if it is larger than that. */ + if (crumb_end_bit_offset <= 32) { + composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset)); + composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset)); + } } /* Shift left for the next segment */ value <<= crumb_spec[++i].crumb_bit_length; @@ -11462,6 +11467,9 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbu (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)), (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)), mask_greatest_bit_offset); + } else { + /* If the bitmask is too large, try to describe its contents. */ + g_snprintf(bf_str, sizeof(bf_str), "%d bits", no_of_bits); } switch (hf_field->type) { -- cgit v1.2.3