MAX_MCS_INDEX is a valid array index.
[metze/wireshark/wip.git] / epan / tvbuff.c
index f087480509ef2f2dad146f223958c47b64f64a32..12378e644139135f1353a2fed555990465614c2d 100644 (file)
@@ -44,7 +44,6 @@
 #include "wsutil/unicode-utils.h"
 #include "wsutil/nstime.h"
 #include "wsutil/time_util.h"
-#include "wsutil/ws_mempbrk.h"
 #include "tvbuff.h"
 #include "tvbuff-int.h"
 #include "strutil.h"
@@ -342,7 +341,7 @@ tvb_new_octet_aligned(tvbuff_t *tvb, guint32 bit_offset, gint32 no_of_bits)
 
        /* already aligned -> shortcut */
        if ((left == 0) && (remaining_bits == 0)) {
-               return tvb_new_subset(tvb, byte_offset, datalen, -1);
+               return tvb_new_subset(tvb, byte_offset, datalen, datalen);
        }
 
        DISSECTOR_ASSERT(datalen>0);
@@ -384,8 +383,11 @@ static tvbuff_t *
 tvb_generic_clone_offset_len(tvbuff_t *tvb, guint offset, guint len)
 {
        tvbuff_t *cloned_tvb;
+       guint8 *data;
 
-       guint8 *data = (guint8 *) g_malloc(len);
+       DISSECTOR_ASSERT(tvb_bytes_exist(tvb, offset, len));
+
+       data = (guint8 *) g_malloc(len);
 
        tvb_memcpy(tvb, data, offset, len);
 
@@ -455,7 +457,7 @@ tvb_captured_length_remaining(const tvbuff_t *tvb, const gint offset)
 guint
 tvb_ensure_captured_length_remaining(const tvbuff_t *tvb, const gint offset)
 {
-       guint abs_offset, rem_length;
+       guint abs_offset = 0, rem_length = 0;
        int   exception;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
@@ -680,7 +682,7 @@ tvb_offset_from_real_beginning(const tvbuff_t *tvb)
 static inline const guint8*
 ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint length, int *pexception)
 {
-       guint abs_offset, abs_length;
+       guint abs_offset = 0, abs_length = 0;
        int   exception;
 
        exception = check_offset_length_no_exception(tvb, offset, length, &abs_offset, &abs_length);
@@ -752,17 +754,6 @@ fast_ensure_contiguous(tvbuff_t *tvb, const gint offset, const guint length)
        return NULL;
 }
 
-static inline const guint8*
-guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles, guchar *found_needle)
-{
-       const guint8 *result = ws_mempbrk(haystack, haystacklen, needles);
-
-       if (result && found_needle)
-               *found_needle = *result;
-
-       return result;
-}
-
 
 
 /************** ACCESSORS **************/
@@ -770,7 +761,7 @@ guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles, g
 void *
 tvb_memcpy(tvbuff_t *tvb, void *target, const gint offset, size_t length)
 {
-       guint   abs_offset, abs_length;
+       guint   abs_offset = 0, abs_length = 0;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
@@ -795,9 +786,17 @@ tvb_memcpy(tvbuff_t *tvb, void *target, const gint offset, size_t length)
        if (tvb->ops->tvb_memcpy)
                return tvb->ops->tvb_memcpy(tvb, target, abs_offset, abs_length);
 
-       /* XXX, fallback to slower method */
-
-       DISSECTOR_ASSERT_NOT_REACHED();
+       /*
+        * If the length is 0, there's nothing to do.
+        * (tvb->real_data could be null if it's allocated with
+        * a size of length.)
+        */
+       if (length != 0) {
+               /*
+                * XXX, fallback to slower method
+                */
+               DISSECTOR_ASSERT_NOT_REACHED();
+       }
        return NULL;
 }
 
@@ -820,7 +819,7 @@ tvb_memcpy(tvbuff_t *tvb, void *target, const gint offset, size_t length)
 void *
 tvb_memdup(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, size_t length)
 {
-       guint  abs_offset, abs_length;
+       guint  abs_offset = 0, abs_length = 0;
        void  *duped;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
@@ -942,6 +941,114 @@ tvb_get_ntoh64(tvbuff_t *tvb, const gint offset)
        return pntoh64(ptr);
 }
 
