diff options
author | Peter Wu <peter@lekensteyn.nl> | 2016-02-24 03:06:46 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2016-02-24 06:06:31 +0000 |
commit | 9ff932bf5ea554f9e94ee1364284aff9eb3fd619 (patch) | |
tree | 18443cf3ef79e676e2fc68f914f21a2c4bc49e32 /epan | |
parent | e395633224fd448fd93af0450b812228192d3a1b (diff) |
ber: avoid deep recursion for constructed strings
Bound the recursion depth to avoid a stack overflow while parsing a
deeply nested constructed string.
Call chain before this patch:
- dissect_ber_octet_string
- dissect_ber_constrained_octet_string
- reassemble_octet_string (called for constructed types)
- dissect_ber_octet_string *recursion*
After this patch, the reassemble_octet_string will throw if the maximum
recursion depth is reached.
Bug: 11822
Change-Id: I6753e3c9f5dcbfab0e4c174418b2c7eb784d64d2
Reviewed-on: https://code.wireshark.org/review/14108
Reviewed-by: Michael Mann <mmann78@netscape.net>
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-ber.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/epan/dissectors/packet-ber.c b/epan/dissectors/packet-ber.c index 81e4d38feb..43dffa438c 100644 --- a/epan/dissectors/packet-ber.c +++ b/epan/dissectors/packet-ber.c @@ -1421,7 +1421,10 @@ static void ber_defragment_cleanup(void) { } static int -reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, gint hf_id, tvbuff_t *tvb, int offset, guint32 con_len, gboolean ind, tvbuff_t **out_tvb) +dissect_ber_constrained_octet_string_impl(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb, guint nest_level); + +static int +reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, gint hf_id, tvbuff_t *tvb, int offset, guint32 con_len, gboolean ind, tvbuff_t **out_tvb, guint nest_level) { fragment_head *fd_head = NULL; tvbuff_t *next_tvb = NULL; @@ -1431,6 +1434,11 @@ reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, gint hf_id, tvbuff_t gboolean fragment = TRUE; gboolean firstFragment = TRUE; + if (nest_level > BER_MAX_NESTING) { + /* Assume that we have a malformed packet. */ + THROW(ReportedBoundsError); + } + /* so we need to consume octet strings for the given length */ if (out_tvb) @@ -1444,7 +1452,8 @@ reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, gint hf_id, tvbuff_t while(!fd_head) { - offset = dissect_ber_octet_string(FALSE, actx, NULL, tvb, offset, hf_id, &next_tvb); + offset = dissect_ber_constrained_octet_string_impl(FALSE, actx, NULL, + tvb, offset, NO_BOUND, NO_BOUND, hf_id, &next_tvb, nest_level + 1); if (next_tvb == NULL) { /* Assume that we have a malformed packet. */ @@ -1520,6 +1529,11 @@ reassemble_octet_string(asn1_ctx_t *actx, proto_tree *tree, gint hf_id, tvbuff_t /* 8.7 Encoding of an octetstring value */ int dissect_ber_constrained_octet_string(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb) { + return dissect_ber_constrained_octet_string_impl(implicit_tag, actx, tree, tvb, offset, min_len, max_len, hf_id, out_tvb, 0); +} + +static int +dissect_ber_constrained_octet_string_impl(gboolean implicit_tag, asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb, int offset, gint32 min_len, gint32 max_len, gint hf_id, tvbuff_t **out_tvb, guint nest_level) { gint8 ber_class; gboolean pc, ind; gint32 tag; @@ -1613,7 +1627,7 @@ printf("OCTET STRING dissect_ber_octet_string(%s) entered\n", name); if (pc) { /* constructed */ - end_offset = reassemble_octet_string(actx, tree, hf_id, tvb, offset, len, ind, out_tvb); + end_offset = reassemble_octet_string(actx, tree, hf_id, tvb, offset, len, ind, out_tvb, nest_level); } else { /* primitive */ gint length_remaining; |