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