From Jakub Zawadzki via bug #4289: (Fix for) Frame arrival times (pcap)
[obnox/wireshark/wip.git] / epan / tvbuff.c
index de0756ab4e3659439db0991e4e575fa7513d3955..be7e32b14ffe2d949b2046709e89410a66a7c209 100644 (file)
@@ -3,11 +3,11 @@
  * Testy, Virtual(-izable) Buffer of guint8*'s
  *
  * "Testy" -- the buffer gets mad when an attempt to access data
- *             beyond the bounds of the buffer. An exception is thrown.
+ *             beyond the bounds of the buffer. An exception is thrown.
  *
  * "Virtual" -- the buffer can have its own data, can use a subset of
- *             the data of a backing tvbuff, or can be a composite of
- *             other tvbuffs.
+ *             the data of a backing tvbuff, or can be a composite of
+ *             other tvbuffs.
  *
  * $Id$
  *
@@ -58,23 +58,32 @@ ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
 static const guint8*
 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
 
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
 /* We dole out tvbuff's from this memchunk. */
 static GMemChunk *tvbuff_mem_chunk = NULL;
+#endif
 
 void
 tvbuff_init(void)
 {
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
        if (!tvbuff_mem_chunk)
                tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
+#endif
 }
 
 void
 tvbuff_cleanup(void)
 {
+#if GLIB_CHECK_VERSION(2,10,0)
+#else
        if (tvbuff_mem_chunk)
                g_mem_chunk_destroy(tvbuff_mem_chunk);
 
        tvbuff_mem_chunk = NULL;
+#endif
 }
 
 static void
@@ -125,13 +134,27 @@ tvb_new(tvbuff_type type)
 {
        tvbuff_t        *tvb;
 
+#if GLIB_CHECK_VERSION(2,10,0)
+       tvb = g_slice_new(tvbuff_t);
+#else
        tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
+#endif
 
        tvb_init(tvb, type);
 
        return tvb;
 }
 
+static tvbuff_t*
+tvb_new_with_subset(guint subset_tvb_offset, guint subset_tvb_length)
+{
+       tvbuff_t *tvb = tvb_new(TVBUFF_SUBSET);
+       tvb->tvbuffs.subset.offset = subset_tvb_offset;
+       tvb->tvbuffs.subset.length = subset_tvb_length;
+
+       return tvb;
+}
+
 void
 tvb_free(tvbuff_t* tvb)
 {
@@ -185,7 +208,11 @@ tvb_free(tvbuff_t* tvb)
                        g_slist_free(tvb->used_in);
                }
 
+#if GLIB_CHECK_VERSION(2,10,0)
+               g_slice_free(tvbuff_t, tvb);
+#else
                g_chunk_free(tvb, tvbuff_mem_chunk);
+#endif
        }
 }
 
@@ -253,6 +280,15 @@ tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
        add_to_used_in_list(parent, child);
 }
 
