* the data of a backing tvbuff, or can be a composite of
* other tvbuffs.
*
- * $Id$
- *
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
*
* Code to convert IEEE floating point formats to native floating point
#include "config.h"
#include <string.h>
+#include <stdio.h>
+#include <errno.h>
#include "wsutil/pint.h"
#include "wsutil/sign_ext.h"
+#include "wsutil/unicode-utils.h"
+#include "wsutil/nstime.h"
+#include "wsutil/time_util.h"
#include "tvbuff.h"
#include "tvbuff-int.h"
#include "strutil.h"
#include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
#include "exceptions.h"
+/*
+ * Just make sure we include the prototype for strptime as well
+ * (needed for glibc 2.2) but make sure we do this only if not
+ * yet defined.
+ */
+#include <time.h>
+/*#ifndef HAVE_STRPTIME*/
+#ifndef strptime
+#include "wsutil/strptime.h"
+#endif
+ /*#endif*/
+
static guint64
_tvb_get_bits64(tvbuff_t *tvb, guint bit_offset, const gint total_no_of_bits);
+static inline gint
+_tvb_captured_length_remaining(const tvbuff_t *tvb, const gint offset);
+
+static inline const guint8*
+ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length);
+
+static inline guint8 *
+tvb_get_raw_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length);
+
tvbuff_t *
tvb_new(const struct tvb_ops *ops)
{
tvbuff_t *next_tvb;
DISSECTOR_ASSERT(tvb);
while (tvb) {
- next_tvb=tvb->next;
+ next_tvb = tvb->next;
tvb_free_internal(tvb);
tvb = next_tvb;
}
tmp->next = parent->next;
parent->next = tmp;
- }
+ }
}
/*
return ReportedBoundsError;
}
-static int
+static inline int
compute_offset(const tvbuff_t *tvb, const gint offset, guint *offset_ptr)
{
if (offset >= 0) {
return 0;
}
-static int
+static inline int
compute_offset_and_remaining(const tvbuff_t *tvb, const gint offset, guint *offset_ptr, guint *rem_len)
{
int exception;
* left for the next protocol - we want the next protocol to be the one
* that gets an exception, so the error is reported as an error in that
* protocol rather than the containing protocol. */
-static int
+static inline int
check_offset_length_no_exception(const tvbuff_t *tvb,
const gint offset, gint const length_val,
guint *offset_ptr, guint *length_ptr)
{
guint end_offset;
- int exception;
+ int exception;
DISSECTOR_ASSERT(offset_ptr);
DISSECTOR_ASSERT(length_ptr);
/* Checks (+/-) offset and length and throws an exception if
* either is out of bounds. Sets integer ptrs to the new offset
* and length. */
-static void
+static inline void
check_offset_length(const tvbuff_t *tvb,
const gint offset, gint const length_val,
guint *offset_ptr, guint *length_ptr)
guint8 left, right, remaining_bits, *buf;
const guint8 *data;
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
byte_offset = bit_offset >> 3;
left = bit_offset % 8; /* for left-shifting */
right = 8 - left; /* for right-shifting */
if (no_of_bits == -1) {
- datalen = tvb_length_remaining(tvb, byte_offset);
+ datalen = _tvb_captured_length_remaining(tvb, byte_offset);
remaining_bits = 0;
} else {
datalen = no_of_bits >> 3;
/* 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);
/* if at least one trailing byte is available, we must use the content
- * of that byte for the last shift (i.e. tvb_get_ptr() must use datalen + 1
- * if non extra byte is available, the last shifted byte requires
- * special treatment
- */
- if (tvb_length_remaining(tvb, byte_offset) > datalen) {
- data = tvb_get_ptr(tvb, byte_offset, datalen + 1);
+ * of that byte for the last shift (i.e. tvb_get_ptr() must use datalen + 1
+ * if non extra byte is available, the last shifted byte requires
+ * special treatment
+ */
+ if (_tvb_captured_length_remaining(tvb, byte_offset) > datalen) {
+ data = ensure_contiguous(tvb, byte_offset, datalen + 1); /* tvb_get_ptr */
/* Do this allocation AFTER tvb_get_ptr() (which could throw an exception) */
buf = (guint8 *)g_malloc(datalen);
for (i = 0; i < datalen; i++)
buf[i] = (data[i] << left) | (data[i+1] >> right);
} else {
- data = tvb_get_ptr(tvb, byte_offset, datalen);
+ data = ensure_contiguous(tvb, byte_offset, datalen); /* tvb_get_ptr() */
/* Do this allocation AFTER tvb_get_ptr() (which could throw an exception) */
buf = (guint8 *)g_malloc(datalen);
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);
}
guint
-tvb_length(const tvbuff_t *tvb)
+tvb_captured_length(const tvbuff_t *tvb)
{
DISSECTOR_ASSERT(tvb && tvb->initialized);
return tvb->length;
}
+/* For tvbuff internal use */
+static inline gint
+_tvb_captured_length_remaining(const tvbuff_t *tvb, const gint offset)
+{
+ guint abs_offset, rem_length;
+ int exception;
+
+ exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &rem_length);
+ if (exception)
+ return 0;
+
+ return rem_length;
+}
+
gint
-tvb_length_remaining(const tvbuff_t *tvb, const gint offset)
+tvb_captured_length_remaining(const tvbuff_t *tvb, const gint offset)
{
guint abs_offset, rem_length;
- int exception;
+ int exception;
DISSECTOR_ASSERT(tvb && tvb->initialized);
}
guint
-tvb_ensure_length_remaining(const tvbuff_t *tvb, const gint offset)
+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);
tvb_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
{
guint abs_offset, abs_length;
- int exception;
+ int exception;
DISSECTOR_ASSERT(tvb && tvb->initialized);
return TRUE;
}
+/* Validates that 'length' bytes, where 'length' is a 64-bit unsigned
+ * integer, are available starting from offset (pos/neg). Throws an
+ * exception if they aren't. */
+void
+tvb_ensure_bytes_exist64(const tvbuff_t *tvb, const gint offset, const guint64 length)
+{
+ /*
+ * Make sure the value fits in a signed integer; if not, assume
+ * that means that it's too big.
+ */
+ if (length > G_MAXINT) {
+ THROW(ReportedBoundsError);
+ }
+
+ /* OK, now cast it and try it with tvb_ensure_bytes_exist(). */
+ tvb_ensure_bytes_exist(tvb, offset, (gint)length);
+}
+
/* Validates that 'length' bytes are available starting from
* offset (pos/neg). Throws an exception if they aren't. */
void
tvb_offset_exists(const tvbuff_t *tvb, const gint offset)
{
guint abs_offset;
- int exception;
+ int exception;
DISSECTOR_ASSERT(tvb && tvb->initialized);
tvb_reported_length_remaining(const tvbuff_t *tvb, const gint offset)
{
guint abs_offset;
- int exception;
+ int exception;
DISSECTOR_ASSERT(tvb && tvb->initialized);
return tvb_offset_from_real_beginning_counter(tvb, 0);
}
-static const guint8*
+static inline const guint8*
ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint length, int *pexception)
{
- guint abs_offset, abs_length;
- int exception;
+ guint abs_offset = 0, abs_length = 0;
+ int exception;
exception = check_offset_length_no_exception(tvb, offset, length, &abs_offset, &abs_length);
if (exception) {
return NULL;
}
-static const guint8*
+static inline const guint8*
ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length)
{
int exception = 0;
return p;
}
-static const guint8*
+static inline const guint8*
fast_ensure_contiguous(tvbuff_t *tvb, const gint offset, const guint length)
{
guint end_offset;
return NULL;
}
-static const guint8*
-guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles, guchar *found_needle)
-{
- gchar tmp[256] = { 0 };
- const guint8 *haystack_end;
-
- while (*needles)
- tmp[*needles++] = 1;
-
- haystack_end = haystack + haystacklen;
- while (haystack < haystack_end) {
- if (tmp[*haystack]) {
- if (found_needle)
- *found_needle = *haystack;
- return haystack;
- }
- haystack++;
- }
-
- return NULL;
-}
-
/************** ACCESSORS **************/
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);
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;
}
* meaning "to the end of the buffer"?
*
* If scope is NULL, memory is allocated with g_malloc() and user must
- * explicitely free it with g_free().
+ * explicitly free it with g_free().
* If scope is not NULL, memory is allocated with the corresponding pool
* lifetime.
*/
void *
tvb_memdup(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, size_t length)
{
- guint abs_offset, abs_length;
- void *duped;
+ guint abs_offset = 0, abs_length = 0;
+ void *duped;
DISSECTOR_ASSERT(tvb && tvb->initialized);
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.
#define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
#define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
-#define IEEE_DP_SIGN_MASK 0x8000000000000000LL
-#define IEEE_DP_EXPONENT_MASK 0x7FF0000000000000LL
-#define IEEE_DP_MANTISSA_MASK 0x000FFFFFFFFFFFFFLL
+#define IEEE_DP_SIGN_MASK G_GINT64_CONSTANT(0x8000000000000000)
+#define IEEE_DP_EXPONENT_MASK G_GINT64_CONSTANT(0x7FF0000000000000)
+#define IEEE_DP_MANTISSA_MASK G_GINT64_CONSTANT(0x000FFFFFFFFFFFFF)
#define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
-#define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
+#define IEEE_DP_IMPLIED_BIT (G_GINT64_CONSTANT(1) << IEEE_DP_MANTISSA_WIDTH)
#define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
#define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
return get_ieee_float(tvb_get_ntohl(tvb, offset));
#else
union {
- gfloat f;
+ gfloat f;
guint32 w;
} ieee_fp_union;
#endif
}
+static inline void
+validate_single_byte_ascii_encoding(const guint encoding)
+{
+ const guint enc = encoding & ~ENC_STR_MASK;
+
+ switch (enc) {
+ case ENC_UTF_16:
+ case ENC_UCS_2:
+ case ENC_UCS_4:
+ case ENC_3GPP_TS_23_038_7BITS:
+ case ENC_EBCDIC:
+ REPORT_DISSECTOR_BUG("Invalid string encoding type passed to tvb_get_string_XXX");
+ break;
+ default:
+ break;
+ }
+ /* make sure something valid was set */
+ if (enc == 0)
+ REPORT_DISSECTOR_BUG("No string encoding type passed to tvb_get_string_XXX");
+}
+
+GByteArray*
+tvb_get_string_bytes(tvbuff_t *tvb, const gint offset, const gint length,
+ const guint encoding, GByteArray *bytes, gint *endoff)
+{
+ const gchar *ptr = (gchar*) tvb_get_raw_string(wmem_packet_scope(), tvb, offset, length);
+ const gchar *begin = ptr;
+ const gchar *end = NULL;
+ GByteArray *retval = NULL;
+
+ errno = EDOM;
+
+ validate_single_byte_ascii_encoding(encoding);
+
+ if (endoff) *endoff = 0;
+
+ while (*begin == ' ') begin++;
+
+ if (*begin && bytes) {
+ if (hex_str_to_bytes_encoding(begin, bytes, &end, encoding, FALSE)) {
+ if (bytes->len > 0) {
+ if (endoff) *endoff = offset + (gint)(end - ptr);
+ errno = 0;
+ retval = bytes;
+ }
+ }
+ }
+
+ return retval;
+}
+
+/* support hex-encoded time values? */
+nstime_t*
+tvb_get_string_time(tvbuff_t *tvb, const gint offset, const gint length,
+ const guint encoding, nstime_t *ns, gint *endoff)
+{
+ const gchar *begin = (gchar*) tvb_get_raw_string(wmem_packet_scope(), tvb, offset, length);
+ const gchar *ptr = begin;
+ const gchar *end = NULL;
+ struct tm tm;
+ nstime_t* retval = NULL;
+ char sign = '+';
+ int off_hr = 0;
+ int off_min = 0;
+ int num_chars = 0;
+ gboolean matched = FALSE;
+
+ errno = EDOM;
+
+ validate_single_byte_ascii_encoding(encoding);
+
+ DISSECTOR_ASSERT(ns);
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_isdst = -1;
+ ns->secs = 0;
+ ns->nsecs = 0;
+
+ while (*ptr == ' ') ptr++;
+
+ if (*ptr) {
+ /* note: sscanf is known to be inconsistent across platforms with respect
+ to whether a %n is counted as a return value or not, so we have to use
+ '>=' a lot */
+ if ((encoding & ENC_ISO_8601_DATE_TIME) == ENC_ISO_8601_DATE_TIME) {
+ /* TODO: using sscanf this many times is probably slow; might want
+ to parse it by hand in the future */
+ /* 2014-04-07T05:41:56+00:00 */
+ if (sscanf(ptr, "%d-%d-%d%*c%d:%d:%d%c%d:%d%n",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &tm.tm_sec,
+ &sign,
+ &off_hr,
+ &off_min,
+ &num_chars) >= 9)
+ {
+ matched = TRUE;
+ }
+ /* no seconds is ok */
+ else if (sscanf(ptr, "%d-%d-%d%*c%d:%d%c%d:%d%n",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &sign,
+ &off_hr,
+ &off_min,
+ &num_chars) >= 8)
+ {
+ matched = TRUE;
+ }
+ /* 2007-04-05T14:30:56Z */
+ else if (sscanf(ptr, "%d-%d-%d%*c%d:%d:%dZ%n",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &tm.tm_sec,
+ &num_chars) >= 6)
+ {
+ matched = TRUE;
+ off_hr = 0;
+ off_min = 0;
+ }
+ /* 2007-04-05T14:30Z no seconds is ok */
+ else if (sscanf(ptr, "%d-%d-%d%*c%d:%dZ%n",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &tm.tm_hour,
+ &tm.tm_min,
+ &num_chars) >= 5)
+ {
+ matched = TRUE;
+ off_hr = 0;
+ off_min = 0;
+ }
+
+ if (matched) {
+ errno = 0;
+ end = ptr + num_chars;
+ tm.tm_mon--;
+ if (tm.tm_year > 1900) tm.tm_year -= 1900;
+ if (sign == '-') off_hr = -off_hr;
+ }
+ }
+ else if (encoding & ENC_ISO_8601_DATE) {
+ /* 2014-04-07 */
+ if (sscanf(ptr, "%d-%d-%d%n",
+ &tm.tm_year,
+ &tm.tm_mon,
+ &tm.tm_mday,
+ &num_chars) >= 3)
+ {
+ errno = 0;
+ end = ptr + num_chars;
+ tm.tm_mon--;
+ if (tm.tm_year > 1900) tm.tm_year -= 1900;
+ }
+ }
+ else if (encoding & ENC_ISO_8601_TIME) {
+ /* 2014-04-07 */
+ if (sscanf(ptr, "%d:%d:%d%n",
+ &tm.tm_hour,
+ &tm.tm_min,
+ &tm.tm_sec,
+ &num_chars) >= 2)
+ {
+ /* what should we do about day/month/year? */
+ /* setting it to "now" for now */
+ time_t time_now = time(NULL);
+ struct tm *tm_now = gmtime(&time_now);
+ tm.tm_year = tm_now->tm_year;
+ tm.tm_mon = tm_now->tm_mon;
+ tm.tm_mday = tm_now->tm_mday;
+ end = ptr + num_chars;
+ errno = 0;
+
+ }
+ }
+ else if (encoding & ENC_RFC_822 || encoding & ENC_RFC_1123) {
+ if (encoding & ENC_RFC_822) {
+ /* this will unfortunately match ENC_RFC_1123 style
+ strings too, partially - probably need to do this the long way */
+ end = strptime(ptr, "%a, %d %b %y %H:%M:%S", &tm);
+ if (!end) end = strptime(ptr, "%a, %d %b %y %H:%M", &tm);
+ if (!end) end = strptime(ptr, "%d %b %y %H:%M:%S", &tm);
+ if (!end) end = strptime(ptr, "%d %b %y %H:%M", &tm);
+ }
+ else if (encoding & ENC_RFC_1123) {
+ end = strptime(ptr, "%a, %d %b %Y %H:%M:%S", &tm);
+ if (!end) end = strptime(ptr, "%a, %d %b %Y %H:%M", &tm);
+ if (!end) end = strptime(ptr, "%d %b %Y %H:%M:%S", &tm);
+ if (!end) end = strptime(ptr, "%d %b %Y %H:%M", &tm);
+ }
+ if (end) {
+ errno = 0;
+ if (*end == ' ') end++;
+ if (g_ascii_strncasecmp(end, "UT", 2) == 0)
+ {
+ end += 2;
+ }
+ else if (g_ascii_strncasecmp(end, "GMT", 3) == 0)
+ {
+ end += 3;
+ }
+ else if (sscanf(end, "%c%2d%2d%n",
+ &sign,
+ &off_hr,
+ &off_min,
+ &num_chars) < 3)
+ {
+ errno = ERANGE;
+ }
+ if (sign == '-') off_hr = -off_hr;
+ }
+ }
+ }
+
+ if (errno == 0) {
+ ns->secs = mktime_utc (&tm);
+ if (off_hr > 0)
+ ns->secs += (off_hr * 3600) + (off_min * 60);
+ else if (off_hr < 0)
+ ns->secs -= ((-off_hr) * 3600) + (off_min * 60);
+ retval = ns;
+ if (endoff)
+ *endoff = (gint)(offset + (end - begin));
+ }
+
+ return retval;
+}
+
/* Fetch an IPv4 address, in network byte order.
* We do *not* convert them to host byte order; we leave them in
* network byte order. */
* 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);
_tvb_get_bits64(tvbuff_t *tvb, guint bit_offset, const gint total_no_of_bits)
{
guint64 value;
- guint octet_offset = bit_offset >> 3;
- guint8 required_bits_in_first_octet = 8 - (bit_offset % 8);
+ guint octet_offset = bit_offset >> 3;
+ guint8 required_bits_in_first_octet = 8 - (bit_offset % 8);
if(required_bits_in_first_octet > total_no_of_bits)
{
const guint8 *ptr;
const guint8 *result;
- ptr = tvb_get_ptr(tvb, abs_offset, limit);
+ ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr() */
result = (const guint8 *) memchr(ptr, needle, limit);
if (!result)
tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 needle)
{
const guint8 *result;
- guint abs_offset;
- guint tvbufflen;
- guint limit;
+ guint abs_offset = 0;
+ guint limit = 0;
+ int exception;
DISSECTOR_ASSERT(tvb && tvb->initialized);
- check_offset_length(tvb, offset, -1, &abs_offset, &tvbufflen);
+ exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
+ if (exception)
+ THROW(exception);
/* Only search to end of tvbuff, w/o throwing exception. */
- if (maxlength == -1) {
- /* No maximum length specified; search to end of tvbuff. */
- limit = tvbufflen;
- }
- else if (tvbufflen < (guint) maxlength) {
- /* Maximum length goes past end of tvbuff; search to end
- of tvbuff. */
- limit = tvbufflen;
- }
- else {
+ if (limit > (guint) maxlength) {
/* Maximum length doesn't go past end of tvbuff; search
to that value. */
limit = maxlength;
return tvb_find_guint8_generic(tvb, offset, limit, needle);
}
-static gint
-tvb_pbrk_guint8_generic(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
+static inline gint
+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 = tvb_get_ptr(tvb, abs_offset, limit);
+ 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.
* 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 tvbufflen;
- guint limit;
+ guint abs_offset = 0;
+ guint limit = 0;
+ int exception;
DISSECTOR_ASSERT(tvb && tvb->initialized);
- check_offset_length(tvb, offset, -1, &abs_offset, &tvbufflen);
+ exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
+ if (exception)
+ THROW(exception);
/* Only search to end of tvbuff, w/o throwing exception. */
- if (maxlength == -1) {
- /* No maximum length specified; search to end of tvbuff. */
- limit = tvbufflen;
- }
- else if (tvbufflen < (guint) maxlength) {
- /* Maximum length goes past end of tvbuff; search to end
- of tvbuff. */
- limit = tvbufflen;
- }
- else {
+ if (limit > (guint) maxlength) {
/* Maximum length doesn't go past end of tvbuff; search
to that value. */
limit = maxlength;
/* 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;
}
}
}
- 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
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);
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);
}
}
-/* 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.
- *
- * If scope is set to NULL, returned buffer is allocated by g_malloc()
- * and must be g_free by the caller. Otherwise memory is automatically
- * freed when the scope lifetime is reached.
- */
-/* XXX: This has been replaced by tvb_get_string() */
-char *
-tvb_get_faked_unicode(wmem_allocator_t *scope, tvbuff_t *tvb, int offset,
- const int len, const gboolean little_endian)
-{
- char *buffer;
- int i;
- guint16 character;
-
- /* Make sure we have enough data before allocating the buffer,
- so we don't blow up if the length is huge. */
- tvb_ensure_bytes_exist(tvb, offset, 2*len);
-
- /* We know we won't throw an exception, so we don't have to worry
- about leaking this buffer. */
- buffer = (char *)wmem_alloc(scope, len + 1);
-
- for (i = 0; i < len; i++) {
- character = little_endian ? tvb_get_letohs(tvb, offset)
- : tvb_get_ntohs(tvb, offset);
- buffer[i] = character < 256 ? character : '.';
- offset += 2;
- }
-
- buffer[len] = 0;
-
- return buffer;
-}
-
/*
* Format the data in the tvb from offset for length ...
*/
return format_text_wsp(ptr, stringlen);
}
+/* Unicode REPLACEMENT CHARACTER */
+#define UNREPL 0x00FFFD
+
/*
- * Given a tvbuff, an offset, and a length, allocate a buffer big enough
- * to hold a non-null-terminated string of that length at that offset,
- * plus a trailing '\0', copy the string into it, and return a pointer
- * to the string.
+ * All string functions below take a scope as an argument.
+ *
+ *
* If scope is NULL, memory is allocated with g_malloc() and user must
- * explicitely free it with g_free().
+ * explicitly free it with g_free().
* If scope is not NULL, memory is allocated with the corresponding pool
* lifetime.
- * Throws an exception if the tvbuff ends before the string does.
+ *
+ * All functions throw an exception if the tvbuff ends before the string
+ * does.
*/
-guint8 *
-tvb_get_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length)
+
+/*
+ * Given a wmem scope, tvbuff, an offset, and a length, treat the string
+ * of bytes referred to by the tvbuff, offset, and length as an ASCII string,
+ * with all bytes with the high-order bit set being invalid, and return a
+ * pointer to a UTF-8 string, allocated using the wmem scope.
+ *
+ * Octets with the highest bit set will be converted to the Unicode
+ * REPLACEMENT CHARACTER.
+ */
+static guint8 *
+tvb_get_ascii_string(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length)
+{
+ const guint8 *ptr;
+
+ ptr = ensure_contiguous(tvb, offset, length);
+ return get_ascii_string(scope, ptr, length);
+}
+
+/*
+ * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
+ * of bytes referred to by the tvbuff, the offset. and the length as a UTF-8
+ * string, and return a pointer to that string, allocated using the wmem scope.
+ *
+ * XXX - should map invalid UTF-8 sequences to UNREPL.
+ */
+static guint8 *
+tvb_get_utf_8_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length)
{
- guint8 *strbuf;
+ guint8 *strbuf;
tvb_ensure_bytes_exist(tvb, offset, length); /* make sure length = -1 fails */
strbuf = (guint8 *)wmem_alloc(scope, length + 1);
return strbuf;
}
-static guint8 *
-tvb_get_string_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length)
+/*
+ * Given a wmem scope, tvbuff, an offset, and a length, treat the string
+ * of bytes referred to by the tvbuff, the offset, and the length as a
+ * raw string, and return a pointer to that string, allocated using the
+ * wmem scope. This means a null is appended at the end, but no replacement
+ * checking is done otherwise. Currently tvb_get_utf_8_string() does not
+ * replace either, but it might in the future.
+ *
+ * Also, this one allows a length of -1 to mean get all, but does not
+ * allow a negative offset.
+ */
+static inline guint8 *
+tvb_get_raw_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, const gint length)
{
- wmem_strbuf_t *str;
+ guint8 *strbuf;
+ gint abs_length = length;
- str = wmem_strbuf_new(scope, "");
+ DISSECTOR_ASSERT(offset >= 0);
+ DISSECTOR_ASSERT(abs_length >= -1);
- while (length > 0) {
- guint8 ch = tvb_get_guint8(tvb, offset);
+ if (abs_length < 0)
+ abs_length = tvb->length - offset;
- if (ch < 0x80)
- wmem_strbuf_append_c(str, ch);
- else {
- /*
- * Note: we assume here that the code points
- * 0x80-0x9F are used for C1 control characters,
- * and thus have the same value as the corresponding
- * Unicode code points.
- */
- wmem_strbuf_append_unichar(str, ch);
- }
- offset++;
- length--;
- }
-
- /* XXX, discarding constiness, should we have some function which "take-over" strbuf->str (like when strbuf is no longer needed) */
- return (guint8 *) wmem_strbuf_get_str(str);
+ tvb_ensure_bytes_exist(tvb, offset, abs_length);
+ strbuf = (guint8 *)wmem_alloc(scope, abs_length + 1);
+ tvb_memcpy(tvb, strbuf, offset, abs_length);
+ strbuf[abs_length] = '\0';
+ return strbuf;
}
+/*
+ * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
+ * of bytes referred to by the tvbuff, the offset, and the length as an
+ * ISO 8859/1 string, and return a pointer to a UTF-8 string, allocated
+ * using the wmem scope.
+ */
static guint8 *
-tvb_get_string_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length, const gunichar2 table[0x80])
+tvb_get_string_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length)
{
- wmem_strbuf_t *str;
+ const guint8 *ptr;
- str = wmem_strbuf_new(scope, "");
-
- while (length > 0) {
- guint8 ch = tvb_get_guint8(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, length);
+ return get_8859_1_string(scope, ptr, length);
+}
- if (ch < 0x80)
- wmem_strbuf_append_c(str, ch);
- else
- wmem_strbuf_append_unichar(str, table[ch-0x80]);
- offset++;
- length--;
- }
+/*
+ * Given a wmem scope, a tvbuff, an offset, and a length, and a translation
+ * table, treat the string of bytes referred to by the tvbuff, the offset,
+ * and the length as a string encoded using one octet per character, with
+ * octets with the high-order bit clear being ASCII and octets with the
+ * high-order bit set being mapped by the translation table to 2-byte
+ * Unicode Basic Multilingual Plane characters (including REPLACEMENT
+ * CHARACTER), and return a pointer to a UTF-8 string, allocated with the
+ * wmem scope.
+ */
+static guint8 *
+tvb_get_string_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length, const gunichar2 table[0x80])
+{
+ const guint8 *ptr;
- /* XXX, discarding constiness, should we have some function which "take-over" strbuf->str (like when strbuf is no longer needed) */
- return (guint8 *) wmem_strbuf_get_str(str);
+ ptr = ensure_contiguous(tvb, offset, length);
+ return get_unichar2_string(scope, ptr, length, table);
}
/*
- * Unicode (UTF-16) version of tvb_get_string()
- * XXX - this is UCS-2, not UTF-16, as it doesn't handle surrogate pairs
- *
- * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
+ * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
+ * giving the byte order, treat the string of bytes referred to by the
+ * tvbuff, the offset, and the length as a UCS-2 encoded string in
+ * the byte order in question, containing characters from the Basic
+ * Multilingual Plane (plane 0) of Unicode, and return a pointer to a
+ * UTF-8 string, allocated with the wmem scope.
*
- * Specify length in bytes
+ * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
*
- * If scope is NULL, memory is allocated with g_malloc() and user must
- * explicitely free it with g_free().
- * If scope is not NULL, memory is allocated with the corresponding pool
- * lifetime.
+ * Specify length in bytes.
*
- * Returns an UTF-8 string
+ * XXX - should map lead and trail surrogate values to REPLACEMENT
+ * CHARACTERs (0xFFFD)?
+ * XXX - if there are an odd number of bytes, should put a
+ * REPLACEMENT CHARACTER at the end.
*/
-gchar *
-tvb_get_unicode_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
+static guint8 *
+tvb_get_ucs_2_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
{
- gunichar2 uchar;
- gint i; /* Byte counter for tvbuff */
- wmem_strbuf_t *strbuf;
+ const guint8 *ptr;
- tvb_ensure_bytes_exist(tvb, offset, length);
-
- strbuf = wmem_strbuf_new(scope, NULL);
-
- for(i = 0; i + 1 < length; i += 2) {
- if (encoding == ENC_BIG_ENDIAN)
- uchar = tvb_get_ntohs(tvb, offset + i);
- else
- uchar = tvb_get_letohs(tvb, offset + i);
+ ptr = ensure_contiguous(tvb, offset, length);
+ return get_ucs_2_string(scope, ptr, length, encoding);
+}
- wmem_strbuf_append_unichar(strbuf, uchar);
- }
+/*
+ * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
+ * giving the byte order, treat the string of bytes referred to by the
+ * tvbuff, the offset, and the length as a UTF-16 encoded string in
+ * the byte order in question, and return a pointer to a UTF-8 string,
+ * allocated with the wmem scope.
+ *
+ * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
+ *
+ * Specify length in bytes.
+ *
+ * XXX - should map surrogate errors to REPLACEMENT CHARACTERs (0xFFFD).
+ * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
+ * XXX - if there are an odd number of bytes, should put a
+ * REPLACEMENT CHARACTER at the end.
+ */
+static guint8 *
+tvb_get_utf_16_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
+{
+ const guint8 *ptr;
- /*
- * XXX - if i < length, this means we were handed an odd
- * number of bytes, so we're not a valid UCS-2 string.
- */
- return (gchar*)wmem_strbuf_get_str(strbuf);
+ ptr = ensure_contiguous(tvb, offset, length);
+ return get_utf_16_string(scope, ptr, length, encoding);
+}
+
+/*
+ * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
+ * giving the byte order, treat the string of bytes referred to by the
+ * tvbuff, the offset, and the length as a UCS-4 encoded string in
+ * the byte order in question, and return a pointer to a UTF-8 string,
+ * allocated with the wmem scope.
+ *
+ * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
+ *
+ * Specify length in bytes
+ *
+ * XXX - should map lead and trail surrogate values to a "substitute"
+ * UTF-8 character?
+ * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
+ * XXX - if the number of bytes isn't a multiple of 4, should put a
+ * REPLACEMENT CHARACTER at the end.
+ */
+static gchar *
+tvb_get_ucs_4_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
+{
+ const guint8 *ptr;
+
+ ptr = ensure_contiguous(tvb, offset, length);
+ return get_ucs_4_string(scope, ptr, length, encoding);
+}
+
+gchar *
+tvb_get_ts_23_038_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb,
+ const gint bit_offset, gint no_of_chars)
+{
+ gint in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
+ gint length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
+ const guint8 *ptr;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ ptr = ensure_contiguous(tvb, in_offset, length);
+ return get_ts_23_038_7bits_string(scope, ptr, bit_offset, no_of_chars);
+}
+
+gchar *
+tvb_get_ascii_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb,
+ const gint bit_offset, gint no_of_chars)
+{
+ gint in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
+ gint length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
+ const guint8 *ptr;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ ptr = ensure_contiguous(tvb, in_offset, length);
+ return get_ascii_7bits_string(scope, ptr, bit_offset, no_of_chars);
+}
+
+/*
+ * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
+ * of bytes referred to by the tvbuff, offset, and length as a string encoded
+ * in EBCDIC using one octet per character, and return a pointer to a
+ * UTF-8 string, allocated using the wmem scope.
+ */
+static guint8 *
+tvb_get_ebcdic_string(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint length)
+{
+ const guint8 *ptr;
+
+ ptr = ensure_contiguous(tvb, offset, length);
+ return get_ebcdic_string(scope, ptr, length);
}
/*
* at that offset, plus a trailing '\0', copy into the buffer the
* string as converted from the appropriate encoding to UTF-8, and
* return a pointer to the string.
- *
- * Throws an exception if the tvbuff ends before the string does.
- *
- * If scope is NULL, memory is allocated with g_malloc() and user must
- * explicitely free it with g_free().
- * If scope is not NULL, memory is allocated with the corresponding pool
- * lifetime.
*/
guint8 *
tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset,
const gint length, const guint encoding)
{
- const guint8 *ptr;
- guint8 *strbuf;
+ guint8 *strptr;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ /* make sure length = -1 fails */
+ if (length < 0) {
+ THROW(ReportedBoundsError);
+ }
switch (encoding & ENC_CHARENCODING_MASK) {
* was a gboolean for the byte order, not an
* encoding value, and passed non-zero values
* other than TRUE to mean "little-endian".
- *
- * XXX - should map all octets with the 8th bit
- * not set to a "substitute" UTF-8 character.
*/
- strbuf = tvb_get_string(scope, tvb, offset, length);
+ strptr = tvb_get_ascii_string(scope, tvb, offset, length);
break;
- case ENC_WINDOWS_1250:
- strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1250);
+ case ENC_UTF_8:
+ /*
+ * XXX - should map lead and trail surrogate value code
+ * points to a "substitute" UTF-8 character?
+ * XXX - should map code points > 10FFFF to REPLACEMENT
+ * CHARACTERs.
+ */
+ strptr = tvb_get_utf_8_string(scope, tvb, offset, length);
+ break;
+
+ case ENC_UTF_16:
+ strptr = tvb_get_utf_16_string(scope, tvb, offset, length,
+ encoding & ENC_LITTLE_ENDIAN);
+ break;
+
+ case ENC_UCS_2:
+ strptr = tvb_get_ucs_2_string(scope, tvb, offset, length,
+ encoding & ENC_LITTLE_ENDIAN);
+ break;
+
+ case ENC_UCS_4:
+ strptr = tvb_get_ucs_4_string(scope, tvb, offset, length,
+ encoding & ENC_LITTLE_ENDIAN);
break;
case ENC_ISO_8859_1:
* to the equivalent Unicode code point value, so
* no translation table is needed.
*/
- strbuf = tvb_get_string_8859_1(scope, tvb, offset, length);
+ strptr = tvb_get_string_8859_1(scope, tvb, offset, length);
break;
case ENC_ISO_8859_2:
- strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_2);
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_2);
+ break;
+
+ case ENC_ISO_8859_3:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_3);
+ break;
+
+ case ENC_ISO_8859_4:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_4);
break;
case ENC_ISO_8859_5:
- strbuf = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_5);
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_5);
break;
- case ENC_UTF_8:
- /*
- * XXX - should map all invalid UTF-8 sequences
- * to a "substitute" UTF-8 character.
- */
- strbuf = tvb_get_string(scope, tvb, offset, length);
+ case ENC_ISO_8859_6:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_6);
break;
- case ENC_UTF_16:
- /*
- * XXX - needs to handle surrogate pairs and to map
- * invalid characters and sequences to a "substitute"
- * UTF-8 character.
- */
- strbuf = tvb_get_unicode_string(scope, tvb, offset, length,
- encoding & ENC_LITTLE_ENDIAN);
+ case ENC_ISO_8859_7:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_7);
break;
- case ENC_UCS_2:
- /*
- * XXX - needs to map values that are not valid UCS-2
- * characters (such as, I think, values used as the
- * components of a UTF-16 surrogate pair) to a
- * "substitute" UTF-8 character.
- */
- strbuf = tvb_get_unicode_string(scope, tvb, offset, length,
- encoding & ENC_LITTLE_ENDIAN);
+ case ENC_ISO_8859_8:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_8);
+ break;
+
+ case ENC_ISO_8859_9:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_9);
+ break;
+
+ case ENC_ISO_8859_10:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_10);
+ break;
+
+ case ENC_ISO_8859_11:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_11);
+ break;
+
+ case ENC_ISO_8859_13:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_13);
+ break;
+
+ case ENC_ISO_8859_14:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_14);
+ break;
+
+ case ENC_ISO_8859_15:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_15);
+ break;
+
+ case ENC_ISO_8859_16:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_16);
+ break;
+
+ case ENC_WINDOWS_1250:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1250);
+ break;
+
+ case ENC_MAC_ROMAN:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_mac_roman);
+ break;
+
+ case ENC_CP437:
+ strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp437);
+ break;
+
+ case ENC_3GPP_TS_23_038_7BITS:
+ {
+ gint bit_offset = offset << 3;
+ gint no_of_chars = (length << 3) / 7;
+ strptr = tvb_get_ts_23_038_7bits_string(scope, tvb, bit_offset, no_of_chars);
+ }
+ break;
+
+ case ENC_ASCII_7BITS:
+ {
+ gint bit_offset = offset << 3;
+ gint no_of_chars = (length << 3) / 7;
+ strptr = tvb_get_ascii_7bits_string(scope, tvb, bit_offset, no_of_chars);
+ }
break;
case ENC_EBCDIC:
/*
- * XXX - do the copy and conversion in one pass.
- *
* XXX - multiple "dialects" of EBCDIC?
*/
- tvb_ensure_bytes_exist(tvb, offset, length); /* make sure length = -1 fails */
- strbuf = (guint8 *)wmem_alloc(scope, length + 1);
- if (length != 0) {
- ptr = ensure_contiguous(tvb, offset, length);
- memcpy(strbuf, ptr, length);
- EBCDIC_to_ASCII(strbuf, length);
- }
- strbuf[length] = '\0';
+ strptr = tvb_get_ebcdic_string(scope, tvb, offset, length);
break;
}
- return strbuf;
+ return strptr;
}
/*
- * Given a tvbuff and an offset, with the offset assumed to refer to
- * 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
- * string (including the terminating null) through a pointer.
+ * This is like tvb_get_string_enc(), except that it handles null-padded
+ * strings.
*
- * If scope is NULL, memory is allocated with g_malloc() and user must
- * explicitely free it with g_free().
- * If scope is not NULL, memory is allocated with the corresponding pool
- * lifetime.
+ * Currently, string values are stored as UTF-8 null-terminated strings,
+ * so nothing needs to be done differently for null-padded strings; we
+ * could save a little memory by not storing the null padding.
+ *
+ * If we ever store string values differently, in a fashion that doesn't
+ * involve null termination, that might change.
*/
guint8 *
-tvb_get_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp)
+tvb_get_stringzpad(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset,
+ const gint length, const guint encoding)
+{
+ return tvb_get_string_enc(scope, tvb, offset, length, encoding);
+}
+
+/*
+ * These routines are like the above routines, except that they handle
+ * null-terminated strings. They find the length of that string (and
+ * throw an exception if the tvbuff ends before we find the null), and
+ * also return through a pointer the length of the string, in bytes,
+ * including the terminating null (the terminating null being 2 bytes
+ * for UCS-2 and UTF-16, 4 bytes for UCS-4, and 1 byte for other
+ * encodings).
+ */
+static guint8 *
+tvb_get_ascii_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint *lengthp)
+{
+ guint size;
+ const guint8 *ptr;
+
+ size = tvb_strsize(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, size);
+ /* XXX, conversion between signed/unsigned integer */
+ if (lengthp)
+ *lengthp = size;
+ return get_ascii_string(scope, ptr, size);
+}
+
+static guint8 *
+tvb_get_utf_8_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp)
{
guint size;
guint8 *strptr;
tvb_get_stringz_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint *lengthp)
{
guint size;
+ const guint8 *ptr;
- /* XXX, convertion between signed/unsigned integer */
- *lengthp = size = tvb_strsize(tvb, offset);
-
- return tvb_get_string_8859_1(scope, tvb, offset, size);
+ size = tvb_strsize(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, size);
+ /* XXX, conversion between signed/unsigned integer */
+ if (lengthp)
+ *lengthp = size;
+ return get_8859_1_string(scope, ptr, size);
}
static guint8 *
tvb_get_stringz_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint *lengthp, const gunichar2 table[0x80])
{
guint size;
+ const guint8 *ptr;
+
+ size = tvb_strsize(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, size);
+ /* XXX, conversion between signed/unsigned integer */
+ if (lengthp)
+ *lengthp = size;
+ return get_unichar2_string(scope, ptr, size, table);
+}
- /* XXX, convertion between signed/unsigned integer */
- *lengthp = size = tvb_strsize(tvb, offset);
+/*
+ * Given a tvbuff and an offset, with the offset assumed to refer to
+ * a null-terminated string, find the length of that string (and throw
+ * an exception if the tvbuff ends before we find the null), ensure that
+ * the TVB is flat, and return a pointer to the string (in the TVB).
+ * Also return the length of the string (including the terminating null)
+ * through a pointer.
+ *
+ * As long as we aren't using composite TVBs, this saves the cycles used
+ * (often unnecessariliy) in allocating a buffer and copying the string into
+ * it. (If we do start using composite TVBs, we may want to replace this
+ * function with the _ephemeral version.)
+ */
+const guint8 *
+tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
+{
+ guint size;
+ const guint8 *strptr;
- return tvb_get_string_unichar2(scope, tvb, offset, size, table);
+ size = tvb_strsize(tvb, offset);
+ strptr = ensure_contiguous(tvb, offset, size);
+ if (lengthp)
+ *lengthp = size;
+ return strptr;
+}
+
+static gchar *
+tvb_get_ucs_2_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
+{
+ gint size; /* Number of bytes in string */
+ const guint8 *ptr;
+
+ size = tvb_unicode_strsize(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, size);
+ /* XXX, conversion between signed/unsigned integer */
+ if (lengthp)
+ *lengthp = size;
+ return get_ucs_2_string(scope, ptr, size, encoding);
+}
+
+static gchar *
+tvb_get_utf_16_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
+{
+ gint size;
+ const guint8 *ptr;
+
+ size = tvb_unicode_strsize(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, size);
+ /* XXX, conversion between signed/unsigned integer */
+ if (lengthp)
+ *lengthp = size;
+ return get_utf_16_string(scope, ptr, size, encoding);
+}
+
+static gchar *
+tvb_get_ucs_4_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
+{
+ gint size;
+ gunichar uchar;
+ const guint8 *ptr;
+
+ size = 0;
+ do {
+ /* Endianness doesn't matter when looking for null */
+ uchar = tvb_get_ntohl(tvb, offset + size);
+ size += 4;
+ } while(uchar != 0);
+
+ ptr = ensure_contiguous(tvb, offset, size);
+ /* XXX, conversion between signed/unsigned integer */
+ if (lengthp)
+ *lengthp = size;
+ return get_ucs_4_string(scope, ptr, size, encoding);
+}
+
+static guint8 *
+tvb_get_ebcdic_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, gint offset, gint *lengthp)
+{
+ guint size;
+ const guint8 *ptr;
+
+ size = tvb_strsize(tvb, offset);
+ ptr = ensure_contiguous(tvb, offset, size);
+ /* XXX, conversion between signed/unsigned integer */
+ if (lengthp)
+ *lengthp = size;
+ return get_ebcdic_string(scope, ptr, size);
}
guint8 *
tvb_get_stringz_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
{
- guint size;
guint8 *strptr;
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
switch (encoding & ENC_CHARENCODING_MASK) {
case ENC_ASCII:
* was a gboolean for the byte order, not an
* encoding value, and passed non-zero values
* other than TRUE to mean "little-endian".
- *
- * XXX - should map all octets with the 8th bit
- * not set to a "substitute" UTF-8 character.
*/
- strptr = tvb_get_stringz(scope, tvb, offset, lengthp);
+ strptr = tvb_get_ascii_stringz(scope, tvb, offset, lengthp);
break;
- case ENC_WINDOWS_1250:
- strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1250);
+ case ENC_UTF_8:
+ /*
+ * XXX - should map all invalid UTF-8 sequences
+ * to a "substitute" UTF-8 character.
+ * XXX - should map code points > 10FFFF to REPLACEMENT
+ * CHARACTERs.
+ */
+ strptr = tvb_get_utf_8_stringz(scope, tvb, offset, lengthp);
+ break;
+
+ case ENC_UTF_16:
+ strptr = tvb_get_utf_16_stringz(scope, tvb, offset, lengthp,
+ encoding & ENC_LITTLE_ENDIAN);
+ break;
+
+ case ENC_UCS_2:
+ strptr = tvb_get_ucs_2_stringz(scope, tvb, offset, lengthp,
+ encoding & ENC_LITTLE_ENDIAN);
+ break;
+
+ case ENC_UCS_4:
+ strptr = tvb_get_ucs_4_stringz(scope, tvb, offset, lengthp,
+ encoding & ENC_LITTLE_ENDIAN);
break;
case ENC_ISO_8859_1:
strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_2);
break;
+ case ENC_ISO_8859_3:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_3);
+ break;
+
+ case ENC_ISO_8859_4:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_4);
+ break;
+
case ENC_ISO_8859_5:
strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_5);
break;
- case ENC_UTF_8:
- /*
- * XXX - should map all invalid UTF-8 sequences
- * to a "substitute" UTF-8 character.
- */
- strptr = tvb_get_stringz(scope, tvb, offset, lengthp);
+ case ENC_ISO_8859_6:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_6);
break;
- case ENC_UTF_16:
- /*
- * XXX - needs to handle surrogate pairs and to map
- * invalid characters and sequences to a "substitute"
- * UTF-8 character.
- */
- strptr = tvb_get_unicode_stringz(scope, tvb, offset, lengthp,
- encoding & ENC_LITTLE_ENDIAN);
+ case ENC_ISO_8859_7:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_7);
break;
- case ENC_UCS_2:
- /*
- * XXX - needs to map values that are not valid UCS-2
- * characters (such as, I think, values used as the
- * components of a UTF-16 surrogate pair) to a
- * "substitute" UTF-8 character.
- */
- strptr = tvb_get_unicode_stringz(scope, tvb, offset, lengthp,
- encoding & ENC_LITTLE_ENDIAN);
+ case ENC_ISO_8859_8:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_8);
break;
- case ENC_EBCDIC:
- /*
- * XXX - do the copy and conversion in one pass.
- *
- * XXX - multiple "dialects" of EBCDIC?
- */
- size = tvb_strsize(tvb, offset);
- strptr = (guint8 *)wmem_alloc(scope, size);
- tvb_memcpy(tvb, strptr, offset, size);
- EBCDIC_to_ASCII(strptr, size);
- if (lengthp)
- *lengthp = size;
+ case ENC_ISO_8859_9:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_9);
break;
- }
- return strptr;
-}
+ case ENC_ISO_8859_10:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_10);
+ break;
-/*
- * Given a tvbuff and an offset, with the offset assumed to refer to
- * a null-terminated string, find the length of that string (and throw
- * an exception if the tvbuff ends before we find the null), ensure that
- * the TVB is flat, and return a pointer to the string (in the TVB).
- * Also return the length of the string (including the terminating null)
- * through a pointer.
- *
- * As long as we aren't using composite TVBs, this saves the cycles used
- * (often unnecessariliy) in allocating a buffer and copying the string into
- * it. (If we do start using composite TVBs, we may want to replace this
- * function with the _ephemeral versoin.)
- */
-const guint8 *
-tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
-{
- guint size;
- const guint8 *strptr;
+ case ENC_ISO_8859_11:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_11);
+ break;
- size = tvb_strsize(tvb, offset);
- strptr = ensure_contiguous(tvb, offset, size);
- if (lengthp)
- *lengthp = size;
- return strptr;
-}
+ case ENC_ISO_8859_13:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_13);
+ break;
-/*
- * Unicode (UTF-16) version of tvb_get_stringz()
- *
- * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
- *
- * Returns an allocated UTF-8 string and updates lengthp pointer with length of string (in bytes)
- */
-gchar *
-tvb_get_unicode_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
-{
- gunichar2 uchar;
- gint size; /* Number of UTF-16 characters */
- gint i; /* Byte counter for tvbuff */
- wmem_strbuf_t *strbuf;
+ case ENC_ISO_8859_14:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_14);
+ break;
- size = tvb_unicode_strsize(tvb, offset);
+ case ENC_ISO_8859_15:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_15);
+ break;
- strbuf = wmem_strbuf_new(scope, NULL);
+ case ENC_ISO_8859_16:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_16);
+ break;
- for(i = 0; i < size; i += 2) {
- if (encoding == ENC_BIG_ENDIAN)
- uchar = tvb_get_ntohs(tvb, offset + i);
- else
- uchar = tvb_get_letohs(tvb, offset + i);
+ case ENC_WINDOWS_1250:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1250);
+ break;
- wmem_strbuf_append_unichar(strbuf, uchar);
- }
+ case ENC_MAC_ROMAN:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_mac_roman);
+ break;
- if (lengthp)
- *lengthp = i; /* Number of *bytes* processed */
+ case ENC_CP437:
+ strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp437);
+ break;
- return (gchar*)wmem_strbuf_get_str(strbuf);
+ case ENC_3GPP_TS_23_038_7BITS:
+ REPORT_DISSECTOR_BUG("TS 23.038 7bits has no null character and doesn't support null-terminated strings");
+ break;
+
+ case ENC_ASCII_7BITS:
+ REPORT_DISSECTOR_BUG("tvb_get_stringz_enc function with ENC_ASCII_7BITS not implemented yet");
+ break;
+
+ case ENC_EBCDIC:
+ /*
+ * XXX - multiple "dialects" of EBCDIC?
+ */
+ strptr = tvb_get_ebcdic_stringz(scope, tvb, offset, lengthp);
+ break;
+ }
+
+ return strptr;
}
/* Looks for a stringz (NUL-terminated string) in tvbuff and copies
_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. */
* at the correct spot, terminating the string.
*/
gint
-tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer)
+tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8 *buffer)
{
gint bytes_copied;
}
}
+
+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
gint eol_offset;
int linelen;
guchar found_needle = 0;
+ static gboolean compiled = FALSE;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
if (len == -1)
- len = tvb_length_remaining(tvb, offset);
+ len = _tvb_captured_length_remaining(tvb, offset);
/*
* XXX - what if "len" is still -1, meaning "offset is past the
* end of the tvbuff"?
*/
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, "\r\n", &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.
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
guchar c = 0;
gint eob_offset;
int linelen;
+ static gboolean compiled = FALSE;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
if (len == -1)
- len = tvb_length_remaining(tvb, offset);
+ 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"?
/*
* 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) {
/*
gint end, tvb_len;
guint8 tempchar;
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
/* Get the length remaining */
- tvb_len = tvb_length(tvb);
+ /*tvb_len = tvb_captured_length(tvb);*/
+ tvb_len = tvb->length;
+
end = offset + maxlength;
if (end >= tvb_len)
{
return (counter);
}
+int
+tvb_skip_guint8(tvbuff_t *tvb, int offset, const int maxlength, const guint8 ch)
+{
+ int end, tvb_len;
+
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
+ /* Get the length remaining */
+ /*tvb_len = tvb_captured_length(tvb);*/
+ tvb_len = tvb->length;
+
+ end = offset + maxlength;
+ if (end >= tvb_len)
+ end = tvb_len;
+
+ while (offset < end) {
+ guint8 tempch = tvb_get_guint8(tvb, offset);
+
+ if (tempch != ch)
+ break;
+ offset++;
+ }
+
+ return offset;
+}
/*
* Format a bunch of data from a tvbuff as bytes, returning a pointer
* separator.
*/
gchar *
-tvb_bytes_to_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_str_punct(ensure_contiguous(tvb, offset, len), len, punct);
+ return bytestring_to_str(scope, ensure_contiguous(tvb, offset, len), len, punct);
}
char *digit_str;
gint t_offset = offset;
+ DISSECTOR_ASSERT(tvb && tvb->initialized);
+
if (!dgt)
dgt = &Dgt1_9_bcd;
if (len == -1) {
- length = tvb_length(tvb);
+ /*length = tvb_captured_length(tvb);*/
+ length = tvb->length;
if (length < offset) {
return "";
}
*/
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++;
* Format a bunch of data from a tvbuff as bytes, returning a pointer
* to the string with the formatted data.
*/
-gchar *
-tvb_bytes_to_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_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;
gint
tvb_raw_offset(tvbuff_t *tvb)
{
- return ((tvb->raw_offset==-1)?(tvb->raw_offset = tvb_offset_from_real_beginning(tvb)):tvb->raw_offset);
+ return ((tvb->raw_offset==-1) ? (tvb->raw_offset = tvb_offset_from_real_beginning(tvb)) : tvb->raw_offset);
}
void