diff options
author | Guy Harris <guy@alum.mit.edu> | 2018-04-19 20:18:10 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2018-04-20 03:18:47 +0000 |
commit | 0a130c5756eda79cbb55f1d38824fbaf9d1abc68 (patch) | |
tree | fb3188f1965219c227e82fb5fcb7cc5307a5e1fc /epan/tvbuff_subset.c | |
parent | 9011a25afc598bfb5d46be92b2ef112cd1b17594 (diff) |
Handle subset tvbuffs where the length goes past the end of the parent.
Add a "contained length" to tvbuffs. For non-subset tvbuffs, that's the
same as the reported length. For a subset tvbuff, that's the amount of
the reported data that was actually present in the "contained data" of
the parent tvbuff.
This is unaffected by the *captured* length of any tvbuff; that differs
from the contained length only if the capture was cut short by a
snapshot length.
If a reference is within the reported data, but not within the contained
data, a ContainedBoundsError exception is thrown. This exception
represents a protocol error, rather than a reference past the captured
data in the packet; we treat it as such.
Change-Id: Ide87f81238eaeb89b3093f54a87bf7f715485af5
Reviewed-on: https://code.wireshark.org/review/27039
Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'epan/tvbuff_subset.c')
-rw-r--r-- | epan/tvbuff_subset.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/epan/tvbuff_subset.c b/epan/tvbuff_subset.c index 518d573bc5..8a33147480 100644 --- a/epan/tvbuff_subset.c +++ b/epan/tvbuff_subset.c @@ -95,7 +95,7 @@ static const struct tvb_ops tvb_subset_ops = { }; static tvbuff_t * -tvb_new_with_subset(tvbuff_t *backing, const gint reported_length, +tvb_new_with_subset(tvbuff_t *backing, const guint reported_length, const guint subset_tvb_offset, const guint subset_tvb_length) { tvbuff_t *tvb = tvb_new(&tvb_subset_ops); @@ -106,14 +106,14 @@ tvb_new_with_subset(tvbuff_t *backing, const gint reported_length, subset_tvb->subset.tvb = backing; tvb->length = subset_tvb_length; + /* + * The contained length must not exceed what remains in the + * backing tvbuff. + */ + tvb->contained_length = MIN(reported_length, backing->contained_length - subset_tvb_offset); tvb->flags = backing->flags; - if (reported_length == -1) { - tvb->reported_length = backing->reported_length - subset_tvb_offset; - } - else { - tvb->reported_length = reported_length; - } + tvb->reported_length = reported_length; tvb->initialized = TRUE; /* Optimization. If the backing buffer has a pointer to contiguous, real data, @@ -137,6 +137,7 @@ tvb_new_subset_length_caplen(tvbuff_t *backing, const gint backing_offset, const tvbuff_t *tvb; guint subset_tvb_offset; guint subset_tvb_length; + guint actual_reported_length; DISSECTOR_ASSERT(backing && backing->initialized); @@ -146,7 +147,12 @@ tvb_new_subset_length_caplen(tvbuff_t *backing, const gint backing_offset, const &subset_tvb_offset, &subset_tvb_length); - tvb = tvb_new_with_subset(backing, reported_length, + if (reported_length == -1) + actual_reported_length = backing->reported_length - subset_tvb_offset; + else + actual_reported_length = (guint)reported_length; + + tvb = tvb_new_with_subset(backing, actual_reported_length, subset_tvb_offset, subset_tvb_length); tvb_add_to_chain(backing, tvb); @@ -167,7 +173,8 @@ tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint r THROW_ON(reported_length < 0, ReportedBoundsError); /* - * Give the next dissector only captured_length bytes. + * Cut the captured length short, so it doesn't go past the subset's + * reported length. */ captured_length = tvb_captured_length_remaining(backing, backing_offset); THROW_ON(captured_length < 0, BoundsError); @@ -178,7 +185,7 @@ tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint r &subset_tvb_offset, &subset_tvb_length); - tvb = tvb_new_with_subset(backing, reported_length, + tvb = tvb_new_with_subset(backing, (guint)reported_length, subset_tvb_offset, subset_tvb_length); tvb_add_to_chain(backing, tvb); @@ -192,12 +199,16 @@ tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset) tvbuff_t *tvb; guint subset_tvb_offset; guint subset_tvb_length; + guint reported_length; tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */, &subset_tvb_offset, &subset_tvb_length); - tvb = tvb_new_with_subset(backing, -1 /* reported_length */, + THROW_ON(backing->reported_length < subset_tvb_offset, ReportedBoundsError); + reported_length = backing->reported_length - subset_tvb_offset; + + tvb = tvb_new_with_subset(backing, reported_length, subset_tvb_offset, subset_tvb_length); tvb_add_to_chain(backing, tvb); |