diff options
author | Gerald Combs <gerald@wireshark.org> | 2018-02-20 11:29:49 -0800 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2018-02-21 01:06:51 +0000 |
commit | 2b74b5c4c8836f413c675d8f7f80c8356b6b1722 (patch) | |
tree | da4cfaa3e0b67c3442fc161d55beca180a5ad69a /epan | |
parent | 9c5803ff7618002b8d18cfcd65fa44ec20fb1c76 (diff) |
BER: Add a length check.
Add a common large length reporting function. Add a length check to
dissect_ber_set.
Bug: 14444.
Change-Id: I6093b5342439cd0ee08f060b8d74b3ae54b3b8f8
Reviewed-on: https://code.wireshark.org/review/25931
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot
Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-ber.c | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/epan/dissectors/packet-ber.c b/epan/dissectors/packet-ber.c index 17a1440af5..43d54fc098 100644 --- a/epan/dissectors/packet-ber.c +++ b/epan/dissectors/packet-ber.c @@ -705,6 +705,23 @@ ber_add_bad_length_error(packet_info *pinfo, proto_tree *tree, } /* + * Add an "exceeds tvb length" error. + */ +static void +ber_add_large_length_error(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, + const gint offset, const guint32 length) +{ + proto_item *cause; + + cause = proto_tree_add_string_format_value( + tree, hf_ber_error, tvb, offset, length, "illegal_length", + "length %u longer than tvb_reported_length_remaining: %d", + length, + tvb_reported_length_remaining(tvb, offset)); + expert_add_info(pinfo, cause, &ei_ber_error_length); +} + +/* * Like proto_tree_add_item(), but checks whether the length of the item * being added is appropriate for the type of the item being added, so * if it's not, we report an error rather than a dissector bug. @@ -842,12 +859,7 @@ try_dissect_unknown_ber(packet_info *pinfo, tvbuff_t *tvb, volatile int offset, offset = dissect_ber_identifier(pinfo, tree, tvb, start_offset, &ber_class, &pc, &tag); offset = dissect_ber_length(pinfo, tree, tvb, offset, &len, NULL); } - cause = proto_tree_add_string_format_value( - tree, hf_ber_error, tvb, offset, len, "illegal_length", - "length:%u longer than tvb_reported_length_remaining:%d", - len, - tvb_reported_length_remaining(tvb, offset)); - expert_add_info(pinfo, cause, &ei_ber_error_length); + ber_add_large_length_error(pinfo, tree, tvb, offset, len); return tvb_reported_length(tvb); } /* we don't care about the class only on the constructor flag */ @@ -1589,12 +1601,7 @@ proto_tree_add_debug_text(tree, "OCTET STRING dissect_ber_octet_string(%s) enter * error - short frame, or this item runs past the * end of the item containing it */ - cause = proto_tree_add_string_format_value( - tree, hf_ber_error, tvb, offset, len, "illegal_length", - "length:%u longer than tvb_reported_length_remaining:%d", - len, - len_remain); - expert_add_info(actx->pinfo, cause, &ei_ber_error_length); + ber_add_large_length_error(actx->pinfo, tree, tvb, offset, len); return end_offset; } @@ -2053,12 +2060,7 @@ dissect_ber_real(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbu len_remain = (guint32)tvb_reported_length_remaining(tvb, offset); if (len_remain < val_length) { /* error - this item runs past the end of the item containing it */ - cause = proto_tree_add_string_format_value( - tree, hf_ber_error, tvb, offset, val_length, "illegal_length", - "length:%u longer than tvb_reported_length_remaining:%d", - val_length, - len_remain); - expert_add_info(actx->pinfo, cause, &ei_ber_error_length); + ber_add_large_length_error(actx->pinfo, tree, tvb, offset, val_length); return end_offset; } } @@ -2560,13 +2562,17 @@ proto_tree_add_debug_text(tree, "SET dissect_ber_set(%s) entered\n", name); offset = get_ber_length(tvb, offset, &len, &ind_field); eoffset = offset + len; + if (len > (guint32)(end_offset - offset) || len > (guint32) tvb_reported_length_remaining(tvb, offset)) { + ber_add_large_length_error(actx->pinfo, tree, tvb, offset, len); + return end_offset; + } + /* Look through the Set to see if this class/id exists and * hasn't been seen before * Skip check completely if ber_class == ANY * of if NOCHKTAG is set */ - for (first_pass = TRUE, cset = set, set_idx = 0; cset->func || first_pass; cset++, set_idx++) { /* we reset for a second pass when we will look for choices */ |