aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2018-02-20 11:29:49 -0800
committerMichael Mann <mmann78@netscape.net>2018-02-21 01:06:51 +0000
commit2b74b5c4c8836f413c675d8f7f80c8356b6b1722 (patch)
treeda4cfaa3e0b67c3442fc161d55beca180a5ad69a /epan
parent9c5803ff7618002b8d18cfcd65fa44ec20fb1c76 (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.c44
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 */