+guint16
+tvb_get_guint16(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letohs(tvb, offset);
+       } else {
+               return tvb_get_ntohs(tvb, offset);
+       }
+}
+
+guint32
+tvb_get_guint24(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letoh24(tvb, offset);
+       } else {
+               return tvb_get_ntoh24(tvb, offset);
+       }
+}
+
+guint32
+tvb_get_guint32(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letohl(tvb, offset);
+       } else {
+               return tvb_get_ntohl(tvb, offset);
+       }
+}
+
+guint64
+tvb_get_guint40(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letoh40(tvb, offset);
+       } else {
+               return tvb_get_ntoh40(tvb, offset);
+       }
+}
+
+gint64
+tvb_get_gint40(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letohi40(tvb, offset);
+       } else {
+               return tvb_get_ntohi40(tvb, offset);
+       }
+}
+
+guint64
+tvb_get_guint48(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letoh48(tvb, offset);
+       } else {
+               return tvb_get_ntoh48(tvb, offset);
+       }
+}
+
+gint64
+tvb_get_gint48(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letohi48(tvb, offset);
+       } else {
+               return tvb_get_ntohi48(tvb, offset);
+       }
+}
+
+guint64
+tvb_get_guint56(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letoh56(tvb, offset);
+       } else {
+               return tvb_get_ntoh56(tvb, offset);
+       }
+}
+
+gint64
+tvb_get_gint56(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letohi56(tvb, offset);
+       } else {
+               return tvb_get_ntohi56(tvb, offset);
+       }
+}
+
+guint64
+tvb_get_guint64(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letoh64(tvb, offset);
+       } else {
+               return tvb_get_ntoh64(tvb, offset);
+       }
+}
+
+gfloat
+tvb_get_ieee_float(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letohieee_float(tvb, offset);
+       } else {
+               return tvb_get_ntohieee_float(tvb, offset);
+       }
+}
+
+gdouble
+tvb_get_ieee_double(tvbuff_t *tvb, const gint offset, const guint encoding) {
+       if (encoding & ENC_LITTLE_ENDIAN) {
+               return tvb_get_letohieee_double(tvb, offset);
+       } else {
+               return tvb_get_ntohieee_double(tvb, offset);
+       }
+}
+
 /*
  * Stuff for IEEE float handling on platforms that don't have IEEE
  * format as the native floating-point format.
@@ -1585,12 +1692,12 @@ tvb_get_letohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid)
  * NOTE: to support code written when proto_tree_add_item() took a
  * gboolean as its last argument, with FALSE meaning "big-endian"
  * and TRUE meaning "little-endian", we treat any non-zero value of
- * "representation" as meaning "little-endian".
+ * "encoding" as meaning "little-endian".
  */
 void
