diff --git a/epan/dissectors/packet-frame.c b/epan/dissectors/packet-frame.c
index 3fbce14..ed9e74c 100644
--- a/epan/dissectors/packet-frame.c
+++ b/epan/dissectors/packet-frame.c
@@ -228,9 +228,9 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
}
if(pinfo->fd->opt_comment){
- item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, -1, ENC_NA);
+ item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, 0, ENC_NA);
comments_tree = proto_item_add_subtree(item, ett_comments);
- comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, -1,
+ comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, 0,
pinfo->fd->opt_comment, "%s",
pinfo->fd->opt_comment);
expert_add_info_format(pinfo, comment_item, PI_COMMENTS_GROUP, PI_COMMENT,
@@ -259,7 +259,7 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
cap_plurality = plurality(cap_len, "", "s");
frame_plurality = plurality(frame_len, "", "s");
- ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, -1,
+ ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_length(tvb),
"Frame %u: %u byte%s on wire",
pinfo->fd->num, frame_len, frame_plurality);
if (generate_bits_field)
@@ -458,7 +458,7 @@ dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
if (pinfo->fd->flags.ignored) {
/* Ignored package, stop handling here */
col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>");
- proto_tree_add_text (tree, tvb, 0, -1, "This frame is marked as ignored");
+ proto_tree_add_text (tree, tvb, 0, 0, "This frame is marked as ignored");
return;
}
diff --git a/epan/proto.c b/epan/proto.c
index 9e55ea7..775aca8 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -3536,15 +3536,7 @@ get_hfi_and_length(int hfindex, tvbuff_t *tvb, const gint start, gint *length,
* end of the tvbuff, so we throw an
* exception.
*/
- *length = tvb_length_remaining(tvb, start);
- if (*length < 0) {
- /*
- * Use "tvb_ensure_bytes_exist()"
- * to force the appropriate exception
- * to be thrown.
- */
- tvb_ensure_bytes_exist(tvb, start, 0);
- }
+ *length = tvb_length_remaining_cheat(tvb, start);
DISSECTOR_ASSERT(*length >= 0);
break;
diff --git a/epan/tvbuff.c b/epan/tvbuff.c
index 0b9d8fb..ca72263 100644
--- a/epan/tvbuff.c
+++ b/epan/tvbuff.c
@@ -427,6 +427,51 @@ tvb_new_with_subset(tvbuff_t *backing, const gint reported_length,
return tvb;
}
+static inline int
+compute_offset(const tvbuff_t *tvb, const gint offset, guint *offset_ptr)
+{
+ if (offset >= 0) {
+ /* Positive offset - relative to the beginning of the packet. */
+ if ((guint) offset <= tvb->length) {
+ *offset_ptr = offset;
+ } else if ((guint) offset <= tvb->reported_length) {
+ return BoundsError;
+ } else if (tvb->flags & TVBUFF_FRAGMENT) {
+ return FragmentBoundsError;
+ } else {
+ return ReportedBoundsError;
+ }
+ }
+ else {
+ /* Negative offset - relative to the end of the packet. */
+ if ((guint) -offset <= tvb->length) {
+ *offset_ptr = tvb->length + offset;
+ } else if ((guint) -offset <= tvb->reported_length) {
+ return BoundsError;
+ } else if (tvb->flags & TVBUFF_FRAGMENT) {
+ return FragmentBoundsError;
+ } else {
+ return ReportedBoundsError;
+ }
+ }
+
+ return 0;
+}
+
+
+static inline int
+compute_offset_and_remaining(const tvbuff_t *tvb, const gint offset, guint *offset_ptr, guint *rem_len)
+{
+ int exception;
+
+ exception = compute_offset(tvb, offset, offset_ptr);
+ if (!exception)
+ *rem_len = tvb->length - *offset_ptr;
+
+ return exception;
+}
+
+
tvbuff_t *
tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
{
@@ -701,6 +746,24 @@ tvb_length_remaining(const tvbuff_t *tvb, const gint offset)
}
}
+/* Just like tvb_length_remaining except it doesn't have to
+ * guarantee that at least one byte is available, it simply guarantees that the
+ * offset exists (so a 0 offset in a 0-length tvb won't throw) */
+guint
+tvb_length_remaining_cheat(const tvbuff_t *tvb, const gint offset)
+{
+ guint abs_offset, rem_length;
+ int exception;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &rem_length);
+ if (exception)
+ THROW(exception);
+
+ return rem_length;
+}
+
guint
tvb_ensure_length_remaining(const tvbuff_t *tvb, const gint offset)
{
diff --git a/epan/tvbuff.h b/epan/tvbuff.h
index 8950feb..dbb8c57 100644
--- a/epan/tvbuff.h
+++ b/epan/tvbuff.h
@@ -221,6 +221,12 @@ WS_DLL_PUBLIC guint tvb_length(const tvbuff_t*);
* indicate that offset is out of bounds. No exception is thrown. */
WS_DLL_PUBLIC gint tvb_length_remaining(const tvbuff_t*, const gint offset);
+/** Same as above, but permits offsets at the end of the tvbuff (such as an
+ * offset of 0 in a tvbuff with a snapshot length of 0, which is a silly thing
+ * to do but we have to be able to handle it gracefully). */
+WS_DLL_PUBLIC guint tvb_length_remaining_cheat(
+ const tvbuff_t *tvb, const gint offset);
+
/** Same as above, but throws an exception if the offset is out of bounds. */
WS_DLL_PUBLIC guint tvb_ensure_length_remaining(const tvbuff_t*, const gint offset);