+static void
+tvb_set_real_data_no_exceptions(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
+{
+       tvb->real_data = data;
+       tvb->length = length;
+       tvb->reported_length = reported_length;
+       tvb->initialized = TRUE;
+}
+
 void
 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
 {
@@ -260,33 +296,21 @@ tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported
        DISSECTOR_ASSERT(tvb->type == TVBUFF_REAL_DATA);
        DISSECTOR_ASSERT(!tvb->initialized);
 
-       if (reported_length < -1) {
-               THROW(ReportedBoundsError);
-       }
+       THROW_ON(reported_length < -1, ReportedBoundsError);
 
-       tvb->real_data          = data;
-       tvb->length             = length;
-       tvb->reported_length    = reported_length;
-       tvb->initialized        = TRUE;
+       tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
 }
 
 tvbuff_t*
 tvb_new_real_data(const guint8* data, guint length, gint reported_length)
 {
-       static tvbuff_t *last_tvb=NULL;
        tvbuff_t        *tvb;
 
-       tvb = tvb_new(TVBUFF_REAL_DATA);
+       THROW_ON(reported_length < -1, ReportedBoundsError);
 
-       if(last_tvb){
-               tvb_free(last_tvb);
-       }
-       /* remember this tvb in case we throw an exception and
-        * lose the pointer to it.
-        */
-       last_tvb=tvb;
+       tvb = tvb_new(TVBUFF_REAL_DATA);
 
-       tvb_set_real_data(tvb, data, length, reported_length);
+       tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
 
        /*
         * This is the top-level real tvbuff for this data source,
@@ -294,9 +318,6 @@ tvb_new_real_data(const guint8* data, guint length, gint reported_length)
         */
        tvb->ds_tvb = tvb;
 
-       /* ok no exception so we dont need to remember it any longer */
-       last_tvb=NULL;
-
        return tvb;
 }
 
@@ -307,7 +328,7 @@ tvb_new_child_real_data(tvbuff_t *parent, const guint8* data, guint length, gint
        if (tvb) {
                tvb_set_child_real_data_tvbuff (parent, tvb);
        }
-       
+
        return tvb;
 }
 
@@ -325,7 +346,7 @@ tvb_new_child_real_data(tvbuff_t *parent, const guint8* data, guint length, gint
  * that gets an exception, so the error is reported as an error in that
  * protocol rather than the containing protocol.  */
 static gboolean
-compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
+compute_offset_length(guint tvb_length, guint tvb_reported_length, gint offset, gint length,
                guint *offset_ptr, guint *length_ptr, int *exception)
 {
        DISSECTOR_ASSERT(offset_ptr);
@@ -334,13 +355,13 @@ compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
        /* Compute the offset */
        if (offset >= 0) {
                /* Positive offset - relative to the beginning of the packet. */
-               if ((guint) offset > tvb->reported_length) {
+               if ((guint) offset > tvb_reported_length) {
                        if (exception) {
                                *exception = ReportedBoundsError;
                        }
                        return FALSE;
                }
-               else if ((guint) offset > tvb->length) {
+               else if ((guint) offset > tvb_length) {
                        if (exception) {
                                *exception = BoundsError;
                        }
@@ -352,20 +373,20 @@ compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
        }
        else {
                /* Negative offset - relative to the end of the packet. */
-               if ((guint) -offset > tvb->reported_length) {
+               if ((guint) -offset > tvb_reported_length) {
                        if (exception) {
                                *exception = ReportedBoundsError;
                        }
                        return FALSE;
                }
-               else if ((guint) -offset > tvb->length) {
+               else if ((guint) -offset > tvb_length) {
                        if (exception) {
                                *exception = BoundsError;
                        }
                        return FALSE;
                }
                else {
-                       *offset_ptr = tvb->length + offset;
+                       *offset_ptr = tvb_length + offset;
                }
        }
 
@@ -378,7 +399,7 @@ compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
                return FALSE;
        }
        else if (length == -1) {
-               *length_ptr = tvb->length - *offset_ptr;
+               *length_ptr = tvb_length - *offset_ptr;
        }
        else {
                *length_ptr = length;
@@ -389,14 +410,12 @@ compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
 
 
 static gboolean
-check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
+check_offset_length_no_exception(guint tvb_length, guint tvb_reported_length, gint offset, gint length,
                guint *offset_ptr, guint *length_ptr, int *exception)
 {
        guint   end_offset;
 
-       DISSECTOR_ASSERT(tvb && tvb->initialized);
-
-       if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
+       if (!compute_offset_length(tvb_length, tvb_reported_length, offset, length, offset_ptr, length_ptr, exception)) {
                return FALSE;
        }
 
@@ -420,10 +439,10 @@ check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
         * If not, return TRUE; otherwise, return FALSE and, if "exception"
         * is non-null, return the appropriate exception through it.
         */
-       if (end_offset <= tvb->length) {
+       if (end_offset <= tvb_length) {
                return TRUE;
        }
-       else if (end_offset <= tvb->reported_length) {
+       else if (end_offset <= tvb_reported_length) {
                if (exception) {
                        *exception = BoundsError;
                }
@@ -441,35 +460,20 @@ check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
  * either is out of bounds. Sets integer ptrs to the new offset
  * and length. */
 static void
-check_offset_length(tvbuff_t *tvb, gint offset, gint length,
+check_offset_length(guint tvb_length, guint tvb_reported_length, gint offset, gint length,
                guint *offset_ptr, guint *length_ptr)
 {
        int exception = 0;
 
-       if (!check_offset_length_no_exception(tvb, offset, length, offset_ptr, length_ptr, &exception)) {
+       if (!check_offset_length_no_exception(tvb_length, tvb_reported_length, offset, length, offset_ptr, length_ptr, &exception)) {
                DISSECTOR_ASSERT(exception > 0);
                THROW(exception);
        }
-       return;
 }
 
-
-void
-tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
-               gint backing_offset, gint backing_length, gint reported_length)
+static void
+tvb_set_subset_no_exceptions(tvbuff_t *tvb, tvbuff_t *backing, gint reported_length)
 {
-       DISSECTOR_ASSERT(tvb);
-       DISSECTOR_ASSERT(tvb->type == TVBUFF_SUBSET);
-       DISSECTOR_ASSERT(!tvb->initialized);
-
-       if (reported_length < -1) {
-               THROW(ReportedBoundsError);
-       }
-
-       check_offset_length(backing, backing_offset, backing_length,
-                       &tvb->tvbuffs.subset.offset,
-                       &tvb->tvbuffs.subset.length);
-
        tvb->tvbuffs.subset.tvb         = backing;
        tvb->length                     = tvb->tvbuffs.subset.length;
 
@@ -489,24 +493,41 @@ tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
        }
 }
 
+void
+tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
+               gint backing_offset, gint backing_length, gint reported_length)
+{
+       DISSECTOR_ASSERT(tvb);
+       DISSECTOR_ASSERT(tvb->type == TVBUFF_SUBSET);
+       DISSECTOR_ASSERT(!tvb->initialized);
+
+       THROW_ON(reported_length < -1, ReportedBoundsError);
+
+       check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
+                       &tvb->tvbuffs.subset.offset,
+                       &tvb->tvbuffs.subset.length);
+
+       tvb_set_subset_no_exceptions(tvb, backing, reported_length);
+}
 
 tvbuff_t*
 tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
 {
-       static tvbuff_t *last_tvb=NULL;
        tvbuff_t        *tvb;
+       guint           subset_tvb_offset;
+       guint           subset_tvb_length;
 
-       tvb = tvb_new(TVBUFF_SUBSET);
+       DISSECTOR_ASSERT(backing && backing->initialized);
 
-       if(last_tvb){
-               tvb_free(last_tvb);
-       }
-       /* remember this tvb in case we throw an exception and
-        * lose the pointer to it.
-        */
-       last_tvb=tvb;
+       THROW_ON(reported_length < -1, ReportedBoundsError);
+
+       check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
+                       &subset_tvb_offset,
+                       &subset_tvb_length);
+
+       tvb = tvb_new_with_subset(subset_tvb_offset, subset_tvb_length);
 
-       tvb_set_subset(tvb, backing, backing_offset, backing_length, reported_length);
+       tvb_set_subset_no_exceptions(tvb, backing, reported_length);
 
        /*
         * The top-level data source of this tvbuff is the top-level
@@ -514,8 +535,29 @@ tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint
         */
        tvb->ds_tvb = backing->ds_tvb;
 
-       /* ok no exception so we dont need to remember it any longer */
-       last_tvb=NULL;
+       return tvb;
+}
+
+tvbuff_t*
+tvb_new_subset_remaining(tvbuff_t *backing, gint backing_offset)
+{
+       tvbuff_t        *tvb;
+       guint           subset_tvb_offset;
+       guint           subset_tvb_length;
+
+       check_offset_length(backing->length, backing->reported_length, backing_offset, -1 /* backing_length */,
+                       &subset_tvb_offset,
+                       &subset_tvb_length);
+
+       tvb = tvb_new_with_subset(subset_tvb_offset, subset_tvb_length);
+
+       tvb_set_subset_no_exceptions(tvb, backing, -1 /* reported_length */);
+
+       /*
+        * The top-level data source of this tvbuff is the top-level
+        * data source of its parent.
+        */
+       tvb->ds_tvb = backing->ds_tvb;
 
        return tvb;
 }
@@ -598,7 +640,7 @@ tvb_length_remaining(tvbuff_t *tvb, gint offset)
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
-       if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
+       if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
                return abs_length;
        }
        else {
@@ -614,7 +656,7 @@ tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
-       if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, &exception)) {
+       if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, &exception)) {
                THROW(exception);
        }
        if (abs_length == 0) {
@@ -643,7 +685,7 @@ tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
-       if (!compute_offset_length(tvb, offset, length, &abs_offset, &abs_length, NULL))
+       if (!compute_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length, NULL))
                return FALSE;
 
        if (abs_offset + abs_length <= tvb->length) {
@@ -676,7 +718,7 @@ tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
        if (length < 0) {
                THROW(ReportedBoundsError);
        }
-       check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
+       check_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length);
 }
 
 gboolean
@@ -685,7 +727,7 @@ tvb_offset_exists(tvbuff_t *tvb, gint offset)
        guint           abs_offset, abs_length;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
-       if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL))
+       if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL))
                return FALSE;
 
        if (abs_offset < tvb->length) {
@@ -711,7 +753,7 @@ tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
-       if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
+       if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
                if (tvb->reported_length >= abs_offset)
                        return tvb->reported_length - abs_offset;
                else
@@ -764,8 +806,8 @@ first_real_data_ptr(tvbuff_t *tvb)
 }
 #endif
 
-int
-offset_from_real_beginning(tvbuff_t *tvb, int counter)
+static guint
+offset_from_real_beginning(tvbuff_t *tvb, guint counter)
 {
        tvbuff_t        *member;
 
@@ -784,6 +826,12 @@ offset_from_real_beginning(tvbuff_t *tvb, int counter)
        return 0;
 }
 
+guint
+tvb_offset_from_real_beginning(tvbuff_t *tvb)
+{
+       return offset_from_real_beginning(tvb, 0);
+}
+
 static const guint8*
 composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
                guint abs_length)