-tvb_get_guid(tvbuff_t *tvb, const gint offset, e_guid_t *guid, const guint representation)
+tvb_get_guid(tvbuff_t *tvb, const gint offset, e_guid_t *guid, const guint encoding)
 {
-       if (representation) {
+       if (encoding) {
                tvb_get_letohguid(tvb, offset, guid);
        } else {
                tvb_get_ntohguid(tvb, offset, guid);
@@ -1752,8 +1859,8 @@ gint
 tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 needle)
 {
        const guint8 *result;
-       guint         abs_offset;
-       guint         limit;
+       guint         abs_offset = 0;
+       guint         limit = 0;
        int           exception;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
@@ -1787,21 +1894,22 @@ tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu
 }
 
 static inline gint
-tvb_pbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
+tvb_ws_mempbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
 {
        const guint8 *ptr;
        const guint8 *result;
 
        ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr */
 
-       result = guint8_pbrk(ptr, limit, needles, found_needle);
+       result = ws_mempbrk_exec(ptr, limit, pattern, found_needle);
        if (!result)
                return -1;
 
        return (gint) ((result - ptr) + abs_offset);
 }
 
-/* Find first occurrence of any of the needles in tvbuff, starting at offset.
+
+/* Find first occurrence of any of the pattern chars in tvbuff, starting at offset.
  * Searches at most maxlength number of bytes; if maxlength is -1, searches
  * to end of tvbuff.
  * Returns the offset of the found needle, or -1 if not found.
@@ -1809,11 +1917,12 @@ tvb_pbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const guin
  * in that case, -1 will be returned if the boundary is reached before
  * finding needle. */
 gint
-tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 *needles, guchar *found_needle)
+tvb_ws_mempbrk_pattern_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength,
+                       const ws_mempbrk_pattern* pattern, guchar *found_needle)
 {
        const guint8 *result;
-       guint         abs_offset;
-       guint         limit;
+       guint         abs_offset = 0;
+       guint         limit = 0;
        int           exception;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
@@ -1831,7 +1940,7 @@ tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu
 
        /* If we have real data, perform our search now. */
        if (tvb->real_data) {
-               result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles, found_needle);
+               result = ws_mempbrk_exec(tvb->real_data + abs_offset, limit, pattern, found_needle);
                if (result == NULL) {
                        return -1;
                }
@@ -1840,10 +1949,10 @@ tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu
                }
        }
 
-       if (tvb->ops->tvb_pbrk_guint8)
-               return tvb->ops->tvb_pbrk_guint8(tvb, abs_offset, limit, needles, found_needle);
+       if (tvb->ops->tvb_ws_mempbrk_pattern_guint8)
+               return tvb->ops->tvb_ws_mempbrk_pattern_guint8(tvb, abs_offset, limit, pattern, found_needle);
 
-       return tvb_pbrk_guint8_generic(tvb, abs_offset, limit, needles, found_needle);
+       return tvb_ws_mempbrk_guint8_generic(tvb, abs_offset, limit, pattern, found_needle);
 }
 
 /* Find size of stringz (NUL-terminated string) by looking for terminating
@@ -1854,7 +1963,7 @@ tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu
 guint
 tvb_strsize(tvbuff_t *tvb, const gint offset)
 {
-       guint abs_offset, junk_length;
+       guint abs_offset = 0, junk_length;
        gint  nul_offset;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
@@ -1912,7 +2021,7 @@ gint
 tvb_strnlen(tvbuff_t *tvb, const gint offset, const guint maxlength)
 {
        gint  result_offset;
-       guint abs_offset, junk_length;
+       guint abs_offset = 0, junk_length;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
@@ -2820,8 +2929,8 @@ static gint
 _tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer, gint *bytes_copied)
 {
        gint     stringlen;
-       guint    abs_offset;
-       gint     limit, len;
+       guint    abs_offset = 0;
+       gint     limit, len = 0;
        gboolean decreased_max = FALSE;
 
        /* Only read to end of tvbuff, w/o throwing exception. */
@@ -2929,6 +3038,8 @@ tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8*
        }
 }
 
+
+static ws_mempbrk_pattern pbrk_crlf;
 /*
  * Given a tvbuff, an offset into the tvbuff, and a length that starts
  * at that offset (which may be -1 for "all the way to the end of the
@@ -2951,16 +3062,11 @@ tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8*
 gint
 tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset, const gboolean desegment)
 {
-#ifdef WIN32
-       static const char __declspec(align(16)) crlf[] = "\r\n" ;
-#else
-       static const char crlf[] __attribute__((aligned(16))) = "\r\n" ;
-#endif
-
        gint   eob_offset;
        gint   eol_offset;
        int    linelen;
        guchar found_needle = 0;
+       static gboolean compiled = FALSE;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
@@ -2972,10 +3078,15 @@ tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset,
         */
        eob_offset = offset + len;
 
+       if (!compiled) {
+               ws_mempbrk_compile(&pbrk_crlf, "\r\n");
+               compiled = TRUE;
+       }
+
        /*
         * Look either for a CR or an LF.
         */
