3 * Testy, Virtual(-izable) Buffer of guint8*'s
5 * "Testy" -- the buffer gets mad when an attempt to access data
6 * beyond the bounds of the buffer. An exception is thrown.
8 * "Virtual" -- the buffer can have its own data, can use a subset of
9 * the data of a backing tvbuff, or can be a composite of
12 * $Id: tvbuff.c,v 1.54 2003/12/03 10:14:34 sahlberg Exp $
14 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
16 * Code to convert IEEE floating point formats to native floating point
17 * derived from code Copyright (c) Ashok Narayanan, 2000
19 * Ethereal - Network traffic analyzer
20 * By Gerald Combs <gerald@ethereal.com>
21 * Copyright 1998 Gerald Combs
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
49 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
53 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
55 /* We dole out tvbuff's from this memchunk. */
56 GMemChunk *tvbuff_mem_chunk = NULL;
61 if (!tvbuff_mem_chunk)
62 tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
69 g_mem_chunk_destroy(tvbuff_mem_chunk);
71 tvbuff_mem_chunk = NULL;
78 tvb_init(tvbuff_t *tvb, tvbuff_type type)
80 tvb_backing_t *backing;
81 tvb_comp_t *composite;
84 tvb->initialized = FALSE;
87 tvb->reported_length = 0;
89 tvb->real_data = NULL;
95 case TVBUFF_REAL_DATA:
100 backing = &tvb->tvbuffs.subset;
106 case TVBUFF_COMPOSITE:
107 composite = &tvb->tvbuffs.composite;
108 composite->tvbs = NULL;
109 composite->start_offsets = NULL;
110 composite->end_offsets = NULL;
117 tvb_new(tvbuff_type type)
121 tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
130 tvb_free(tvbuff_t* tvb)
132 tvbuff_t *member_tvb;
133 tvb_comp_t *composite;
138 if (tvb->usage_count == 0) {
140 case TVBUFF_REAL_DATA:
142 tvb->free_cb(tvb->real_data);
147 /* This will be NULL if tvb_new_subset() fails because
148 * reported_length < -1 */
149 if (tvb->tvbuffs.subset.tvb) {
150 tvb_decrement_usage_count(tvb->tvbuffs.subset.tvb, 1);
154 case TVBUFF_COMPOSITE:
155 composite = &tvb->tvbuffs.composite;
156 for (slist = composite->tvbs; slist != NULL ; slist = slist->next) {
157 member_tvb = slist->data;
158 tvb_decrement_usage_count(member_tvb, 1);
161 g_slist_free(composite->tvbs);
163 if (composite->start_offsets)
164 g_free(composite->start_offsets);
165 if (composite->end_offsets)
166 g_free(composite->end_offsets);
168 g_free(tvb->real_data);
174 g_slist_free(tvb->used_in);
177 g_chunk_free(tvb, tvbuff_mem_chunk);
182 tvb_increment_usage_count(tvbuff_t* tvb, guint count)
184 tvb->usage_count += count;
186 return tvb->usage_count;
190 tvb_decrement_usage_count(tvbuff_t* tvb, guint count)
192 if (tvb->usage_count <= count) {
193 tvb->usage_count = 1;
198 tvb->usage_count -= count;
199 return tvb->usage_count;
205 tvb_free_chain(tvbuff_t* tvb)
209 /* Recursively call tvb_free_chain() */
210 for (slist = tvb->used_in; slist != NULL ; slist = slist->next) {
211 tvb_free_chain( (tvbuff_t*)slist->data );
214 /* Stop the recursion */
221 tvb_set_free_cb(tvbuff_t* tvb, tvbuff_free_cb_t func)
223 g_assert(tvb->type == TVBUFF_REAL_DATA);
228 add_to_used_in_list(tvbuff_t *tvb, tvbuff_t *used_in)
230 tvb->used_in = g_slist_prepend(tvb->used_in, used_in);
231 tvb_increment_usage_count(tvb, 1);
235 tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
237 g_assert(parent->initialized);
238 g_assert(child->initialized);
239 g_assert(child->type == TVBUFF_REAL_DATA);
240 add_to_used_in_list(parent, child);
244 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
246 g_assert(tvb->type == TVBUFF_REAL_DATA);
247 g_assert(!tvb->initialized);
249 if (reported_length < -1) {
250 THROW(ReportedBoundsError);
253 tvb->real_data = (gpointer) data;
254 tvb->length = length;
255 tvb->reported_length = reported_length;
256 tvb->initialized = TRUE;
260 tvb_new_real_data(const guint8* data, guint length, gint reported_length)
262 static tvbuff_t *last_tvb=NULL;
265 tvb = tvb_new(TVBUFF_REAL_DATA);
270 /* remember this tvb in case we throw an exception and
271 * lose the pointer to it.
275 tvb_set_real_data(tvb, data, length, reported_length);
278 * This is the top-level real tvbuff for this data source,
279 * so its data source tvbuff is itself.
283 /* ok no exception so we dont need to remember it any longer */
289 /* Computes the absolute offset and length based on a possibly-negative offset
290 * and a length that is possible -1 (which means "to the end of the data").
291 * Returns TRUE/FALSE indicating whether the offset is in bounds or
292 * not. The integer ptrs are modified with the new offset and length.
293 * No exception is thrown.
295 * XXX - we return TRUE, not FALSE, if the offset is positive and right
296 * after the end of the tvbuff (i.e., equal to the length). We do this
297 * so that a dissector constructing a subset tvbuff for the next protocol
298 * will get a zero-length tvbuff, not an exception, if there's no data
299 * left for the next protocol - we want the next protocol to be the one
300 * that gets an exception, so the error is reported as an error in that
301 * protocol rather than the containing protocol. */
303 compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
304 guint *offset_ptr, guint *length_ptr, int *exception)
306 g_assert(offset_ptr);
307 g_assert(length_ptr);
309 /* Compute the offset */
311 /* Positive offset - relative to the beginning of the packet. */
312 if ((guint) offset > tvb->reported_length) {
314 *exception = ReportedBoundsError;
318 else if ((guint) offset > tvb->length) {
320 *exception = BoundsError;
325 *offset_ptr = offset;
329 /* Negative offset - relative to the end of the packet. */
330 if ((guint) -offset > tvb->reported_length) {
332 *exception = ReportedBoundsError;
336 else if ((guint) -offset > tvb->length) {
338 *exception = BoundsError;
343 *offset_ptr = tvb->length + offset;
347 /* Compute the length */
350 /* XXX - ReportedBoundsError? */
351 *exception = BoundsError;
355 else if (length == -1) {
356 *length_ptr = tvb->length - *offset_ptr;
359 *length_ptr = length;
367 check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
368 guint *offset_ptr, guint *length_ptr, int *exception)
372 g_assert(tvb->initialized);
374 if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
379 * Compute the offset of the first byte past the length.
381 end_offset = *offset_ptr + *length_ptr;
384 * Check for an overflow, and clamp "end_offset" at the maximum
385 * if we got an overflow - that should force us to indicate that
386 * we're past the end of the tvbuff.
388 if (end_offset < *offset_ptr)
389 end_offset = UINT_MAX;
392 * Check whether that offset goes more than one byte past the
395 * If not, return TRUE; otherwise, return FALSE and, if "exception"
396 * is non-null, return the appropriate exception through it.
398 if (end_offset <= tvb->length) {
401 else if (end_offset <= tvb->reported_length) {
403 *exception = BoundsError;
409 *exception = ReportedBoundsError;
414 g_assert_not_reached();
417 /* Checks (+/-) offset and length and throws an exception if
418 * either is out of bounds. Sets integer ptrs to the new offset
421 check_offset_length(tvbuff_t *tvb, gint offset, gint length,
422 guint *offset_ptr, guint *length_ptr)
426 if (!check_offset_length_no_exception(tvb, offset, length, offset_ptr, length_ptr, &exception)) {
427 g_assert(exception > 0);
435 tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
436 gint backing_offset, gint backing_length, gint reported_length)
438 g_assert(tvb->type == TVBUFF_SUBSET);
439 g_assert(!tvb->initialized);
441 if (reported_length < -1) {
442 THROW(ReportedBoundsError);
445 check_offset_length(backing, backing_offset, backing_length,
446 &tvb->tvbuffs.subset.offset,
447 &tvb->tvbuffs.subset.length);
449 tvb->tvbuffs.subset.tvb = backing;
450 tvb->length = tvb->tvbuffs.subset.length;
452 if (reported_length == -1) {
453 tvb->reported_length = backing->reported_length - tvb->tvbuffs.subset.offset;
456 tvb->reported_length = reported_length;
458 tvb->initialized = TRUE;
459 add_to_used_in_list(backing, tvb);
461 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
462 * then we can point directly to our starting offset in that buffer */
463 if (backing->real_data != NULL) {
464 tvb->real_data = backing->real_data + tvb->tvbuffs.subset.offset;
470 tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
472 static tvbuff_t *last_tvb=NULL;
475 tvb = tvb_new(TVBUFF_SUBSET);
480 /* remember this tvb in case we throw an exception and
481 * lose the pointer to it.
485 tvb_set_subset(tvb, backing, backing_offset, backing_length, reported_length);
488 * The top-level data source of this tvbuff is the top-level
489 * data source of its parent.
491 tvb->ds_tvb = backing->ds_tvb;
493 /* ok no exception so we dont need to remember it any longer */
500 tvb_composite_append(tvbuff_t* tvb, tvbuff_t* member)
502 tvb_comp_t *composite;
504 g_assert(!tvb->initialized);
505 composite = &tvb->tvbuffs.composite;
506 composite->tvbs = g_slist_append( composite->tvbs, member );
507 add_to_used_in_list(member, tvb);
511 tvb_composite_prepend(tvbuff_t* tvb, tvbuff_t* member)
513 tvb_comp_t *composite;
515 g_assert(!tvb->initialized);
516 composite = &tvb->tvbuffs.composite;
517 composite->tvbs = g_slist_prepend( composite->tvbs, member );
518 add_to_used_in_list(member, tvb);
522 tvb_new_composite(void)
524 return tvb_new(TVBUFF_COMPOSITE);
528 tvb_composite_finalize(tvbuff_t* tvb)
532 tvbuff_t *member_tvb;
533 tvb_comp_t *composite;
536 g_assert(!tvb->initialized);
537 g_assert(tvb->length == 0);
539 composite = &tvb->tvbuffs.composite;
540 num_members = g_slist_length(composite->tvbs);
542 composite->start_offsets = g_new(guint, num_members);
543 composite->end_offsets = g_new(guint, num_members);
545 for (slist = composite->tvbs; slist != NULL; slist = slist->next) {
546 g_assert((guint) i < num_members);
547 member_tvb = slist->data;
548 composite->start_offsets[i] = tvb->length;
549 tvb->length += member_tvb->length;
550 composite->end_offsets[i] = tvb->length - 1;
554 tvb->initialized = TRUE;
560 tvb_length(tvbuff_t* tvb)
562 g_assert(tvb->initialized);
568 tvb_length_remaining(tvbuff_t *tvb, gint offset)
570 guint abs_offset, abs_length;
572 g_assert(tvb->initialized);
574 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
583 tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
585 guint abs_offset, abs_length;
588 g_assert(tvb->initialized);
590 if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, &exception)) {
599 /* Validates that 'length' bytes are available starting from
600 * offset (pos/neg). Does not throw an exception. */
602 tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
604 guint abs_offset, abs_length;
606 g_assert(tvb->initialized);
608 if (!compute_offset_length(tvb, offset, length, &abs_offset, &abs_length, NULL))
611 if (abs_offset + abs_length <= tvb->length) {
619 /* Validates that 'length' bytes are available starting from
620 * offset (pos/neg). Throws an exception if they aren't. */
622 tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
624 guint abs_offset, abs_length;
626 g_assert(tvb->initialized);
629 * -1 doesn't mean "until end of buffer", as that's pointless
630 * for this routine. We must treat it as a Really Large Positive
631 * Number, so that we throw an exception; we throw
632 * ReportedBoundsError, as if it were past even the end of a
633 * reassembled packet, and past the end of even the data we
636 * We do the same with other negative lengths.
639 THROW(ReportedBoundsError);
641 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
645 tvb_offset_exists(tvbuff_t *tvb, gint offset)
647 guint abs_offset, abs_length;
649 g_assert(tvb->initialized);
650 if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL))
653 if (abs_offset < tvb->length) {
662 tvb_reported_length(tvbuff_t* tvb)
664 g_assert(tvb->initialized);
666 return tvb->reported_length;
670 tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
672 guint abs_offset, abs_length;
674 g_assert(tvb->initialized);
676 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
677 if (tvb->reported_length >= abs_offset)
678 return tvb->reported_length - abs_offset;
687 /* Set the reported length of a tvbuff to a given value; used for protocols
688 whose headers contain an explicit length and where the calling
689 dissector's payload may include padding as well as the packet for
692 Also adjusts the data length. */
694 tvb_set_reported_length(tvbuff_t* tvb, guint reported_length)
696 g_assert(tvb->initialized);
698 if (reported_length > tvb->reported_length)
699 THROW(ReportedBoundsError);
701 tvb->reported_length = reported_length;
702 if (reported_length < tvb->length)
703 tvb->length = reported_length;
708 first_real_data_ptr(tvbuff_t *tvb)
713 case TVBUFF_REAL_DATA:
714 return tvb->real_data;
716 member = tvb->tvbuffs.subset.tvb;
717 return first_real_data_ptr(member);
718 case TVBUFF_COMPOSITE:
719 member = tvb->tvbuffs.composite.tvbs->data;
720 return first_real_data_ptr(member);
723 g_assert_not_reached();
728 offset_from_real_beginning(tvbuff_t *tvb, int counter)
733 case TVBUFF_REAL_DATA:
736 member = tvb->tvbuffs.subset.tvb;
737 return offset_from_real_beginning(member, counter + tvb->tvbuffs.subset.offset);
738 case TVBUFF_COMPOSITE:
739 member = tvb->tvbuffs.composite.tvbs->data;
740 return offset_from_real_beginning(member, counter);
743 g_assert_not_reached();
748 composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
751 guint i, num_members;
752 tvb_comp_t *composite;
753 tvbuff_t *member_tvb = NULL;
754 guint member_offset, member_length;
757 g_assert(tvb->type == TVBUFF_COMPOSITE);
759 /* Maybe the range specified by offset/length
760 * is contiguous inside one of the member tvbuffs */
761 composite = &tvb->tvbuffs.composite;
762 num_members = g_slist_length(composite->tvbs);
764 for (i = 0; i < num_members; i++) {
765 if (abs_offset <= composite->end_offsets[i]) {
766 slist = g_slist_nth(composite->tvbs, i);
767 member_tvb = slist->data;
771 g_assert(member_tvb);
773 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
774 abs_length, &member_offset, &member_length, NULL)) {
777 * The range is, in fact, contiguous within member_tvb.
779 g_assert(!tvb->real_data);
780 return ensure_contiguous_no_exception(member_tvb, member_offset, member_length, NULL);
783 tvb->real_data = tvb_memdup(tvb, 0, -1);
784 return tvb->real_data + abs_offset;
787 g_assert_not_reached();
792 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
795 guint abs_offset, abs_length;
797 if (!check_offset_length_no_exception(tvb, offset, length,
798 &abs_offset, &abs_length, exception)) {
803 * We know that all the data is present in the tvbuff, so
804 * no exceptions should be thrown.
806 if (tvb->real_data) {
807 return tvb->real_data + abs_offset;
811 case TVBUFF_REAL_DATA:
812 g_assert_not_reached();
814 return ensure_contiguous_no_exception(tvb->tvbuffs.subset.tvb,
815 abs_offset - tvb->tvbuffs.subset.offset,
817 case TVBUFF_COMPOSITE:
818 return composite_ensure_contiguous_no_exception(tvb, abs_offset, abs_length);
822 g_assert_not_reached();
827 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length)
832 p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
834 g_assert(exception > 0);
841 guint8_find(const guint8* haystack, size_t haystacklen, guint8 needle)
846 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
856 guint8_pbrk(const guint8* haystack, size_t haystacklen, guint8 *needles)
860 guint8 item, *needlep, needle;
862 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
865 while ((needle = *needlep) != '\0') {
877 /************** ACCESSORS **************/
880 composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, guint abs_length)
882 guint i, num_members;
883 tvb_comp_t *composite;
884 tvbuff_t *member_tvb = NULL;
885 guint member_offset, member_length;
889 g_assert(tvb->type == TVBUFF_COMPOSITE);
891 /* Maybe the range specified by offset/length
892 * is contiguous inside one of the member tvbuffs */
893 composite = &tvb->tvbuffs.composite;
894 num_members = g_slist_length(composite->tvbs);
896 for (i = 0; i < num_members; i++) {
897 if (abs_offset <= composite->end_offsets[i]) {
898 slist = g_slist_nth(composite->tvbs, i);
899 member_tvb = slist->data;
903 g_assert(member_tvb);
905 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
906 abs_length, &member_offset, &member_length, NULL)) {
908 g_assert(!tvb->real_data);
909 return tvb_memcpy(member_tvb, target, member_offset, member_length);
912 /* The requested data is non-contiguous inside
913 * the member tvb. We have to memcpy() the part that's in the member tvb,
914 * then iterate across the other member tvb's, copying their portions
915 * until we have copied all data.
917 retval = compute_offset_length(member_tvb, abs_offset - composite->start_offsets[i], -1,
918 &member_offset, &member_length, NULL);
921 tvb_memcpy(member_tvb, target, member_offset, member_length);
922 abs_offset += member_length;
923 abs_length -= member_length;
926 if (abs_length > 0) {
927 composite_memcpy(tvb, target + member_length, abs_offset, abs_length);
933 g_assert_not_reached();
938 tvb_memcpy(tvbuff_t *tvb, guint8* target, gint offset, gint length)
940 guint abs_offset, abs_length;
942 g_assert(length >= -1);
943 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
945 if (tvb->real_data) {
946 return (guint8*) memcpy(target, tvb->real_data + abs_offset, abs_length);
950 case TVBUFF_REAL_DATA:
951 g_assert_not_reached();
954 return tvb_memcpy(tvb->tvbuffs.subset.tvb, target,
955 abs_offset - tvb->tvbuffs.subset.offset,
958 case TVBUFF_COMPOSITE:
959 return composite_memcpy(tvb, target, offset, length);
962 g_assert_not_reached();
968 * XXX - this doesn't treat a length of -1 as an error.
969 * If it did, this could replace some code that calls
970 * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
973 * "composite_ensure_contiguous_no_exception()" depends on -1 not being
974 * an error; does anything else depend on this routine treating -1 as
975 * meaning "to the end of the buffer"?
978 tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
980 guint abs_offset, abs_length;
983 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
985 duped = g_malloc(abs_length);
986 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
992 tvb_get_ptr(tvbuff_t *tvb, gint offset, gint length)
994 return ensure_contiguous(tvb, offset, length);
998 tvb_get_guint8(tvbuff_t *tvb, gint offset)
1002 ptr = ensure_contiguous(tvb, offset, sizeof(guint8));
1007 tvb_get_ntohs(tvbuff_t *tvb, gint offset)
1011 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1016 tvb_get_ntoh24(tvbuff_t *tvb, gint offset)
1020 ptr = ensure_contiguous(tvb, offset, 3);
1021 return pntoh24(ptr);
1025 tvb_get_ntohl(tvbuff_t *tvb, gint offset)
1029 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1034 * Stuff for IEEE float handling on platforms that don't have IEEE
1035 * format as the native floating-point format.
1037 * For now, we treat only the VAX as such a platform.
1039 * XXX - other non-IEEE boxes that can run UNIX include some Crays,
1040 * and possibly other machines.
1042 * It appears that the official Linux port to System/390 and
1043 * zArchitecture uses IEEE format floating point (not a
1046 * I don't know whether there are any other machines that
1047 * could run Ethereal and that don't use IEEE format.
1048 * As far as I know, all of the main commercial microprocessor
1049 * families on which OSes that support Ethereal can run
1050 * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
1051 * IA-64, and so on).
1061 #define IEEE_SP_NUMBER_WIDTH 32 /* bits in number */
1062 #define IEEE_SP_EXP_WIDTH 8 /* bits in exponent */
1063 #define IEEE_SP_MANTISSA_WIDTH 23 /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1065 #define IEEE_SP_SIGN_MASK 0x80000000
1066 #define IEEE_SP_EXPONENT_MASK 0x7F800000
1067 #define IEEE_SP_MANTISSA_MASK 0x007FFFFF
1068 #define IEEE_SP_INFINITY IEEE_SP_EXPONENT_MASK
1070 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1071 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1072 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1075 ieee_float_is_zero(guint32 w)
1077 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1081 get_ieee_float(guint32 w)
1087 sign = w & IEEE_SP_SIGN_MASK;
1088 exponent = w & IEEE_SP_EXPONENT_MASK;
1089 mantissa = w & IEEE_SP_MANTISSA_MASK;
1091 if (ieee_float_is_zero(w)) {
1092 /* number is zero, unnormalized, or not-a-number */
1097 * XXX - how to handle this?
1099 if (IEEE_SP_INFINITY == exponent) {
1101 * number is positive or negative infinity, or a special value
1103 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1107 exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1108 IEEE_SP_MANTISSA_WIDTH;
1109 mantissa |= IEEE_SP_IMPLIED_BIT;
1112 return -mantissa * pow(2, exponent);
1114 return mantissa * pow(2, exponent);
1119 * We assume that if you don't have IEEE floating-point, you have a
1120 * compiler that understands 64-bit integral quantities.
1122 #define IEEE_DP_NUMBER_WIDTH 64 /* bits in number */
1123 #define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
1124 #define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1126 #define IEEE_DP_SIGN_MASK 0x8000000000000000LL
1127 #define IEEE_DP_EXPONENT_MASK 0x7FF0000000000000LL
1128 #define IEEE_DP_MANTISSA_MASK 0x000FFFFFFFFFFFFFLL
1129 #define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
1131 #define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
1132 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1133 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1136 ieee_double_is_zero(guint64 w)
1138 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1142 get_ieee_double(guint64 w)
1148 sign = w & IEEE_DP_SIGN_MASK;
1149 exponent = w & IEEE_DP_EXPONENT_MASK;
1150 mantissa = w & IEEE_DP_MANTISSA_MASK;
1152 if (ieee_double_is_zero(w)) {
1153 /* number is zero, unnormalized, or not-a-number */
1158 * XXX - how to handle this?
1160 if (IEEE_DP_INFINITY == exponent) {
1162 * number is positive or negative infinity, or a special value
1164 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1168 exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1169 IEEE_DP_MANTISSA_WIDTH;
1170 mantissa |= IEEE_DP_IMPLIED_BIT;
1173 return -mantissa * pow(2, exponent);
1175 return mantissa * pow(2, exponent);
1180 * Fetches an IEEE single-precision floating-point number, in
1181 * big-endian form, and returns a "float".
1183 * XXX - should this be "double", in case there are IEEE single-
1184 * precision numbers that won't fit in some platform's native
1188 tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
1191 return get_ieee_float(tvb_get_ntohl(tvb, offset));
1198 ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1199 return ieee_fp_union.f;
1204 * Fetches an IEEE double-precision floating-point number, in
1205 * big-endian form, and returns a "double".
1208 tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
1222 #ifdef WORDS_BIGENDIAN
1223 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1224 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1226 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1227 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1230 return get_ieee_double(ieee_fp_union.dw);
1232 return ieee_fp_union.d;
1237 tvb_get_letohs(tvbuff_t *tvb, gint offset)
1241 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1242 return pletohs(ptr);
1246 tvb_get_letoh24(tvbuff_t *tvb, gint offset)
1250 ptr = ensure_contiguous(tvb, offset, 3);
1251 return pletoh24(ptr);
1255 tvb_get_letohl(tvbuff_t *tvb, gint offset)
1259 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1260 return pletohl(ptr);
1264 * Fetches an IEEE single-precision floating-point number, in
1265 * little-endian form, and returns a "float".
1267 * XXX - should this be "double", in case there are IEEE single-
1268 * precision numbers that won't fit in some platform's native
1272 tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
1275 return get_ieee_float(tvb_get_letohl(tvb, offset));
1282 ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1283 return ieee_fp_union.f;
1288 * Fetches an IEEE double-precision floating-point number, in
1289 * little-endian form, and returns a "double".
1292 tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
1306 #ifdef WORDS_BIGENDIAN
1307 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1308 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1310 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1311 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1314 return get_ieee_double(ieee_fp_union.dw);
1316 return ieee_fp_union.d;
1320 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1321 * at most maxlength number of bytes; if maxlength is -1, searches to
1323 * Returns the offset of the found needle, or -1 if not found.
1324 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1325 * in that case, -1 will be returned if the boundary is reached before
1326 * finding needle. */
1328 tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
1330 const guint8 *result;
1331 guint abs_offset, junk_length;
1335 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1337 /* Only search to end of tvbuff, w/o throwing exception. */
1338 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1339 if (maxlength == -1) {
1340 /* No maximum length specified; search to end of tvbuff. */
1343 else if (tvbufflen < (guint) maxlength) {
1344 /* Maximum length goes past end of tvbuff; search to end
1349 /* Maximum length doesn't go past end of tvbuff; search
1354 /* If we have real data, perform our search now. */
1355 if (tvb->real_data) {
1356 result = guint8_find(tvb->real_data + abs_offset, limit, needle);
1357 if (result == NULL) {
1361 return result - tvb->real_data;
1366 case TVBUFF_REAL_DATA:
1367 g_assert_not_reached();
1370 return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1371 abs_offset - tvb->tvbuffs.subset.offset,
1374 case TVBUFF_COMPOSITE:
1375 g_assert_not_reached();
1376 /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1379 g_assert_not_reached();
1383 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1384 * Searches at most maxlength number of bytes; if maxlength is -1, searches
1386 * Returns the offset of the found needle, or -1 if not found.
1387 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1388 * in that case, -1 will be returned if the boundary is reached before
1389 * finding needle. */
1391 tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 *needles)
1393 const guint8 *result;
1394 guint abs_offset, junk_length;
1398 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1400 /* Only search to end of tvbuff, w/o throwing exception. */
1401 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1402 if (maxlength == -1) {
1403 /* No maximum length specified; search to end of tvbuff. */
1406 else if (tvbufflen < (guint) maxlength) {
1407 /* Maximum length goes past end of tvbuff; search to end
1412 /* Maximum length doesn't go past end of tvbuff; search
1417 /* If we have real data, perform our search now. */
1418 if (tvb->real_data) {
1419 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
1420 if (result == NULL) {
1424 return result - tvb->real_data;
1429 case TVBUFF_REAL_DATA:
1430 g_assert_not_reached();
1433 return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
1434 abs_offset - tvb->tvbuffs.subset.offset,
1437 case TVBUFF_COMPOSITE:
1438 g_assert_not_reached();
1439 /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
1442 g_assert_not_reached();
1446 /* Find size of stringz (NUL-terminated string) by looking for terminating
1447 * NUL. The size of the string includes the terminating NUL.
1449 * If the NUL isn't found, it throws the appropriate exception.
1452 tvb_strsize(tvbuff_t *tvb, gint offset)
1454 guint abs_offset, junk_length;
1457 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1458 nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1459 if (nul_offset == -1) {
1461 * OK, we hit the end of the tvbuff, so we should throw
1464 * Did we hit the end of the captured data, or the end
1465 * of the actual data? If there's less captured data
1466 * than actual data, we presumably hit the end of the
1467 * captured data, otherwise we hit the end of the actual
1470 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
1473 THROW(ReportedBoundsError);
1476 return (nul_offset - abs_offset) + 1;
1479 /* Find length of string by looking for end of string ('\0'), up to
1480 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1482 * Returns -1 if 'maxlength' reached before finding EOS. */
1484 tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
1487 guint abs_offset, junk_length;
1489 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1491 result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1493 if (result_offset == -1) {
1497 return result_offset - abs_offset;
1502 * Implement strneql etc
1506 * Call strncmp after checking if enough chars left, returning 0 if
1507 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1510 tvb_strneql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1514 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1517 int cmp = strncmp(ptr, str, size);
1520 * Return 0 if equal, -1 otherwise.
1522 return (cmp == 0 ? 0 : -1);
1525 * Not enough characters in the tvbuff to match the
1533 * Call strncasecmp after checking if enough chars left, returning 0 if
1534 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1537 tvb_strncaseeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1541 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1544 int cmp = strncasecmp(ptr, str, size);
1547 * Return 0 if equal, -1 otherwise.
1549 return (cmp == 0 ? 0 : -1);
1552 * Not enough characters in the tvbuff to match the
1560 * Call memcmp after checking if enough chars left, returning 0 if
1561 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1564 tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1568 ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1571 int cmp = memcmp(ptr, str, size);
1574 * Return 0 if equal, -1 otherwise.
1576 return (cmp == 0 ? 0 : -1);
1579 * Not enough characters in the tvbuff to match the
1586 /* Convert a string from Unicode to ASCII. At the moment we fake it by
1587 * assuming all characters are ASCII )-: The caller must free the
1588 * result returned. The len parameter is the number of guint16's to
1589 * convert from Unicode. */
1591 tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
1597 /* Make sure we have enough data before allocating the buffer,
1598 so we don't blow up if the length is huge. */
1599 tvb_ensure_bytes_exist(tvb, offset, 2*len);
1601 /* We know we won't throw an exception, so we don't have to worry
1602 about leaking this buffer. */
1603 buffer = g_malloc(len + 1);
1605 for (i = 0; i < len; i++) {
1606 character = little_endian ? tvb_get_letohs(tvb, offset)
1607 : tvb_get_ntohs(tvb, offset);
1608 buffer[i] = character & 0xff;
1618 * Format the data in the tvb from offset for length ...
1622 tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
1627 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1629 len = tvb_length_remaining(tvb, offset);
1630 ptr = ensure_contiguous(tvb, offset, len);
1634 return format_text(ptr, len);
1639 * Given a tvbuff, an offset, and a length, allocate a buffer big enough
1640 * to hold a non-null-terminated string of that length at that offset,
1641 * plus a trailing '\0', copy the string into it, and return a pointer
1644 * Throws an exception if the tvbuff ends before the string does.
1647 tvb_get_string(tvbuff_t *tvb, gint offset, gint length)
1649 guint8 *ptr, *strbuf;
1651 ptr = ensure_contiguous(tvb, offset, length);
1652 strbuf = g_malloc(length + 1);
1654 memcpy(strbuf, ptr, length);
1655 strbuf[length] = '\0';
1660 * Given a tvbuff and an offset, with the offset assumed to refer to
1661 * a null-terminated string, find the length of that string (and throw
1662 * an exception if the tvbuff ends before we find the null), allocate
1663 * a buffer big enough to hold the string, copy the string into it,
1664 * and return a pointer to the string. Also return the length of the
1665 * string (including the terminating null) through a pointer.
1668 tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
1673 size = tvb_strsize(tvb, offset);
1674 strptr = g_malloc(size);
1675 tvb_memcpy(tvb, strptr, offset, size);
1680 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1681 * no more than bufsize number of bytes, including terminating NUL, to buffer.
1682 * Returns length of string (not including terminating NUL), or -1 if the string was
1683 * truncated in the buffer due to not having reached the terminating NUL.
1684 * In this way, it acts like snprintf().
1686 * bufsize MUST be greater than 0.
1688 * When processing a packet where the remaining number of bytes is less
1689 * than bufsize, an exception is not thrown if the end of the packet
1690 * is reached before the NUL is found. If no NUL is found before reaching
1691 * the end of the short packet, -1 is still returned, and the string
1692 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1693 * at the correct spot, terminating the string.
1695 * *bytes_copied will contain the number of bytes actually copied,
1696 * including the terminating-NUL.
1699 _tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
1703 guint abs_offset, junk_length;
1705 gboolean decreased_max = FALSE;
1707 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1709 /* There must at least be room for the terminating NUL. */
1710 g_assert(bufsize != 0);
1712 /* If there's no room for anything else, just return the NUL. */
1719 /* Only read to end of tvbuff, w/o throwing exception. */
1720 len = tvb_length_remaining(tvb, abs_offset);
1722 /* check_offset_length() won't throw an exception if we're
1723 * looking at the byte immediately after the end of the tvbuff. */
1725 THROW(ReportedBoundsError);
1728 /* This should not happen because check_offset_length() would
1729 * have already thrown an exception if 'offset' were out-of-bounds.
1731 g_assert(len != -1);
1734 * If we've been passed a negative number, bufsize will
1737 g_assert(bufsize <= G_MAXINT);
1739 if ((guint)len < bufsize) {
1741 decreased_max = TRUE;
1747 stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
1748 /* If NUL wasn't found, copy the data and return -1 */
1749 if (stringlen == -1) {
1750 tvb_memcpy(tvb, buffer, abs_offset, limit);
1751 if (decreased_max) {
1753 /* Add 1 for the extra NUL that we set at buffer[limit],
1754 * pretending that it was copied as part of the string. */
1755 *bytes_copied = limit + 1;
1758 *bytes_copied = limit;
1763 /* Copy the string to buffer */
1764 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
1765 *bytes_copied = stringlen + 1;
1769 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1770 * no more than bufsize number of bytes, including terminating NUL, to buffer.
1771 * Returns length of string (not including terminating NUL), or -1 if the string was
1772 * truncated in the buffer due to not having reached the terminating NUL.
1773 * In this way, it acts like snprintf().
1775 * When processing a packet where the remaining number of bytes is less
1776 * than bufsize, an exception is not thrown if the end of the packet
1777 * is reached before the NUL is found. If no NUL is found before reaching
1778 * the end of the short packet, -1 is still returned, and the string
1779 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1780 * at the correct spot, terminating the string.
1783 tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1787 return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1790 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
1791 * have a terminating NUL. If the string was truncated when copied into buffer,
1792 * a NUL is placed at the end of buffer to terminate it.
1795 tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1797 gint len, bytes_copied;
1799 len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1802 buffer[bufsize - 1] = 0;
1803 return bytes_copied - 1;
1811 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1812 * at that offset (which may be -1 for "all the way to the end of the
1813 * tvbuff"), find the end of the (putative) line that starts at the
1814 * specified offset in the tvbuff, going no further than the specified
1817 * Return the length of the line (not counting the line terminator at
1818 * the end), or, if we don't find a line terminator:
1820 * if "deseg" is true, return -1;
1822 * if "deseg" is false, return the amount of data remaining in
1825 * Set "*next_offset" to the offset of the character past the line
1826 * terminator, or past the end of the buffer if we don't find a line
1827 * terminator. (It's not set if we return -1.)
1830 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
1838 len = tvb_length_remaining(tvb, offset);
1840 * XXX - what if "len" is still -1, meaning "offset is past the
1841 * end of the tvbuff"?
1843 eob_offset = offset + len;
1846 * Look either for a CR or an LF.
1848 eol_offset = tvb_pbrk_guint8(tvb, offset, len, "\r\n");
1849 if (eol_offset == -1) {
1851 * No CR or LF - line is presumably continued in next packet.
1855 * Tell our caller we saw no EOL, so they can
1856 * try to desegment and get the entire line
1862 * Pretend the line runs to the end of the tvbuff.
1864 linelen = eob_offset - offset;
1865 *next_offset = eob_offset;
1869 * Find the number of bytes between the starting offset
1872 linelen = eol_offset - offset;
1877 if (tvb_get_guint8(tvb, eol_offset) == '\r') {
1879 * Yes - is it followed by an LF?
1881 if (eol_offset + 1 >= eob_offset) {
1883 * Dunno - the next byte isn't in this
1888 * We'll return -1, although that
1889 * runs the risk that if the line
1890 * really *is* terminated with a CR,
1891 * we won't properly dissect this
1894 * It's probably more likely that
1895 * the line ends with CR-LF than
1896 * that it ends with CR by itself.
1902 * Well, we can at least look at the next
1905 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
1907 * It's an LF; skip over the CR.
1915 * Return the offset of the character after the last
1916 * character in the line, skipping over the last character
1917 * in the line terminator.
1919 *next_offset = eol_offset + 1;
1925 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1926 * at that offset (which may be -1 for "all the way to the end of the
1927 * tvbuff"), find the end of the (putative) line that starts at the
1928 * specified offset in the tvbuff, going no further than the specified
1931 * However, treat quoted strings inside the buffer specially - don't
1932 * treat newlines in quoted strings as line terminators.
1934 * Return the length of the line (not counting the line terminator at
1935 * the end), or the amount of data remaining in the buffer if we don't
1936 * find a line terminator.
1938 * Set "*next_offset" to the offset of the character past the line
1939 * terminator, or past the end of the buffer if we don't find a line
1943 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
1946 gint cur_offset, char_offset;
1953 len = tvb_length_remaining(tvb, offset);
1955 * XXX - what if "len" is still -1, meaning "offset is past the
1956 * end of the tvbuff"?
1958 eob_offset = offset + len;
1960 cur_offset = offset;
1964 * Is this part of the string quoted?
1968 * Yes - look only for the terminating quote.
1970 char_offset = tvb_find_guint8(tvb, cur_offset, len,
1974 * Look either for a CR, an LF, or a '"'.
1976 char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
1979 if (char_offset == -1) {
1981 * Not found - line is presumably continued in
1983 * We pretend the line runs to the end of the tvbuff.
1985 linelen = eob_offset - offset;
1986 *next_offset = eob_offset;
1992 * We're processing a quoted string.
1993 * We only looked for ", so we know it's a ";
1994 * as we're processing a quoted string, it's a
2002 c = tvb_get_guint8(tvb, char_offset);
2005 * Un-quoted "; it begins a quoted
2011 * It's a CR or LF; we've found a line
2014 * Find the number of bytes between the
2015 * starting offset and the CR or LF.
2017 linelen = char_offset - offset;
2024 * Yes; is it followed by an LF?
2026 if (char_offset + 1 < eob_offset &&
2027 tvb_get_guint8(tvb, char_offset + 1)
2030 * Yes; skip over the CR.
2037 * Return the offset of the character after
2038 * the last character in the line, skipping
2039 * over the last character in the line
2040 * terminator, and quit.
2042 *next_offset = char_offset + 1;
2048 * Step past the character we found.
2050 cur_offset = char_offset + 1;
2051 if (cur_offset >= eob_offset) {
2053 * The character we found was the last character
2054 * in the tvbuff - line is presumably continued in
2056 * We pretend the line runs to the end of the tvbuff.
2058 linelen = eob_offset - offset;
2059 *next_offset = eob_offset;
2067 * Format a bunch of data from a tvbuff as bytes, returning a pointer
2068 * to the string with the formatted data.
2071 tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
2073 return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
2076 /* Find a needle tvbuff within a haystack tvbuff. */
2078 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
2080 guint haystack_abs_offset, haystack_abs_length;
2081 const guint8 *haystack_data;
2082 const guint8 *needle_data;
2083 const guint needle_len = needle_tvb->length;
2084 const guint8 *location;
2086 if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
2090 /* Get pointers to the tvbuffs' data. */
2091 haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
2092 needle_data = tvb_get_ptr(needle_tvb, 0, -1);
2094 check_offset_length(haystack_tvb, haystack_offset, -1,
2095 &haystack_abs_offset, &haystack_abs_length);
2097 location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
2098 needle_data, needle_len);
2101 return location - haystack_data;