@@ -810,7 +858,7 @@ composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
        }
        DISSECTOR_ASSERT(member_tvb);
 
-       if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
+       if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
                                abs_length, &member_offset, &member_length, NULL)) {
 
                /*
@@ -834,8 +882,8 @@ ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
 {
        guint   abs_offset, abs_length;
 
-       if (!check_offset_length_no_exception(tvb, offset, length,
-           &abs_offset, &abs_length, exception)) {
+       if (!check_offset_length_no_exception(tvb->length, tvb->reported_length, offset, length,
+               &abs_offset, &abs_length, exception)) {
                return NULL;
        }
 
@@ -888,7 +936,7 @@ fast_ensure_contiguous(tvbuff_t *tvb, gint offset, guint length)
        DISSECTOR_ASSERT(length <= 8);
 
        if (offset < 0 || !tvb->real_data) {
-           return ensure_contiguous(tvb, offset, length);
+               return ensure_contiguous(tvb, offset, length);
        }
 
        u_offset = offset;
@@ -972,7 +1020,7 @@ composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, size_t abs_len
        }
        DISSECTOR_ASSERT(member_tvb);
 
-       if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
+       if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
                                (gint) abs_length, &member_offset, &member_length, NULL)) {
 
                DISSECTOR_ASSERT(!tvb->real_data);
@@ -984,7 +1032,7 @@ composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, size_t abs_len
                 * then iterate across the other member tvb's, copying their portions
                 * until we have copied all data.
                 */
-               retval = compute_offset_length(member_tvb, abs_offset - composite->start_offsets[i], -1,
+               retval = compute_offset_length(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i], -1,
                                &member_offset, &member_length, NULL);
                DISSECTOR_ASSERT(retval);
 
@@ -1009,6 +1057,8 @@ tvb_memcpy(tvbuff_t *tvb, void* target, gint offset, size_t length)
 {
        guint   abs_offset, abs_length;
 
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
        /*
         * XXX - we should eliminate the "length = -1 means 'to the end
         * of the tvbuff'" convention, and use other means to achieve
@@ -1021,7 +1071,7 @@ tvb_memcpy(tvbuff_t *tvb, void* target, gint offset, size_t length)
         * instead, we check for a length <= 2^31-1.
         */
        DISSECTOR_ASSERT(length <= 0x7FFFFFFF);
-       check_offset_length(tvb, offset, (gint) length, &abs_offset, &abs_length);
+       check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
 
        if (tvb->real_data) {
                return memcpy(target, tvb->real_data + abs_offset, abs_length);
@@ -1061,7 +1111,9 @@ tvb_memdup(tvbuff_t *tvb, gint offset, size_t length)
        guint   abs_offset, abs_length;
        void    *duped;
 
-       check_offset_length(tvb, offset, (gint) length, &abs_offset, &abs_length);
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+       check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
 
        duped = g_malloc(abs_length);
        return tvb_memcpy(tvb, duped, abs_offset, abs_length);
@@ -1089,7 +1141,9 @@ ep_tvb_memdup(tvbuff_t *tvb, gint offset, size_t length)
        guint   abs_offset, abs_length;
        void    *duped;
 
-       check_offset_length(tvb, offset, (gint) length, &abs_offset, &abs_length);
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+       check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
 
        duped = ep_alloc(abs_length);
        return tvb_memcpy(tvb, duped, abs_offset, abs_length);
@@ -1224,7 +1278,7 @@ get_ieee_float(guint32 w)
 #endif
 
        exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
-           IEEE_SP_MANTISSA_WIDTH;
+               IEEE_SP_MANTISSA_WIDTH;
        mantissa |= IEEE_SP_IMPLIED_BIT;
 
        if (sign)
@@ -1285,7 +1339,7 @@ get_ieee_double(guint64 w)
 #endif
 
        exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
-           IEEE_DP_MANTISSA_WIDTH;
+               IEEE_DP_MANTISSA_WIDTH;
        mantissa |= IEEE_DP_IMPLIED_BIT;
 
        if (sign)
@@ -1501,26 +1555,26 @@ tvb_get_guid(tvbuff_t *tvb, gint offset, e_guid_t *guid, gboolean little_endian)
 }
 
 static const guint8 bit_mask8[] = {
-    0xff,
-    0x7f,
-    0x3f,
-    0x1f,
-    0x0f,
-    0x07,
-    0x03,
-    0x01
+       0xff,
+       0x7f,
+       0x3f,
+       0x1f,
+       0x0f,
+       0x07,
+       0x03,
+       0x01
 };
 
 /* Bit offset mask for number of bits = 8 - 16 */
 static const guint16 bit_mask16[] = {
-    0xffff,
-    0x7fff,
-    0x3fff,
-    0x1fff,
-    0x0fff,
-    0x07ff,
-    0x03ff,
-    0x01ff
+       0xffff,
+       0x7fff,
+       0x3fff,
+       0x1fff,
+       0x0fff,
+       0x07ff,
+       0x03ff,
+       0x01ff
 };
 
 /* Get 1 - 8 bits */
@@ -1559,14 +1613,14 @@ tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, gint no_of_bits)
 /* Get 9 - 16 bits */
 /* Bit offset mask for number of bits = 16 - 32 */
 static const guint32 bit_mask32[] = {
-    0xffffffff,
-    0x7fffffff,
-    0x3fffffff,
-    0x1fffffff,
-    0x0fffffff,
-    0x07ffffff,
-    0x03ffffff,
-    0x01ffffff
+       0xffffffff,
+       0x7fffffff,
+       0x3fffffff,
+       0x1fffffff,
+       0x0fffffff,
+       0x07ffffff,
+       0x03ffffff,
+       0x01ffffff
 };
 
 guint16
@@ -1613,14 +1667,14 @@ tvb_get_bits16(tvbuff_t *tvb, gint bit_offset, gint no_of_bits,gboolean little_e
 
 /* Bit offset mask for number of bits = 32 - 64 */
 static const guint64 bit_mask64[] = {
-    G_GINT64_CONSTANT(0xffffffffffffffffU),
-    G_GINT64_CONSTANT(0x7fffffffffffffffU),
-    G_GINT64_CONSTANT(0x3fffffffffffffffU),
-    G_GINT64_CONSTANT(0x1fffffffffffffffU),
-    G_GINT64_CONSTANT(0x0fffffffffffffffU),
-    G_GINT64_CONSTANT(0x07ffffffffffffffU),
-    G_GINT64_CONSTANT(0x03ffffffffffffffU),
-    G_GINT64_CONSTANT(0x01ffffffffffffffU)
+       G_GINT64_CONSTANT(0xffffffffffffffffU),
+       G_GINT64_CONSTANT(0x7fffffffffffffffU),
+       G_GINT64_CONSTANT(0x3fffffffffffffffU),
+       G_GINT64_CONSTANT(0x1fffffffffffffffU),
+       G_GINT64_CONSTANT(0x0fffffffffffffffU),
+       G_GINT64_CONSTANT(0x07ffffffffffffffU),
+       G_GINT64_CONSTANT(0x03ffffffffffffffU),
+       G_GINT64_CONSTANT(0x01ffffffffffffffU)
 };
 
 guint32
@@ -1707,6 +1761,28 @@ tvb_get_bits64(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_
        return value;
 }
 
+guint32
+tvb_get_bits(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean little_endian)
+{
+       /* This function can handle only up to 32 requested bits */
+       if (no_of_bits > 32)
+               DISSECTOR_ASSERT_NOT_REACHED();
+
+       if (no_of_bits == 0)
+               return 0;
+
+       /* Number of requested bits is in range [17, 32] */
+       if (no_of_bits > 16)
+               return tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
+
+       /* Number of requested bits is in range [9, 16] */
+       if (no_of_bits > 8)
+               return tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
+
+       /* Number of requested bits is in range [1, 8] */
+       return tvb_get_bits8(tvb, bit_offset, no_of_bits);
+}
+
 /* Find first occurence of needle in tvbuff, starting at offset. Searches
  * at most maxlength number of bytes; if maxlength is -1, searches to
  * end of tvbuff.
@@ -1722,7 +1798,9 @@ tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
        guint           tvbufflen;
        guint           limit;
 
-       check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+       check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
 
        /* Only search to end of tvbuff, w/o throwing exception. */
        tvbufflen = tvb_length_remaining(tvb, abs_offset);
@@ -1785,7 +1863,9 @@ tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, const guint8 *needle
        guint           tvbufflen;
        guint           limit;
 
-       check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+       check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
 
        /* Only search to end of tvbuff, w/o throwing exception. */
        tvbufflen = tvb_length_remaining(tvb, abs_offset);
@@ -1844,7 +1924,9 @@ tvb_strsize(tvbuff_t *tvb, gint offset)
        guint   abs_offset, junk_length;
        gint    nul_offset;
 
-       check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+       check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
        nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
        if (nul_offset == -1) {
                /*
@@ -1852,7 +1934,7 @@ tvb_strsize(tvbuff_t *tvb, gint offset)
                 * an exception.
                 *
                 * Did we hit the end of the captured data, or the end
-                * of the actual data?  If there's less captured data
+                * of the actual data?  If there's less captured data
                 * than actual data, we presumably hit the end of the
                 * captured data, otherwise we hit the end of the actual
                 * data.
@@ -1876,7 +1958,9 @@ tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
        gint    result_offset;
        guint   abs_offset, junk_length;
 
-       check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+       check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
 
        result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
 
@@ -1973,7 +2057,7 @@ tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, size_t size)
        }
 }
 
-/* Convert a string from Unicode to ASCII.  At the moment we fake it by
+/* Convert a string from Unicode to ASCII.     At the moment we fake it by
  * replacing all non-ASCII characters with a '.' )-:  The caller must
  * free the result returned.  The len parameter is the number of guint16's
  * to convert from Unicode. */
@@ -2004,7 +2088,7 @@ tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
        return buffer;
 }
 
-/* Convert a string from Unicode to ASCII.  At the moment we fake it by
+/* Convert a string from Unicode to ASCII.     At the moment we fake it by
  * replacing all non-ASCII characters with a '.' )-:   The len parameter is
  * the number of guint16's to convert from Unicode.
  *
@@ -2050,14 +2134,11 @@ tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
   gint len = size;
 
   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
-
     len = tvb_length_remaining(tvb, offset);
     ptr = ensure_contiguous(tvb, offset, len);
-
   }
 
   return format_text(ptr, len);
-
 }
 
 /*
@@ -2072,8 +2153,8 @@ tvb_format_text_wsp(tvbuff_t *tvb, gint offset, gint size)
 
   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
 
-    len = tvb_length_remaining(tvb, offset);
-    ptr = ensure_contiguous(tvb, offset, len);
+       len = tvb_length_remaining(tvb, offset);
+       ptr = ensure_contiguous(tvb, offset, len);
 
   }
 
@@ -2094,13 +2175,13 @@ tvb_format_stringzpad(tvbuff_t *tvb, gint offset, gint size)
 
   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
 
-    len = tvb_length_remaining(tvb, offset);
-    ptr = ensure_contiguous(tvb, offset, len);
+       len = tvb_length_remaining(tvb, offset);
+       ptr = ensure_contiguous(tvb, offset, len);
 
   }
 
   for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
-    ;
+       ;
   return format_text(ptr, stringlen);
 
 }
@@ -2118,13 +2199,13 @@ tvb_format_stringzpad_wsp(tvbuff_t *tvb, gint offset, gint size)
 
   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
 
-    len = tvb_length_remaining(tvb, offset);
-    ptr = ensure_contiguous(tvb, offset, len);
+       len = tvb_length_remaining(tvb, offset);
+       ptr = ensure_contiguous(tvb, offset, len);
 
   }
 
   for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
-    ;
+       ;
   return format_text_wsp(ptr, stringlen);
 
 }
@@ -2218,7 +2299,7 @@ tvb_get_seasonal_string(tvbuff_t *tvb, gint offset, gint length)
  * a null-terminated string, find the length of that string (and throw
  * an exception if the tvbuff ends before we find the null), allocate
  * a buffer big enough to hold the string, copy the string into it,
- * and return a pointer to the string.  Also return the length of the
+ * and return a pointer to the string. Also return the length of the
  * string (including the terminating null) through a pointer.
  */
 guint8 *
@@ -2230,7 +2311,8 @@ tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
        size = tvb_strsize(tvb, offset);
        strptr = g_malloc(size);
        tvb_memcpy(tvb, strptr, offset, size);
-       *lengthp = size;
+       if (lengthp)
+               *lengthp = size;
        return strptr;
 }
 /*
@@ -2238,7 +2320,7 @@ tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
  * a null-terminated string, find the length of that string (and throw
  * an exception if the tvbuff ends before we find the null), allocate
  * a buffer big enough to hold the string, copy the string into it,
- * and return a pointer to the string.  Also return the length of the
+ * and return a pointer to the string. Also return the length of the
  * string (including the terminating null) through a pointer.
  *
  * This function allocates memory from a buffer with packet lifetime.
@@ -2256,7 +2338,8 @@ tvb_get_ephemeral_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
        size = tvb_strsize(tvb, offset);
        strptr = ep_alloc(size);
        tvb_memcpy(tvb, strptr, offset, size);
-       *lengthp = size;
+       if (lengthp)
+               *lengthp = size;
        return strptr;
 }
 
@@ -2265,7 +2348,7 @@ tvb_get_ephemeral_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
  * a null-terminated string, find the length of that string (and throw
  * an exception if the tvbuff ends before we find the null), allocate
  * a buffer big enough to hold the string, copy the string into it,
- * and return a pointer to the string.  Also return the length of the
+ * and return a pointer to the string. Also return the length of the
  * string (including the terminating null) through a pointer.
  *
  * This function allocates memory from a buffer with capture session lifetime.
@@ -2281,7 +2364,8 @@ tvb_get_seasonal_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
        size = tvb_strsize(tvb, offset);
        strptr = se_alloc(size);
        tvb_memcpy(tvb, strptr, offset, size);
-       *lengthp = size;
+       if (lengthp)
+               *lengthp = size;
        return strptr;
 }
 
@@ -2312,7 +2396,7 @@ _tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
        gint    limit, len;
        gboolean decreased_max = FALSE;
 
-       check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
+       check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
 
        /* There must at least be room for the terminating NUL. */
        DISSECTOR_ASSERT(bufsize != 0);
@@ -2392,6 +2476,8 @@ tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
 {
        gint bytes_copied;
 
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
        return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
 }
 
@@ -2404,6 +2490,8 @@ tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
 {
        gint    len, bytes_copied;
 
+       DISSECTOR_ASSERT(tvb && tvb->initialized);
+
        len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
 
        if (len == -1) {
@@ -2432,11 +2520,11 @@ tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
  *
  * Set "*next_offset" to the offset of the character past the line
  * terminator, or past the end of the buffer if we don't find a line
- * terminator.  (It's not set if we return -1.)
+ * terminator. (It's not set if we return -1.)
  */
 gint
 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
-    gboolean desegment)
+       gboolean desegment)
 {
        gint eob_offset;
        gint eol_offset;
@@ -2470,7 +2558,8 @@ tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
                         * Pretend the line runs to the end of the tvbuff.
                         */
                        linelen = eob_offset - offset;
-                       *next_offset = eob_offset;
+                       if (next_offset)
+                               *next_offset = eob_offset;
                }
        } else {
                /*
@@ -2524,7 +2613,8 @@ tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
                 * character in the line, skipping over the last character
                 * in the line terminator.
                 */
-               *next_offset = eol_offset + 1;
+               if (next_offset)
+                       *next_offset = eol_offset + 1;
        }
        return linelen;
 }
@@ -2549,7 +2639,7 @@ tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
  */
 gint
 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
-    gint *next_offset)
+       gint *next_offset)
 {
        gint cur_offset, char_offset;
        gboolean is_quoted;
@@ -2568,7 +2658,7 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
        cur_offset = offset;
        is_quoted = FALSE;
        for (;;) {
-               /*
+                       /*
                 * Is this part of the string quoted?
                 */
                if (is_quoted) {
@@ -2576,13 +2666,13 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
                         * Yes - look only for the terminating quote.
                         */
                        char_offset = tvb_find_guint8(tvb, cur_offset, len,
-                           '"');
+                               '"');
                } else {
                        /*
                         * Look either for a CR, an LF, or a '"'.
                         */
                        char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
-                           (const guint8 *)"\r\n\"");
+                               (const guint8 *)"\r\n\"");
                }
                if (char_offset == -1) {
                        /*
@@ -2591,7 +2681,8 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
                         * We pretend the line runs to the end of the tvbuff.
                         */
                        linelen = eob_offset - offset;
-                       *next_offset = eob_offset;
+                       if (next_offset)
+                               *next_offset = eob_offset;
                        break;
                }
 