-       eol_offset = tvb_pbrk_guint8(tvb, offset, len, crlf, &found_needle);
+       eol_offset = tvb_ws_mempbrk_pattern_guint8(tvb, offset, len, &pbrk_crlf, &found_needle);
        if (eol_offset == -1) {
                /*
                 * No CR or LF - line is presumably continued in next packet.
@@ -3053,6 +3164,7 @@ tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset,
        return linelen;
 }
 
+static ws_mempbrk_pattern pbrk_crlf_dquote;
 /*
  * Given a tvbuff, an offset into the tvbuff, and a length that starts
  * at that offset (which may be -1 for "all the way to the end of the
@@ -3079,11 +3191,18 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, const gint offset, int len, gint *next
        guchar   c = 0;
        gint     eob_offset;
        int      linelen;
+       static gboolean compiled = FALSE;
 
        DISSECTOR_ASSERT(tvb && tvb->initialized);
 
        if (len == -1)
                len = _tvb_captured_length_remaining(tvb, offset);
+
+       if (!compiled) {
+               ws_mempbrk_compile(&pbrk_crlf_dquote, "\r\n\"");
+               compiled = TRUE;
+       }
+
        /*
         * XXX - what if "len" is still -1, meaning "offset is past the
         * end of the tvbuff"?
@@ -3106,7 +3225,7 @@ tvb_find_line_end_unquoted(tvbuff_t *tvb, const gint offset, int len, gint *next
                        /*
                         * Look either for a CR, an LF, or a '"'.
                         */
-                       char_offset = tvb_pbrk_guint8(tvb, cur_offset, len, "\r\n\"", &c);
+                       char_offset = tvb_ws_mempbrk_pattern_guint8(tvb, cur_offset, len, &pbrk_crlf_dquote, &c);
                }
                if (char_offset == -1) {
                        /*
@@ -3286,9 +3405,9 @@ tvb_skip_guint8(tvbuff_t *tvb, int offset, const int maxlength, const guint8 ch)
  * separator.
  */
 gchar *
-tvb_bytes_to_ep_str_punct(tvbuff_t *tvb, const gint offset, const gint len, const gchar punct)
+tvb_bytes_to_str_punct(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint len, const gchar punct)
 {
-       return bytes_to_ep_str_punct(ensure_contiguous(tvb, offset, len), len, punct);
+       return bytestring_to_str(scope, ensure_contiguous(tvb, offset, len), len, punct);
 }
 
 
@@ -3346,8 +3465,15 @@ tvb_bcd_dig_to_wmem_packet_str(tvbuff_t *tvb, const gint offset, const gint len,
                 */
                octet = octet >> 4;
 
-               if (octet == 0x0f)      /* odd number bytes - hit filler */
+               if (t_offset == length - 1 && octet == 0x0f) {
+                       /*
+                        * This is the last octet, and the low-order
+                        * nibble is 0xf, so we have an odd number of
+                        * digits, and this is a filler digit.  Ignore
+                        * it.
+                        */
                        break;
+               }
 
                digit_str[i] = dgt->out[octet & 0x0f];
                i++;
@@ -3363,17 +3489,17 @@ tvb_bcd_dig_to_wmem_packet_str(tvbuff_t *tvb, const gint offset, const gint len,
  * Format a bunch of data from a tvbuff as bytes, returning a pointer
  * to the string with the formatted data.
  */
-gchar *
-tvb_bytes_to_ep_str(tvbuff_t *tvb, const gint offset, const gint len)
+gchar *tvb_bytes_to_str(wmem_allocator_t *allocator, tvbuff_t *tvb,
+    const gint offset, const gint len)
 {
-       return bytes_to_ep_str(ensure_contiguous(tvb, offset, len), len);
+       return bytes_to_str(allocator, ensure_contiguous(tvb, offset, len), len);
 }
 
 /* Find a needle tvbuff within a haystack tvbuff. */
 gint
 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const gint haystack_offset)
 {
-       guint         haystack_abs_offset, haystack_abs_length;
+       guint         haystack_abs_offset = 0, haystack_abs_length = 0;
        const guint8 *haystack_data;
        const guint8 *needle_data;
        const guint   needle_len = needle_tvb->length;