summaryrefslogtreecommitdiff
path: root/epan
diff options
context:
space:
mode:
authorEvan Huus <eapache@gmail.com>2013-10-22 16:29:10 +0000
committerEvan Huus <eapache@gmail.com>2013-10-22 16:29:10 +0000
commit7aee8b2dcf70cade2c3732eef0649220a79e82a8 (patch)
treecb21f0d551aff346b89fe991ae9e1ca364ee914c /epan
parenta3a15ff90b3aca7f94e853ddcaeb1f373368a29c (diff)
downloadwireshark-7aee8b2dcf70cade2c3732eef0649220a79e82a8.tar.gz
Optimize tvb_ensure_bytes_exist through manual inlining and removal of redundant
checks and computations. Should contain no behavioural changes at *all*, I hope. svn path=/trunk/; revision=52768
Diffstat (limited to 'epan')
-rw-r--r--epan/tvbuff.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/epan/tvbuff.c b/epan/tvbuff.c
index e783746acd..d6c44a08ed 100644
--- a/epan/tvbuff.c
+++ b/epan/tvbuff.c
@@ -467,7 +467,7 @@ tvb_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
void
tvb_ensure_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
{
- guint abs_offset, abs_length;
+ guint real_offset, end_offset;
DISSECTOR_ASSERT(tvb && tvb->initialized);
@@ -484,7 +484,56 @@ tvb_ensure_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length
if (length < 0) {
THROW(ReportedBoundsError);
}
- check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
+
+ /* XXX: Below this point could be replaced with a call to
+ * check_offset_length with no functional change, however this is a
+ * *very* hot path and check_offset_length is not well-optimized for
+ * this case, so we eat some code duplication for a lot of speedup. */
+
+ if (offset >= 0) {
+ /* Positive offset - relative to the beginning of the packet. */
+ if ((guint) offset <= tvb->length) {
+ real_offset = offset;
+ } else if ((guint) offset <= tvb->reported_length) {
+ THROW(BoundsError);
+ } else if (tvb->flags & TVBUFF_FRAGMENT) {
+ THROW(FragmentBoundsError);
+ } else {
+ THROW(ReportedBoundsError);
+ }
+ }
+ else {
+ /* Negative offset - relative to the end of the packet. */
+ if ((guint) -offset <= tvb->length) {
+ real_offset = tvb->length + offset;
+ } else if ((guint) -offset <= tvb->reported_length) {
+ THROW(BoundsError);
+ } else if (tvb->flags & TVBUFF_FRAGMENT) {
+ THROW(FragmentBoundsError);
+ } else {
+ THROW(ReportedBoundsError);
+ }
+ }
+
+ /*
+ * Compute the offset of the first byte past the length.
+ */
+ end_offset = real_offset + length;
+
+ /*
+ * Check for an overflow
+ */
+ if (end_offset < real_offset)
+ THROW(BoundsError);
+
+ if (G_LIKELY(end_offset <= tvb->length))
+ return;
+ else if (end_offset <= tvb->reported_length)
+ THROW(BoundsError);
+ else if (tvb->flags & TVBUFF_FRAGMENT)
+ THROW(FragmentBoundsError);
+ else
+ THROW(ReportedBoundsError);
}
gboolean