@@ -2632,8 +2723,8 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
                                         * Yes; is it followed by an LF?
                                         */
                                        if (char_offset + 1 < eob_offset &&
-                                           tvb_get_guint8(tvb, char_offset + 1)
-                                             == '\n') {
+                                               tvb_get_guint8(tvb, char_offset + 1)
+                                                 == '\n') {
                                                /*
                                                 * Yes; skip over the CR.
                                                 */
@@ -2647,7 +2738,8 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
                                 * over the last character in the line
                                 * terminator, and quit.
                                 */
-                               *next_offset = char_offset + 1;
+                               if (next_offset)
+                                       *next_offset = char_offset + 1;
                                break;
                        }
                }
@@ -2664,7 +2756,8 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
                         * We pretend the line runs to the end of the tvbuff.
                         */
                        linelen = eob_offset - offset;
-                       *next_offset = eob_offset;
+                       if (next_offset)
+                               *next_offset = eob_offset;
                        break;
                }
        }
@@ -2674,8 +2767,8 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
 /*
  * Copied from the mgcp dissector. (This function should be moved to /epan )
  * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
- *                character following offset or offset + maxlength -1 whichever
- *                is smaller.
+ *                               character following offset or offset + maxlength -1 whichever
+ *                               is smaller.
  *
  * Parameters:
  * tvb - The tvbuff in which we are skipping whitespace.
@@ -2684,8 +2777,8 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
  * whitespace.
  *
  * Returns: The position in tvb of the first non-whitespace
- *          character following offset or offset + maxlength -1 whichever
- *          is smaller.
+ *                     character following offset or offset + maxlength -1 whichever
+ *                     is smaller.
  */
 gint tvb_skip_wsp(tvbuff_t* tvb, gint offset, gint maxlength)
 {
@@ -2703,10 +2796,10 @@ gint tvb_skip_wsp(tvbuff_t* tvb, gint offset, gint maxlength)
 
        /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
        for (counter = offset;
-            counter < end &&
-             ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
-             tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
-            counter++);
+                counter < end &&
+                 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
+                 tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
+                counter++);
 
        return (counter);
 }
