diff options
author | Peter Wu <peter@lekensteyn.nl> | 2018-05-14 00:22:44 +0200 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-05-14 08:13:47 +0000 |
commit | 19c45892461da6f1767190c86c62dab02db8a2e3 (patch) | |
tree | 8b53ef9285272bf78b1ef62cf76668ec99c920f3 /epan/proto.c | |
parent | b10dbb861457736991943fbddb13356ff6eb4c81 (diff) |
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 <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/proto.c')
-rw-r--r-- | epan/proto.c | 14 |
1 files 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) { |