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.27 2002/01/04 06:45:14 gram Exp $
14 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
16 * Ethereal - Network traffic analyzer
17 * By Gerald Combs <gerald@ethereal.com>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 /* The backing tvbuff_t */
49 /* The offset/length of 'tvb' to which I'm privy */
58 /* Used for quick testing to see if this
59 * is the tvbuff that a COMPOSITE is
71 gchar* ds_name; /* data source name */
73 /* The tvbuffs in which this tvbuff is a member
74 * (that is, a backing tvbuff for a TVBUFF_SUBSET
75 * or a member for a TVB_COMPOSITE) */
78 /* TVBUFF_SUBSET and TVBUFF_COMPOSITE keep track
79 * of the other tvbuff's they use */
85 /* We're either a TVBUFF_REAL_DATA or a
86 * TVBUFF_SUBSET that has a backing buffer that
87 * has real_data != NULL, or a TVBUFF_COMPOSITE
88 * which has flattened its data due to a call
93 /* Length of virtual buffer (and/or real_data). */
96 /* Reported length. */
97 guint reported_length;
99 /* Offset from beginning of first TVBUFF_REAL. */
102 /* Func to call when actually freed */
103 tvbuff_free_cb_t free_cb;
107 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
109 /* We dole out tvbuff's from this memchunk. */
110 GMemChunk *tvbuff_mem_chunk = NULL;
115 if (!tvbuff_mem_chunk)
116 tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
122 if (tvbuff_mem_chunk)
123 g_mem_chunk_destroy(tvbuff_mem_chunk);
125 tvbuff_mem_chunk = NULL;
132 tvb_init(tvbuff_t *tvb, tvbuff_type type)
134 tvb_backing_t *backing;
135 tvb_comp_t *composite;
138 tvb->initialized = FALSE;
139 tvb->usage_count = 1;
141 tvb->reported_length = 0;
143 tvb->real_data = NULL;
144 tvb->raw_offset = -1;
149 case TVBUFF_REAL_DATA:
154 backing = &tvb->tvbuffs.subset;
160 case TVBUFF_COMPOSITE:
161 composite = &tvb->tvbuffs.composite;
162 composite->tvbs = NULL;
163 composite->start_offsets = NULL;
164 composite->end_offsets = NULL;
171 tvb_new(tvbuff_type type)
175 tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
183 /* We accept a void* instead of a field_info* to satisfy CLEANUP_POP */
185 tvb_free_void(void *tvb)
187 tvb_free((tvbuff_t*)tvb);
193 tvb_free(tvbuff_t* tvb)
195 tvbuff_t *member_tvb;
196 tvb_comp_t *composite;
201 if (tvb->usage_count == 0) {
203 case TVBUFF_REAL_DATA:
205 tvb->free_cb(tvb->real_data);
208 g_free(tvb->ds_name);
212 /* This will be NULL if tvb_new_subset() fails because
213 * reported_length < -1 */
214 if (tvb->tvbuffs.subset.tvb) {
215 tvb_decrement_usage_count(tvb->tvbuffs.subset.tvb, 1);
219 * TVBUFF_SUBSET tvbuffs share a "ds_name" with
220 * the parent tvbuff, so this tvbuff's "ds_name"
221 * shouldn't be freed.
225 case TVBUFF_COMPOSITE:
226 composite = &tvb->tvbuffs.composite;
227 for (slist = composite->tvbs; slist != NULL ; slist = slist->next) {
228 member_tvb = slist->data;
229 tvb_decrement_usage_count(member_tvb, 1);
232 g_slist_free(composite->tvbs);
234 if (composite->start_offsets)
235 g_free(composite->start_offsets);
236 if (composite->end_offsets)
237 g_free(composite->end_offsets);
239 g_free(tvb->real_data);
241 g_free(tvb->ds_name);
247 g_slist_free(tvb->used_in);
250 g_chunk_free(tvb, tvbuff_mem_chunk);
255 tvb_increment_usage_count(tvbuff_t* tvb, guint count)
257 tvb->usage_count += count;
259 return tvb->usage_count;
263 tvb_decrement_usage_count(tvbuff_t* tvb, guint count)
265 if (tvb->usage_count <= count) {
266 tvb->usage_count = 1;
271 tvb->usage_count -= count;
272 return tvb->usage_count;
278 tvb_free_chain(tvbuff_t* tvb)
282 /* Recursively call tvb_free_chain() */
283 for (slist = tvb->used_in; slist != NULL ; slist = slist->next) {
284 tvb_free_chain( (tvbuff_t*)slist->data );
287 /* Stop the recursion */
294 tvb_set_free_cb(tvbuff_t* tvb, tvbuff_free_cb_t func)
296 g_assert(tvb->type == TVBUFF_REAL_DATA);
301 add_to_used_in_list(tvbuff_t *tvb, tvbuff_t *used_in)
303 tvb->used_in = g_slist_prepend(tvb->used_in, used_in);
304 tvb_increment_usage_count(tvb, 1);
308 tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
310 g_assert(parent->initialized);
311 g_assert(child->initialized);
312 g_assert(child->type == TVBUFF_REAL_DATA);
313 add_to_used_in_list(parent, child);
317 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
319 g_assert(tvb->type == TVBUFF_REAL_DATA);
320 g_assert(!tvb->initialized);
322 if (reported_length < -1) {
323 THROW(ReportedBoundsError);
326 tvb->real_data = (gpointer) data;
327 tvb->length = length;
328 tvb->reported_length = reported_length;
329 tvb->initialized = TRUE;
333 tvb_new_real_data(const guint8* data, guint length, gint reported_length, const gchar* ds_name)
337 tvb = tvb_new(TVBUFF_REAL_DATA);
339 CLEANUP_PUSH(tvb_free_void, tvb);
341 tvb_set_real_data(tvb, data, length, reported_length);
343 /* set the data source name */
344 tvb->ds_name = g_strdup( ds_name);
351 /* Computes the absolute offset and length based on a possibly-negative offset
352 * and a length that is possible -1 (which means "to the end of the data").
353 * Returns TRUE/FALSE indicating whether the offset is in bounds or
354 * not. The integer ptrs are modified with the new offset and length.
355 * No exception is thrown.
357 * XXX - we return TRUE, not FALSE, if the offset is positive and right
358 * after the end of the tvbuff (i.e., equal to the length). We do this
359 * so that a dissector constructing a subset tvbuff for the next protocol
360 * will get a zero-length tvbuff, not an exception, if there's no data
361 * left for the next protocol - we want the next protocol to be the one
362 * that gets an exception, so the error is reported as an error in that
363 * protocol rather than the containing protocol. */
365 compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
366 guint *offset_ptr, guint *length_ptr, int *exception)
368 g_assert(offset_ptr);
369 g_assert(length_ptr);
371 /* Compute the offset */
373 /* Positive offset - relative to the beginning of the packet. */
374 if ((guint) offset > tvb->reported_length) {
376 *exception = ReportedBoundsError;
380 else if ((guint) offset > tvb->length) {
382 *exception = BoundsError;
387 *offset_ptr = offset;
391 /* Negative offset - relative to the end of the packet. */
392 if ((guint) -offset > tvb->reported_length) {
394 *exception = ReportedBoundsError;
398 else if ((guint) -offset > tvb->length) {
400 *exception = BoundsError;
405 *offset_ptr = tvb->length + offset;
409 /* Compute the length */
413 else if (length == -1) {
414 *length_ptr = tvb->length - *offset_ptr;
417 *length_ptr = length;
425 check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
426 guint *offset_ptr, guint *length_ptr, int *exception)
428 g_assert(tvb->initialized);
430 if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
434 if (*offset_ptr + *length_ptr <= tvb->length) {
437 else if (*offset_ptr + *length_ptr <= tvb->reported_length) {
439 *exception = BoundsError;
445 *exception = ReportedBoundsError;
450 g_assert_not_reached();
453 /* Checks (+/-) offset and length and throws BoundsError if
454 * either is out of bounds. Sets integer ptrs to the new offset
457 check_offset_length(tvbuff_t *tvb, gint offset, gint length,
458 guint *offset_ptr, guint *length_ptr)
466 if (!check_offset_length_no_exception(tvb, offset, length, offset_ptr, length_ptr, &exception)) {
467 g_assert(exception > 0);
475 tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
476 gint backing_offset, gint backing_length, gint reported_length)
478 g_assert(tvb->type == TVBUFF_SUBSET);
479 g_assert(!tvb->initialized);
481 if (reported_length < -1) {
482 THROW(ReportedBoundsError);
485 check_offset_length(backing, backing_offset, backing_length,
486 &tvb->tvbuffs.subset.offset,
487 &tvb->tvbuffs.subset.length);
489 tvb->tvbuffs.subset.tvb = backing;
490 tvb->length = tvb->tvbuffs.subset.length;
492 if (reported_length == -1) {
493 tvb->reported_length = backing->reported_length - tvb->tvbuffs.subset.offset;
496 tvb->reported_length = reported_length;
498 tvb->initialized = TRUE;
499 add_to_used_in_list(backing, tvb);
501 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
502 * then we can point directly to our starting offset in that buffer */
503 if (backing->real_data != NULL) {
504 tvb->real_data = backing->real_data + tvb->tvbuffs.subset.offset;
510 tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
514 tvb = tvb_new(TVBUFF_SUBSET);
516 CLEANUP_PUSH(tvb_free_void, tvb);
518 tvb_set_subset(tvb, backing, backing_offset, backing_length, reported_length);
520 tvb->ds_name = backing->ds_name;
527 tvb_composite_append(tvbuff_t* tvb, tvbuff_t* member)
529 tvb_comp_t *composite;
531 g_assert(!tvb->initialized);
532 composite = &tvb->tvbuffs.composite;
533 composite->tvbs = g_slist_append( composite->tvbs, member );
534 add_to_used_in_list(member, tvb);
538 tvb_composite_prepend(tvbuff_t* tvb, tvbuff_t* member)
540 tvb_comp_t *composite;
542 g_assert(!tvb->initialized);
543 composite = &tvb->tvbuffs.composite;
544 composite->tvbs = g_slist_prepend( composite->tvbs, member );
545 add_to_used_in_list(member, tvb);
549 tvb_new_composite(void)
551 return tvb_new(TVBUFF_COMPOSITE);
555 tvb_composite_finalize(tvbuff_t* tvb)
559 tvbuff_t *member_tvb;
560 tvb_comp_t *composite;
563 g_assert(!tvb->initialized);
564 g_assert(tvb->length == 0);
566 composite = &tvb->tvbuffs.composite;
567 num_members = g_slist_length(composite->tvbs);
569 composite->start_offsets = g_new(guint, num_members);
570 composite->end_offsets = g_new(guint, num_members);
572 for (slist = composite->tvbs; slist != NULL; slist = slist->next) {
573 g_assert((guint) i < num_members);
574 member_tvb = slist->data;
575 composite->start_offsets[i] = tvb->length;
576 tvb->length += member_tvb->length;
577 composite->end_offsets[i] = tvb->length - 1;
581 tvb->initialized = TRUE;
587 tvb_length(tvbuff_t* tvb)
589 g_assert(tvb->initialized);
595 tvb_length_remaining(tvbuff_t *tvb, gint offset)
597 guint abs_offset, abs_length;
599 g_assert(tvb->initialized);
601 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
611 /* Validates that 'length' bytes are available starting from
612 * offset (pos/neg). Does not throw BoundsError exception. */
614 tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
616 guint abs_offset, abs_length;
618 g_assert(tvb->initialized);
620 if (!compute_offset_length(tvb, offset, length, &abs_offset, &abs_length, NULL))
623 if (abs_offset + abs_length <= tvb->length) {
632 tvb_offset_exists(tvbuff_t *tvb, gint offset)
634 guint abs_offset, abs_length;
636 g_assert(tvb->initialized);
637 if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL))
640 if (abs_offset < tvb->length) {
649 tvb_reported_length(tvbuff_t* tvb)
651 g_assert(tvb->initialized);
653 return tvb->reported_length;
657 tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
659 guint abs_offset, abs_length;
661 g_assert(tvb->initialized);
663 if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
664 if (tvb->reported_length >= abs_offset)
665 return tvb->reported_length - abs_offset;
674 /* Set the reported length of a tvbuff to a given value; used for protocols
675 whose headers contain an explicit length and where the calling
676 dissector's payload may include padding as well as the packet for
679 Also adjusts the data length. */
681 tvb_set_reported_length(tvbuff_t* tvb, guint reported_length)
683 g_assert(tvb->initialized);
685 if (reported_length > tvb->reported_length)
686 THROW(ReportedBoundsError);
688 tvb->reported_length = reported_length;
689 if (reported_length < tvb->length)
690 tvb->length = reported_length;
695 first_real_data_ptr(tvbuff_t *tvb)
700 case TVBUFF_REAL_DATA:
701 return tvb->real_data;
703 member = tvb->tvbuffs.subset.tvb;
704 return first_real_data_ptr(member);
705 case TVBUFF_COMPOSITE:
706 member = tvb->tvbuffs.composite.tvbs->data;
707 return first_real_data_ptr(member);
710 g_assert_not_reached();
715 offset_from_real_beginning(tvbuff_t *tvb, int counter)
720 case TVBUFF_REAL_DATA:
723 member = tvb->tvbuffs.subset.tvb;
724 return offset_from_real_beginning(member, counter + tvb->tvbuffs.subset.offset);
725 case TVBUFF_COMPOSITE:
726 member = tvb->tvbuffs.composite.tvbs->data;
727 return offset_from_real_beginning(member, counter);
730 g_assert_not_reached();
735 tvb_raw_offset(tvbuff_t *tvb)
737 if (tvb->raw_offset == -1) {
738 tvb->raw_offset = offset_from_real_beginning(tvb, 0);
740 return tvb->raw_offset;
744 composite_ensure_contiguous(tvbuff_t *tvb, guint abs_offset, guint abs_length)
746 guint i, num_members;
747 tvb_comp_t *composite;
748 tvbuff_t *member_tvb = NULL;
749 guint member_offset, member_length;
752 g_assert(tvb->type == TVBUFF_COMPOSITE);
754 /* Maybe the range specified by offset/length
755 * is contiguous inside one of the member tvbuffs */
756 composite = &tvb->tvbuffs.composite;
757 num_members = g_slist_length(composite->tvbs);
759 for (i = 0; i < num_members; i++) {
760 if (abs_offset <= composite->end_offsets[i]) {
761 slist = g_slist_nth(composite->tvbs, i);
762 member_tvb = slist->data;
766 g_assert(member_tvb);
768 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
769 abs_length, &member_offset, &member_length, NULL)) {
771 g_assert(!tvb->real_data);
772 return ensure_contiguous(member_tvb, member_offset, member_length);
775 tvb->real_data = tvb_memdup(tvb, 0, -1);
776 return tvb->real_data + abs_offset;
779 g_assert_not_reached();
784 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length)
786 guint abs_offset, abs_length;
788 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
790 if (tvb->real_data) {
791 return tvb->real_data + abs_offset;
795 case TVBUFF_REAL_DATA:
796 g_assert_not_reached();
798 return ensure_contiguous(tvb->tvbuffs.subset.tvb,
799 abs_offset - tvb->tvbuffs.subset.offset,
801 case TVBUFF_COMPOSITE:
802 return composite_ensure_contiguous(tvb, abs_offset, abs_length);
806 g_assert_not_reached();
811 guint8_find(const guint8* haystack, size_t haystacklen, guint8 needle)
816 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
826 guint8_pbrk(const guint8* haystack, size_t haystacklen, guint8 *needles)
830 guint8 item, *needlep, needle;
832 for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
835 while ((needle = *needlep) != '\0') {
847 /************** ACCESSORS **************/
850 composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, guint abs_length)
852 guint i, num_members;
853 tvb_comp_t *composite;
854 tvbuff_t *member_tvb = NULL;
855 guint member_offset, member_length;
859 g_assert(tvb->type == TVBUFF_COMPOSITE);
861 /* Maybe the range specified by offset/length
862 * is contiguous inside one of the member tvbuffs */
863 composite = &tvb->tvbuffs.composite;
864 num_members = g_slist_length(composite->tvbs);
866 for (i = 0; i < num_members; i++) {
867 if (abs_offset <= composite->end_offsets[i]) {
868 slist = g_slist_nth(composite->tvbs, i);
869 member_tvb = slist->data;
873 g_assert(member_tvb);
875 if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
876 abs_length, &member_offset, &member_length, NULL)) {
878 g_assert(!tvb->real_data);
879 return tvb_memcpy(member_tvb, target, member_offset, member_length);
882 /* The requested data is non-contiguous inside
883 * the member tvb. We have to memcpy() the part that's in the member tvb,
884 * then iterate across the other member tvb's, copying their portions
885 * until we have copied all data.
887 retval = compute_offset_length(member_tvb, abs_offset - composite->start_offsets[i], -1,
888 &member_offset, &member_length, NULL);
891 tvb_memcpy(member_tvb, target, member_offset, member_length);
892 abs_offset += member_length;
893 abs_length -= member_length;
896 if (abs_length > 0) {
897 composite_memcpy(tvb, target + member_length, abs_offset, abs_length);
903 g_assert_not_reached();
908 tvb_memcpy(tvbuff_t *tvb, guint8* target, gint offset, gint length)
910 guint abs_offset, abs_length;
912 g_assert(length >= -1);
913 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
915 if (tvb->real_data) {
916 return (guint8*) memcpy(target, tvb->real_data + abs_offset, abs_length);
920 case TVBUFF_REAL_DATA:
921 g_assert_not_reached();
924 return tvb_memcpy(tvb->tvbuffs.subset.tvb, target,
925 abs_offset - tvb->tvbuffs.subset.offset,
928 case TVBUFF_COMPOSITE:
929 return composite_memcpy(tvb, target, offset, length);
932 g_assert_not_reached();
938 tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
940 guint abs_offset, abs_length;
943 check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
945 duped = g_malloc(abs_length);
946 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
952 tvb_get_ptr(tvbuff_t *tvb, gint offset, gint length)
954 return ensure_contiguous(tvb, offset, length);
958 tvb_get_guint8(tvbuff_t *tvb, gint offset)
962 ptr = ensure_contiguous(tvb, offset, sizeof(guint8));
967 tvb_get_ntohs(tvbuff_t *tvb, gint offset)
971 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
976 tvb_get_ntoh24(tvbuff_t *tvb, gint offset)
980 ptr = ensure_contiguous(tvb, offset, 3);
985 tvb_get_ntohl(tvbuff_t *tvb, gint offset)
989 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
994 tvb_get_letohs(tvbuff_t *tvb, gint offset)
998 ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1003 tvb_get_letoh24(tvbuff_t *tvb, gint offset)
1007 ptr = ensure_contiguous(tvb, offset, 3);
1008 return pletoh24(ptr);
1012 tvb_get_letohl(tvbuff_t *tvb, gint offset)
1016 ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1017 return pletohl(ptr);
1020 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1021 * at most maxlength number of bytes; if maxlength is -1, searches to
1023 * Returns the offset of the found needle, or -1 if not found.
1024 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1025 * in that case, -1 will be returned if the boundary is reached before
1026 * finding needle. */
1028 tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
1030 const guint8 *result;
1031 guint abs_offset, junk_length;
1035 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1037 /* Only search to end of tvbuff, w/o throwing exception. */
1038 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1039 if (maxlength == -1) {
1040 /* No maximum length specified; search to end of tvbuff. */
1043 else if (tvbufflen < (guint) maxlength) {
1044 /* Maximum length goes past end of tvbuff; search to end
1049 /* Maximum length doesn't go past end of tvbuff; search
1054 /* If we have real data, perform our search now. */
1055 if (tvb->real_data) {
1056 result = guint8_find(tvb->real_data + abs_offset, limit, needle);
1057 if (result == NULL) {
1061 return result - tvb->real_data;
1066 case TVBUFF_REAL_DATA:
1067 g_assert_not_reached();
1070 return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1071 abs_offset - tvb->tvbuffs.subset.offset,
1074 case TVBUFF_COMPOSITE:
1075 g_assert_not_reached();
1076 /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1079 g_assert_not_reached();
1083 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1084 * Searches at most maxlength number of bytes; if maxlength is -1, searches
1086 * Returns the offset of the found needle, or -1 if not found.
1087 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1088 * in that case, -1 will be returned if the boundary is reached before
1089 * finding needle. */
1091 tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 *needles)
1093 const guint8 *result;
1094 guint abs_offset, junk_length;
1098 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1100 /* Only search to end of tvbuff, w/o throwing exception. */
1101 tvbufflen = tvb_length_remaining(tvb, abs_offset);
1102 if (maxlength == -1) {
1103 /* No maximum length specified; search to end of tvbuff. */
1106 else if (tvbufflen < (guint) maxlength) {
1107 /* Maximum length goes past end of tvbuff; search to end
1112 /* Maximum length doesn't go past end of tvbuff; search
1117 /* If we have real data, perform our search now. */
1118 if (tvb->real_data) {
1119 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
1120 if (result == NULL) {
1124 return result - tvb->real_data;
1129 case TVBUFF_REAL_DATA:
1130 g_assert_not_reached();
1133 return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
1134 abs_offset - tvb->tvbuffs.subset.offset,
1137 case TVBUFF_COMPOSITE:
1138 g_assert_not_reached();
1139 /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
1142 g_assert_not_reached();
1146 /* Find size of stringz (NUL-terminated string) by looking for terminating
1147 * NUL. The size of the string includes the terminating NUL.
1149 * If the NUL isn't found, it throws the appropriate exception.
1152 tvb_strsize(tvbuff_t *tvb, gint offset)
1154 guint abs_offset, junk_length;
1157 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1158 nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1159 if (nul_offset == -1) {
1161 * OK, we hit the end of the tvbuff, so we should throw
1164 * Did we hit the end of the captured data, or the end
1165 * of the actual data? If there's less captured data
1166 * than actual data, we presumably hit the end of the
1167 * captured data, otherwise we hit the end of the actual
1170 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
1173 THROW(ReportedBoundsError);
1176 return (nul_offset - abs_offset) + 1;
1179 /* Find length of string by looking for end of string ('\0'), up to
1180 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1182 * Returns -1 if 'maxlength' reached before finding EOS. */
1184 tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
1187 guint abs_offset, junk_length;
1189 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1191 result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1193 if (result_offset == -1) {
1197 return result_offset - abs_offset;
1202 * Implement strneql etc
1206 * Call strncmp after checking if enough chars left, returning 0 if
1207 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1210 tvb_strneql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1214 ptr = ensure_contiguous(tvb, offset, size);
1217 int cmp = strncmp(ptr, str, size);
1220 * Return 0 if equal, -1 otherwise.
1222 return (cmp == 0 ? 0 : -1);
1225 * Not enough characters in the tvbuff to match the
1233 * Call strncasecmp after checking if enough chars left, returning 0 if
1234 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1237 tvb_strncaseeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1241 ptr = ensure_contiguous(tvb, offset, size);
1244 int cmp = strncasecmp(ptr, str, size);
1247 * Return 0 if equal, -1 otherwise.
1249 return (cmp == 0 ? 0 : -1);
1252 * Not enough characters in the tvbuff to match the
1260 * Call memcmp after checking if enough chars left, returning 0 if
1261 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1264 tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1268 ptr = ensure_contiguous(tvb, offset, size);
1271 int cmp = memcmp(ptr, str, size);
1274 * Return 0 if equal, -1 otherwise.
1276 return (cmp == 0 ? 0 : -1);
1279 * Not enough characters in the tvbuff to match the
1287 * Format the data in the tvb from offset for length ...
1291 tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
1296 if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1298 len = tvb_length_remaining(tvb, offset);
1299 ptr = ensure_contiguous(tvb, offset, len);
1303 return format_text(ptr, len);
1307 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1308 * no more than maxlength number of bytes, including terminating NUL, to buffer.
1309 * Returns length of string (not including terminating NUL), or -1 if the string was
1310 * truncated in the buffer due to not having reached the terminating NUL.
1311 * In this way, it acts like snprintf().
1314 tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint maxlength, guint8* buffer)
1317 guint abs_offset, junk_length;
1320 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1322 if (maxlength == 0) {
1327 /* Only copy to end of tvbuff, w/o throwing exception. */
1328 len = tvb_length_remaining(tvb, abs_offset);
1330 /* This should not happen because check_offset_length() would
1331 * have already thrown an exception if 'offset' were out-of-bounds.
1333 g_assert(len != -1);
1335 if ((guint)len < maxlength) {
1336 limit = maxlength - (tvb_length(tvb) - abs_offset);
1342 stringlen = tvb_strnlen(tvb, abs_offset, limit);
1344 /* If NUL wasn't found, copy the data and return -1 */
1345 if (stringlen == -1) {
1346 tvb_memcpy(tvb, buffer, abs_offset, limit);
1350 /* Copy the string to buffer */
1351 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
1355 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
1356 * have a terminating NUL. If the string was truncated when copied into buffer,
1357 * a NUL is placed at the end of buffer to terminate it.
1360 tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint maxlength, guint8* buffer)
1364 len = tvb_get_nstringz(tvb, offset, maxlength, buffer);
1367 buffer[maxlength] = 0;
1368 return maxlength - 1;
1376 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1377 * at that offset (which may be -1 for "all the way to the end of the
1378 * tvbuff"), find the end of the (putative) line that starts at the
1379 * specified offset in the tvbuff, going no further than the specified
1382 * Return the length of the line (not counting the line terminator at
1383 * the end), or the amount of data remaining in the buffer if we don't
1384 * find a line terminator.
1386 * Set "*next_offset" to the offset of the character past the line
1387 * terminator, or past the end of the buffer if we don't find a line
1391 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset)
1398 len = tvb_length_remaining(tvb, offset);
1400 * XXX - what if "len" is still -1, meaning "offset is past the
1401 * end of the tvbuff"?
1403 eob_offset = offset + len;
1406 * Look either for a CR or an LF.
1408 eol_offset = tvb_pbrk_guint8(tvb, offset, len, "\r\n");
1409 if (eol_offset == -1) {
1411 * No CR or LF - line is presumably continued in next packet.
1412 * We pretend the line runs to the end of the tvbuff.
1414 linelen = eob_offset - offset;
1415 *next_offset = eob_offset;
1418 * Find the number of bytes between the starting offset
1421 linelen = eol_offset - offset;
1426 if (tvb_get_guint8(tvb, eol_offset) == '\r') {
1428 * Yes - is it followed by an LF?
1430 if (eol_offset + 1 < eob_offset &&
1431 tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
1433 * Yes; skip over the CR.
1440 * Return the offset of the character after the last
1441 * character in the line, skipping over the last character
1442 * in the line terminator.
1444 *next_offset = eol_offset + 1;
1450 * Given a tvbuff, an offset into the tvbuff, and a length that starts
1451 * at that offset (which may be -1 for "all the way to the end of the
1452 * tvbuff"), find the end of the (putative) line that starts at the
1453 * specified offset in the tvbuff, going no further than the specified
1456 * However, treat quoted strings inside the buffer specially - don't
1457 * treat newlines in quoted strings as line terminators.
1459 * Return the length of the line (not counting the line terminator at
1460 * the end), or the amount of data remaining in the buffer if we don't
1461 * find a line terminator.
1463 * Set "*next_offset" to the offset of the character past the line
1464 * terminator, or past the end of the buffer if we don't find a line
1468 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
1471 gint cur_offset, char_offset;
1478 len = tvb_length_remaining(tvb, offset);
1480 * XXX - what if "len" is still -1, meaning "offset is past the
1481 * end of the tvbuff"?
1483 eob_offset = offset + len;
1485 cur_offset = offset;
1489 * Is this part of the string quoted?
1493 * Yes - look only for the terminating quote.
1495 char_offset = tvb_find_guint8(tvb, cur_offset, len,
1499 * Look either for a CR, an LF, or a '"'.
1501 char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
1504 if (char_offset == -1) {
1506 * Not found - line is presumably continued in
1508 * We pretend the line runs to the end of the tvbuff.
1510 linelen = eob_offset - offset;
1511 *next_offset = eob_offset;
1517 * We're processing a quoted string.
1518 * We only looked for ", so we know it's a ";
1519 * as we're processing a quoted string, it's a
1527 c = tvb_get_guint8(tvb, char_offset);
1530 * Un-quoted "; it begins a quoted
1536 * It's a CR or LF; we've found a line
1539 * Find the number of bytes between the
1540 * starting offset and the CR or LF.
1542 linelen = char_offset - offset;
1549 * Yes; is it followed by an LF?
1551 if (char_offset + 1 < eob_offset &&
1552 tvb_get_guint8(tvb, char_offset + 1)
1555 * Yes; skip over the CR.
1562 * Return the offset of the character after
1563 * the last character in the line, skipping
1564 * over the last character in the line
1565 * terminator, and quit.
1567 *next_offset = char_offset + 1;
1573 * Step past the character we found.
1575 cur_offset = char_offset + 1;
1576 if (cur_offset >= eob_offset) {
1578 * The character we found was the last character
1579 * in the tvbuff - line is presumably continued in
1581 * We pretend the line runs to the end of the tvbuff.
1583 linelen = eob_offset - offset;
1584 *next_offset = eob_offset;
1592 * Format a bunch of data from a tvbuff as bytes, returning a pointer
1593 * to the string with the formatted data.
1596 tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
1598 return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
1602 tvb_get_name(tvbuff_t* tvb)
1604 return tvb->ds_name;