@@ -2756,6 +2849,8 @@ tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
        const guint     needle_len = needle_tvb->length;
        const guint8    *location;
 
+       DISSECTOR_ASSERT(haystack_tvb && haystack_tvb->initialized);
+
        if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
                return -1;
        }
@@ -2764,7 +2859,7 @@ tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
        haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
        needle_data = tvb_get_ptr(needle_tvb, 0, -1);
 
-       check_offset_length(haystack_tvb, haystack_offset, -1,
+       check_offset_length(haystack_tvb->length, haystack_tvb->reported_length, haystack_offset, -1,
                        &haystack_abs_offset, &haystack_abs_length);
 
        location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
@@ -2791,8 +2886,6 @@ tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
 tvbuff_t *
 tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
 {
-
-
        gint err = Z_OK;
        guint bytes_out = 0;
        guint8 *compr = NULL;
@@ -2813,30 +2906,17 @@ tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
                return NULL;
        }
 
-       strm = g_malloc0(sizeof(z_stream));
-
-       if (strm == NULL) {
-               return NULL;
-       }
-
        compr = tvb_memdup(tvb, offset, comprlen);
 
-       if (!compr) {
-               g_free(strm);
+       if (!compr)
                return NULL;
-       }
 
        /*
         * Assume that the uncompressed data is at least twice as big as
         * the compressed size.
         */
        bufsiz = tvb_length_remaining(tvb, offset) * 2;
-
-       if (bufsiz < TVB_Z_MIN_BUFSIZ) {
-               bufsiz = TVB_Z_MIN_BUFSIZ;
-       } else if (bufsiz > TVB_Z_MAX_BUFSIZ) {
-               bufsiz = TVB_Z_MIN_BUFSIZ;
-       }
+       bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
 
 #ifdef TVB_Z_DEBUG
        printf("bufsiz: %u bytes\n", bufsiz);
@@ -2844,18 +2924,11 @@ tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
 
        next = compr;
 
+       strm = g_new0(z_stream, 1);
        strm->next_in = next;
        strm->avail_in = comprlen;
 
-
        strmbuf = g_malloc0(bufsiz);
-
-       if(strmbuf == NULL) {
-               g_free(compr);
-               g_free(strm);
-               return NULL;
-       }
-
        strm->next_out = strmbuf;
        strm->avail_out = bufsiz;
 
@@ -2886,25 +2959,11 @@ tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
                        if (uncompr == NULL) {
                                uncompr = g_memdup(strmbuf, bytes_pass);
                        } else {
-                               guint8 *new_data = g_malloc0(bytes_out +
-                                   bytes_pass);
-
-                               if (new_data == NULL) {
-                                       inflateEnd(strm);
-                                       g_free(strm);
-                                       g_free(strmbuf);
-                                       g_free(compr);
-
-                                       if (uncompr != NULL) {
-                                               g_free(uncompr);
-                                       }
-
-                                       return NULL;
-                               }
+                               guint8 *new_data = g_malloc0(bytes_out + bytes_pass);
 
                                g_memmove(new_data, uncompr, bytes_out);
                                g_memmove((new_data + bytes_out), strmbuf,
-                                   bytes_pass);
+                                       bytes_pass);
 
                                g_free(uncompr);
                                uncompr = new_data;
@@ -2936,8 +2995,8 @@ tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
                        }
 
                } else if (err == Z_DATA_ERROR && inits_done == 1
-                   && uncompr == NULL && (*compr  == 0x1f) &&
-                   (*(compr + 1) == 0x8b)) {
+                       && uncompr == NULL && (*compr  == 0x1f) &&
+                       (*(compr + 1) == 0x8b)) {
                        /*
                         * inflate() is supposed to handle both gzip and deflate
                         * streams automatically, but in reality it doesn't
@@ -2973,7 +3032,7 @@ tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
                        if (flags & (1 << 2)) {
                                /* An Extra field is present. */
                                gint xsize = (gint)(*c |
-                                   (*(c + 1) << 8));
+                                       (*(c + 1) << 8));
 
                                c += xsize;
                        }
@@ -3015,7 +3074,7 @@ tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
                        err = inflateInit2(strm, wbits);
                        inits_done++;
                } else if (err == Z_DATA_ERROR && uncompr == NULL &&
-                   inits_done <= 3) {
+                       inits_done <= 3) {
 
                        /*
                         * Re-init the stream with a negative
@@ -3069,7 +3128,7 @@ tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
 
        if (uncompr != NULL) {
                uncompr_tvb =  tvb_new_real_data((guint8*) uncompr, bytes_out,
-                   bytes_out);
+                       bytes_out);
                tvb_set_free_cb(uncompr_tvb, g_free);
        }
        g_free(compr);
@@ -3091,4 +3150,3 @@ tvbuff_t* tvb_child_uncompress(tvbuff_t *parent _U_, tvbuff_t *tvb, int offset,
        return new_tvb;
 }
 
-