Add a "contains" operator for byte-strings, strings, and tvbuffs (protocols).
[obnox/wireshark/wip.git] / epan / tvbuff.c
1 /* tvbuff.c
2  *
3  * Testy, Virtual(-izable) Buffer of guint8*'s
4  *
5  * "Testy" -- the buffer gets mad when an attempt to access data
6  *              beyond the bounds of the buffer. An exception is thrown.
7  *
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
10  *              other tvbuffs.
11  *
12  * $Id: tvbuff.c,v 1.49 2003/08/27 15:23:02 gram Exp $
13  *
14  * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
15  *
16  * Code to convert IEEE floating point formats to native floating point
17  * derived from code Copyright (c) Ashok Narayanan, 2000
18  *
19  * Ethereal - Network traffic analyzer
20  * By Gerald Combs <gerald@ethereal.com>
21  * Copyright 1998 Gerald Combs
22  *
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.
27  *
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.
32  *
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.
36  */
37
38 #ifdef HAVE_CONFIG_H
39 # include "config.h"
40 #endif
41
42 #include <string.h>
43
44 #include "pint.h"
45 #include "tvbuff.h"
46 #include "strutil.h"
47
48 typedef struct {
49         /* The backing tvbuff_t */
50         tvbuff_t        *tvb;
51
52         /* The offset/length of 'tvb' to which I'm privy */
53         guint           offset;
54         guint           length;
55
56 } tvb_backing_t;
57
58 typedef struct {
59         GSList          *tvbs;
60
61         /* Used for quick testing to see if this
62          * is the tvbuff that a COMPOSITE is
63          * interested in. */
64         guint           *start_offsets;
65         guint           *end_offsets;
66
67 } tvb_comp_t;
68
69 struct tvbuff {
70         /* Record-keeping */
71         tvbuff_type             type;
72         gboolean                initialized;
73         guint                   usage_count;
74         tvbuff_t*               ds_tvb;   /* data source top-level tvbuff */
75
76         /* The tvbuffs in which this tvbuff is a member
77          * (that is, a backing tvbuff for a TVBUFF_SUBSET
78          * or a member for a TVB_COMPOSITE) */
79         GSList                  *used_in;
80
81         /* TVBUFF_SUBSET and TVBUFF_COMPOSITE keep track
82          * of the other tvbuff's they use */
83         union {
84                 tvb_backing_t   subset;
85                 tvb_comp_t      composite;
86         } tvbuffs;
87
88         /* We're either a TVBUFF_REAL_DATA or a
89          * TVBUFF_SUBSET that has a backing buffer that
90          * has real_data != NULL, or a TVBUFF_COMPOSITE
91          * which has flattened its data due to a call
92          * to tvb_get_ptr().
93          */
94         guint8                  *real_data;
95
96         /* Length of virtual buffer (and/or real_data). */
97         guint                   length;
98
99         /* Reported length. */
100         guint                   reported_length;
101
102         /* Offset from beginning of first TVBUFF_REAL. */
103         gint                    raw_offset;
104
105         /* Func to call when actually freed */
106         tvbuff_free_cb_t        free_cb;
107 };
108
109 static guint8*
110 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
111                 int *exception);
112
113 static guint8*
114 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length);
115
116 /* We dole out tvbuff's from this memchunk. */
117 GMemChunk *tvbuff_mem_chunk = NULL;
118
119 void
120 tvbuff_init(void)
121 {
122         if (!tvbuff_mem_chunk)
123                 tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
124 }
125
126 void
127 tvbuff_cleanup(void)
128 {
129         if (tvbuff_mem_chunk)
130                 g_mem_chunk_destroy(tvbuff_mem_chunk);
131
132         tvbuff_mem_chunk = NULL;
133 }
134
135
136
137
138 static void
139 tvb_init(tvbuff_t *tvb, tvbuff_type type)
140 {
141         tvb_backing_t   *backing;
142         tvb_comp_t      *composite;
143
144         tvb->type               = type;
145         tvb->initialized        = FALSE;
146         tvb->usage_count        = 1;
147         tvb->length             = 0;
148         tvb->reported_length    = 0;
149         tvb->free_cb            = NULL;
150         tvb->real_data          = NULL;
151         tvb->raw_offset         = -1;
152         tvb->used_in            = NULL;
153         tvb->ds_tvb             = NULL;
154
155         switch(type) {
156                 case TVBUFF_REAL_DATA:
157                         /* Nothing */
158                         break;
159
160                 case TVBUFF_SUBSET:
161                         backing = &tvb->tvbuffs.subset;
162                         backing->tvb    = NULL;
163                         backing->offset = 0;
164                         backing->length = 0;
165                         break;
166
167                 case TVBUFF_COMPOSITE:
168                         composite = &tvb->tvbuffs.composite;
169                         composite->tvbs                 = NULL;
170                         composite->start_offsets        = NULL;
171                         composite->end_offsets          = NULL;
172                         break;
173         }
174 }
175
176
177 tvbuff_t*
178 tvb_new(tvbuff_type type)
179 {
180         tvbuff_t        *tvb;
181
182         tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
183         g_assert(tvb);
184
185         tvb_init(tvb, type);
186
187         return tvb;
188 }
189
190 /* We accept a void* instead of a field_info* to satisfy CLEANUP_POP */
191 static void
192 tvb_free_void(void *tvb)
193 {
194         tvb_free((tvbuff_t*)tvb);
195 }
196
197
198
199 void
200 tvb_free(tvbuff_t* tvb)
201 {
202         tvbuff_t        *member_tvb;
203         tvb_comp_t      *composite;
204         GSList          *slist;
205
206         tvb->usage_count--;
207
208         if (tvb->usage_count == 0) {
209                 switch (tvb->type) {
210                 case TVBUFF_REAL_DATA:
211                         if (tvb->free_cb) {
212                                 tvb->free_cb(tvb->real_data);
213                         }
214                         break;
215
216                 case TVBUFF_SUBSET:
217                         /* This will be NULL if tvb_new_subset() fails because
218                          * reported_length < -1 */
219                         if (tvb->tvbuffs.subset.tvb) {
220                                 tvb_decrement_usage_count(tvb->tvbuffs.subset.tvb, 1);
221                         }
222                         break;
223
224                 case TVBUFF_COMPOSITE:
225                         composite = &tvb->tvbuffs.composite;
226                         for (slist = composite->tvbs; slist != NULL ; slist = slist->next) {
227                                 member_tvb = slist->data;
228                                 tvb_decrement_usage_count(member_tvb, 1);
229                         }
230
231                         g_slist_free(composite->tvbs);
232
233                         if (composite->start_offsets)
234                                 g_free(composite->start_offsets);
235                         if (composite->end_offsets)
236                                 g_free(composite->end_offsets);
237                         if (tvb->real_data)
238                                 g_free(tvb->real_data);
239
240                         break;
241                 }
242
243                 if (tvb->used_in) {
244                         g_slist_free(tvb->used_in);
245                 }
246
247                 g_chunk_free(tvb, tvbuff_mem_chunk);
248         }
249 }
250
251 guint
252 tvb_increment_usage_count(tvbuff_t* tvb, guint count)
253 {
254         tvb->usage_count += count;
255
256         return tvb->usage_count;
257 }
258
259 guint
260 tvb_decrement_usage_count(tvbuff_t* tvb, guint count)
261 {
262         if (tvb->usage_count <= count) {
263                 tvb->usage_count = 1;
264                 tvb_free(tvb);
265                 return 0;
266         }
267         else {
268                 tvb->usage_count -= count;
269                 return tvb->usage_count;
270         }
271
272 }
273
274 void
275 tvb_free_chain(tvbuff_t* tvb)
276 {
277         GSList          *slist;
278
279         /* Recursively call tvb_free_chain() */
280         for (slist = tvb->used_in; slist != NULL ; slist = slist->next) {
281                 tvb_free_chain( (tvbuff_t*)slist->data );
282         }
283
284         /* Stop the recursion */
285         tvb_free(tvb);
286 }
287
288
289
290 void
291 tvb_set_free_cb(tvbuff_t* tvb, tvbuff_free_cb_t func)
292 {
293         g_assert(tvb->type == TVBUFF_REAL_DATA);
294         tvb->free_cb = func;
295 }
296
297 static void
298 add_to_used_in_list(tvbuff_t *tvb, tvbuff_t *used_in)
299 {
300         tvb->used_in = g_slist_prepend(tvb->used_in, used_in);
301         tvb_increment_usage_count(tvb, 1);
302 }
303
304 void
305 tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
306 {
307         g_assert(parent->initialized);
308         g_assert(child->initialized);
309         g_assert(child->type == TVBUFF_REAL_DATA);
310         add_to_used_in_list(parent, child);
311 }
312
313 void
314 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, guint length, gint reported_length)
315 {
316         g_assert(tvb->type == TVBUFF_REAL_DATA);
317         g_assert(!tvb->initialized);
318
319         if (reported_length < -1) {
320                 THROW(ReportedBoundsError);
321         }
322
323         tvb->real_data          = (gpointer) data;
324         tvb->length             = length;
325         tvb->reported_length    = reported_length;
326         tvb->initialized        = TRUE;
327 }
328
329 tvbuff_t*
330 tvb_new_real_data(const guint8* data, guint length, gint reported_length)
331 {
332         tvbuff_t        *tvb;
333
334         tvb = tvb_new(TVBUFF_REAL_DATA);
335
336         CLEANUP_PUSH(tvb_free_void, tvb);
337
338         tvb_set_real_data(tvb, data, length, reported_length);
339
340         /*
341          * This is the top-level real tvbuff for this data source,
342          * so its data source tvbuff is itself.
343          */
344         tvb->ds_tvb = tvb;
345
346         CLEANUP_POP;
347
348         return tvb;
349 }
350
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.
356  *
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.  */
364 static gboolean
365 compute_offset_length(tvbuff_t *tvb, gint offset, gint length,
366                 guint *offset_ptr, guint *length_ptr, int *exception)
367 {
368         g_assert(offset_ptr);
369         g_assert(length_ptr);
370
371         /* Compute the offset */
372         if (offset >= 0) {
373                 /* Positive offset - relative to the beginning of the packet. */
374                 if ((guint) offset > tvb->reported_length) {
375                         if (exception) {
376                                 *exception = ReportedBoundsError;
377                         }
378                         return FALSE;
379                 }
380                 else if ((guint) offset > tvb->length) {
381                         if (exception) {
382                                 *exception = BoundsError;
383                         }
384                         return FALSE;
385                 }
386                 else {
387                         *offset_ptr = offset;
388                 }
389         }
390         else {
391                 /* Negative offset - relative to the end of the packet. */
392                 if ((guint) -offset > tvb->reported_length) {
393                         if (exception) {
394                                 *exception = ReportedBoundsError;
395                         }
396                         return FALSE;
397                 }
398                 else if ((guint) -offset > tvb->length) {
399                         if (exception) {
400                                 *exception = BoundsError;
401                         }
402                         return FALSE;
403                 }
404                 else {
405                         *offset_ptr = tvb->length + offset;
406                 }
407         }
408
409         /* Compute the length */
410         if (length < -1) {
411                 return FALSE;
412         }
413         else if (length == -1) {
414                 *length_ptr = tvb->length - *offset_ptr;
415         }
416         else {
417                 *length_ptr = length;
418         }
419
420         return TRUE;
421 }
422
423
424 static gboolean
425 check_offset_length_no_exception(tvbuff_t *tvb, gint offset, gint length,
426                 guint *offset_ptr, guint *length_ptr, int *exception)
427 {
428         guint   end_offset;
429
430         g_assert(tvb->initialized);
431
432         if (!compute_offset_length(tvb, offset, length, offset_ptr, length_ptr, exception)) {
433                 return FALSE;
434         }
435
436         /*
437          * Compute the offset of the first byte past the length.
438          */
439         end_offset = *offset_ptr + *length_ptr;
440
441         /*
442          * Check for an overflow, and clamp "end_offset" at the maximum
443          * if we got an overflow - that should force us to indicate that
444          * we're past the end of the tvbuff.
445          */
446         if (end_offset < *offset_ptr)
447                 end_offset = UINT_MAX;
448
449         /*
450          * Check whether that offset goes more than one byte past the
451          * end of the buffer.
452          *
453          * If not, return TRUE; otherwise, return FALSE and, if "exception"
454          * is non-null, return the appropriate exception through it.
455          */
456         if (end_offset <= tvb->length) {
457                 return TRUE;
458         }
459         else if (end_offset <= tvb->reported_length) {
460                 if (exception) {
461                         *exception = BoundsError;
462                 }
463                 return FALSE;
464         }
465         else {
466                 if (exception) {
467                         *exception = ReportedBoundsError;
468                 }
469                 return FALSE;
470         }
471
472         g_assert_not_reached();
473 }
474
475 /* Checks (+/-) offset and length and throws an exception if
476  * either is out of bounds. Sets integer ptrs to the new offset
477  * and length. */
478 static void
479 check_offset_length(tvbuff_t *tvb, gint offset, gint length,
480                 guint *offset_ptr, guint *length_ptr)
481 {
482         int exception = 0;
483
484         if (length < -1) {
485                 THROW(BoundsError);
486         }
487
488         if (!check_offset_length_no_exception(tvb, offset, length, offset_ptr, length_ptr, &exception)) {
489                 g_assert(exception > 0);
490                 THROW(exception);
491         }
492         return;
493 }
494
495
496 void
497 tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
498                 gint backing_offset, gint backing_length, gint reported_length)
499 {
500         g_assert(tvb->type == TVBUFF_SUBSET);
501         g_assert(!tvb->initialized);
502
503         if (reported_length < -1) {
504                 THROW(ReportedBoundsError);
505         }
506
507         check_offset_length(backing, backing_offset, backing_length,
508                         &tvb->tvbuffs.subset.offset,
509                         &tvb->tvbuffs.subset.length);
510
511         tvb->tvbuffs.subset.tvb         = backing;
512         tvb->length                     = tvb->tvbuffs.subset.length;
513
514         if (reported_length == -1) {
515                 tvb->reported_length    = backing->reported_length - tvb->tvbuffs.subset.offset;
516         }
517         else {
518                 tvb->reported_length    = reported_length;
519         }
520         tvb->initialized                = TRUE;
521         add_to_used_in_list(backing, tvb);
522
523         /* Optimization. If the backing buffer has a pointer to contiguous, real data,
524          * then we can point directly to our starting offset in that buffer */
525         if (backing->real_data != NULL) {
526                 tvb->real_data = backing->real_data + tvb->tvbuffs.subset.offset;
527         }
528 }
529
530
531 tvbuff_t*
532 tvb_new_subset(tvbuff_t *backing, gint backing_offset, gint backing_length, gint reported_length)
533 {
534         tvbuff_t        *tvb;
535
536         tvb = tvb_new(TVBUFF_SUBSET);
537
538         CLEANUP_PUSH(tvb_free_void, tvb);
539
540         tvb_set_subset(tvb, backing, backing_offset, backing_length, reported_length);
541
542         /*
543          * The top-level data source of this tvbuff is the top-level
544          * data source of its parent.
545          */
546         tvb->ds_tvb = backing->ds_tvb;
547
548         CLEANUP_POP;
549
550         return tvb;
551 }
552
553 void
554 tvb_composite_append(tvbuff_t* tvb, tvbuff_t* member)
555 {
556         tvb_comp_t      *composite;
557
558         g_assert(!tvb->initialized);
559         composite = &tvb->tvbuffs.composite;
560         composite->tvbs = g_slist_append( composite->tvbs, member );
561         add_to_used_in_list(member, tvb);
562 }
563
564 void
565 tvb_composite_prepend(tvbuff_t* tvb, tvbuff_t* member)
566 {
567         tvb_comp_t      *composite;
568
569         g_assert(!tvb->initialized);
570         composite = &tvb->tvbuffs.composite;
571         composite->tvbs = g_slist_prepend( composite->tvbs, member );
572         add_to_used_in_list(member, tvb);
573 }
574
575 tvbuff_t*
576 tvb_new_composite(void)
577 {
578         return tvb_new(TVBUFF_COMPOSITE);
579 }
580
581 void
582 tvb_composite_finalize(tvbuff_t* tvb)
583 {
584         GSList          *slist;
585         guint           num_members;
586         tvbuff_t        *member_tvb;
587         tvb_comp_t      *composite;
588         int             i = 0;
589
590         g_assert(!tvb->initialized);
591         g_assert(tvb->length == 0);
592
593         composite = &tvb->tvbuffs.composite;
594         num_members = g_slist_length(composite->tvbs);
595
596         composite->start_offsets = g_new(guint, num_members);
597         composite->end_offsets = g_new(guint, num_members);
598
599         for (slist = composite->tvbs; slist != NULL; slist = slist->next) {
600                 g_assert((guint) i < num_members);
601                 member_tvb = slist->data;
602                 composite->start_offsets[i] = tvb->length;
603                 tvb->length += member_tvb->length;
604                 composite->end_offsets[i] = tvb->length - 1;
605                 i++;
606         }
607
608         tvb->initialized = TRUE;
609 }
610
611
612
613 guint
614 tvb_length(tvbuff_t* tvb)
615 {
616         g_assert(tvb->initialized);
617
618         return tvb->length;
619 }
620
621 gint
622 tvb_length_remaining(tvbuff_t *tvb, gint offset)
623 {
624         guint   abs_offset, abs_length;
625
626         g_assert(tvb->initialized);
627
628         if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
629                 return abs_length;
630         }
631         else {
632                 return -1;
633         }
634 }
635
636 guint
637 tvb_ensure_length_remaining(tvbuff_t *tvb, gint offset)
638 {
639         guint   abs_offset, abs_length;
640         int     exception;
641
642         g_assert(tvb->initialized);
643
644         if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, &exception)) {
645                 THROW(exception);
646         }
647         return abs_length;
648 }
649
650
651
652
653 /* Validates that 'length' bytes are available starting from
654  * offset (pos/neg). Does not throw an exception. */
655 gboolean
656 tvb_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
657 {
658         guint           abs_offset, abs_length;
659
660         g_assert(tvb->initialized);
661
662         if (!compute_offset_length(tvb, offset, length, &abs_offset, &abs_length, NULL))
663                 return FALSE;
664
665         if (abs_offset + abs_length <= tvb->length) {
666                 return TRUE;
667         }
668         else {
669                 return FALSE;
670         }
671 }
672
673 /* Validates that 'length' bytes are available starting from
674  * offset (pos/neg). Throws an exception if they aren't. */
675 void
676 tvb_ensure_bytes_exist(tvbuff_t *tvb, gint offset, gint length)
677 {
678         guint           abs_offset, abs_length;
679
680         g_assert(tvb->initialized);
681
682         /*
683          * -1 doesn't mean "until end of buffer", as that's pointless
684          * for this routine.  We must treat it as a Really Large Positive
685          * Number, so that we throw an exception; we throw
686          * ReportedBoundsError, as if it were past even the end of a
687          * reassembled packet, and past the end of even the data we
688          * didn't capture.
689          *
690          * We do the same with other negative lengths.
691          */
692         if (length < 0) {
693                 THROW(ReportedBoundsError);
694         }
695         check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
696 }
697
698 gboolean
699 tvb_offset_exists(tvbuff_t *tvb, gint offset)
700 {
701         guint           abs_offset, abs_length;
702
703         g_assert(tvb->initialized);
704         if (!compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL))
705                 return FALSE;
706
707         if (abs_offset < tvb->length) {
708                 return TRUE;
709         }
710         else {
711                 return FALSE;
712         }
713 }
714
715 guint
716 tvb_reported_length(tvbuff_t* tvb)
717 {
718         g_assert(tvb->initialized);
719
720         return tvb->reported_length;
721 }
722
723 gint
724 tvb_reported_length_remaining(tvbuff_t *tvb, gint offset)
725 {
726         guint   abs_offset, abs_length;
727
728         g_assert(tvb->initialized);
729
730         if (compute_offset_length(tvb, offset, -1, &abs_offset, &abs_length, NULL)) {
731                 if (tvb->reported_length >= abs_offset)
732                         return tvb->reported_length - abs_offset;
733                 else
734                         return -1;
735         }
736         else {
737                 return -1;
738         }
739 }
740
741 /* Set the reported length of a tvbuff to a given value; used for protocols
742    whose headers contain an explicit length and where the calling
743    dissector's payload may include padding as well as the packet for
744    this protocol.
745
746    Also adjusts the data length. */
747 void
748 tvb_set_reported_length(tvbuff_t* tvb, guint reported_length)
749 {
750         g_assert(tvb->initialized);
751
752         if (reported_length > tvb->reported_length)
753                 THROW(ReportedBoundsError);
754
755         tvb->reported_length = reported_length;
756         if (reported_length < tvb->length)
757                 tvb->length = reported_length;
758 }
759
760
761 static guint8*
762 first_real_data_ptr(tvbuff_t *tvb)
763 {
764         tvbuff_t        *member;
765
766         switch(tvb->type) {
767                 case TVBUFF_REAL_DATA:
768                         return tvb->real_data;
769                 case TVBUFF_SUBSET:
770                         member = tvb->tvbuffs.subset.tvb;
771                         return first_real_data_ptr(member);
772                 case TVBUFF_COMPOSITE:
773                         member = tvb->tvbuffs.composite.tvbs->data;
774                         return first_real_data_ptr(member);
775         }
776
777         g_assert_not_reached();
778         return NULL;
779 }
780
781 static int
782 offset_from_real_beginning(tvbuff_t *tvb, int counter)
783 {
784         tvbuff_t        *member;
785
786         switch(tvb->type) {
787                 case TVBUFF_REAL_DATA:
788                         return counter;
789                 case TVBUFF_SUBSET:
790                         member = tvb->tvbuffs.subset.tvb;
791                         return offset_from_real_beginning(member, counter + tvb->tvbuffs.subset.offset);
792                 case TVBUFF_COMPOSITE:
793                         member = tvb->tvbuffs.composite.tvbs->data;
794                         return offset_from_real_beginning(member, counter);
795         }
796
797         g_assert_not_reached();
798         return 0;
799 }
800
801 gint
802 tvb_raw_offset(tvbuff_t *tvb)
803 {
804         if (tvb->raw_offset == -1) {
805                 tvb->raw_offset = offset_from_real_beginning(tvb, 0);
806         }
807         return tvb->raw_offset;
808 }
809
810 static guint8*
811 composite_ensure_contiguous_no_exception(tvbuff_t *tvb, guint abs_offset,
812                 guint abs_length)
813 {
814         guint           i, num_members;
815         tvb_comp_t      *composite;
816         tvbuff_t        *member_tvb = NULL;
817         guint           member_offset, member_length;
818         GSList          *slist;
819
820         g_assert(tvb->type == TVBUFF_COMPOSITE);
821
822         /* Maybe the range specified by offset/length
823          * is contiguous inside one of the member tvbuffs */
824         composite = &tvb->tvbuffs.composite;
825         num_members = g_slist_length(composite->tvbs);
826
827         for (i = 0; i < num_members; i++) {
828                 if (abs_offset <= composite->end_offsets[i]) {
829                         slist = g_slist_nth(composite->tvbs, i);
830                         member_tvb = slist->data;
831                         break;
832                 }
833         }
834         g_assert(member_tvb);
835
836         if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
837                                 abs_length, &member_offset, &member_length, NULL)) {
838
839                 /*
840                  * The range is, in fact, contiguous within member_tvb.
841                  */
842                 g_assert(!tvb->real_data);
843                 return ensure_contiguous_no_exception(member_tvb, member_offset, member_length, NULL);
844         }
845         else {
846                 tvb->real_data = tvb_memdup(tvb, 0, -1);
847                 return tvb->real_data + abs_offset;
848         }
849
850         g_assert_not_reached();
851         return NULL;
852 }
853
854 static guint8*
855 ensure_contiguous_no_exception(tvbuff_t *tvb, gint offset, gint length,
856                 int *exception)
857 {
858         guint   abs_offset, abs_length;
859
860         if (!check_offset_length_no_exception(tvb, offset, length,
861             &abs_offset, &abs_length, exception)) {
862                 return NULL;
863         }
864
865         /*
866          * We know that all the data is present in the tvbuff, so
867          * no exceptions should be thrown.
868          */
869         if (tvb->real_data) {
870                 return tvb->real_data + abs_offset;
871         }
872         else {
873                 switch(tvb->type) {
874                         case TVBUFF_REAL_DATA:
875                                 g_assert_not_reached();
876                         case TVBUFF_SUBSET:
877                                 return ensure_contiguous_no_exception(tvb->tvbuffs.subset.tvb,
878                                                 abs_offset - tvb->tvbuffs.subset.offset,
879                                                 abs_length, NULL);
880                         case TVBUFF_COMPOSITE:
881                                 return composite_ensure_contiguous_no_exception(tvb, abs_offset, abs_length);
882                 }
883         }
884
885         g_assert_not_reached();
886         return NULL;
887 }
888
889 static guint8*
890 ensure_contiguous(tvbuff_t *tvb, gint offset, gint length)
891 {
892         int exception;
893         guint8 *p;
894
895         p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
896         if (p == NULL) {
897                 g_assert(exception > 0);
898                 THROW(exception);
899         }
900         return p;
901 }
902
903 static const guint8*
904 guint8_find(const guint8* haystack, size_t haystacklen, guint8 needle)
905 {
906         const guint8    *b;
907         int             i;
908
909         for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
910                 if (*b == needle) {
911                         return b;
912                 }
913         }
914
915         return NULL;
916 }
917
918 static const guint8*
919 guint8_pbrk(const guint8* haystack, size_t haystacklen, guint8 *needles)
920 {
921         const guint8    *b;
922         int             i;
923         guint8          item, *needlep, needle;
924
925         for (b = haystack, i = 0; (guint) i < haystacklen; i++, b++) {
926                 item = *b;
927                 needlep = needles;
928                 while ((needle = *needlep) != '\0') {
929                         if (item == needle)
930                                 return b;
931                         needlep++;
932                 }
933         }
934
935         return NULL;
936 }
937
938
939
940 /************** ACCESSORS **************/
941
942 static guint8*
943 composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, guint abs_length)
944 {
945         guint           i, num_members;
946         tvb_comp_t      *composite;
947         tvbuff_t        *member_tvb = NULL;
948         guint           member_offset, member_length;
949         gboolean        retval;
950         GSList          *slist;
951
952         g_assert(tvb->type == TVBUFF_COMPOSITE);
953
954         /* Maybe the range specified by offset/length
955          * is contiguous inside one of the member tvbuffs */
956         composite = &tvb->tvbuffs.composite;
957         num_members = g_slist_length(composite->tvbs);
958
959         for (i = 0; i < num_members; i++) {
960                 if (abs_offset <= composite->end_offsets[i]) {
961                         slist = g_slist_nth(composite->tvbs, i);
962                         member_tvb = slist->data;
963                         break;
964                 }
965         }
966         g_assert(member_tvb);
967
968         if (check_offset_length_no_exception(member_tvb, abs_offset - composite->start_offsets[i],
969                                 abs_length, &member_offset, &member_length, NULL)) {
970
971                 g_assert(!tvb->real_data);
972                 return tvb_memcpy(member_tvb, target, member_offset, member_length);
973         }
974         else {
975                 /* The requested data is non-contiguous inside
976                  * the member tvb. We have to memcpy() the part that's in the member tvb,
977                  * then iterate across the other member tvb's, copying their portions
978                  * until we have copied all data.
979                  */
980                 retval = compute_offset_length(member_tvb, abs_offset - composite->start_offsets[i], -1,
981                                 &member_offset, &member_length, NULL);
982                 g_assert(retval);
983
984                 tvb_memcpy(member_tvb, target, member_offset, member_length);
985                 abs_offset      += member_length;
986                 abs_length      -= member_length;
987
988                 /* Recurse */
989                 if (abs_length > 0) {
990                         composite_memcpy(tvb, target + member_length, abs_offset, abs_length);
991                 }
992
993                 return target;
994         }
995
996         g_assert_not_reached();
997         return NULL;
998 }
999
1000 guint8*
1001 tvb_memcpy(tvbuff_t *tvb, guint8* target, gint offset, gint length)
1002 {
1003         guint   abs_offset, abs_length;
1004
1005         g_assert(length >= -1);
1006         check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
1007
1008         if (tvb->real_data) {
1009                 return (guint8*) memcpy(target, tvb->real_data + abs_offset, abs_length);
1010         }
1011
1012         switch(tvb->type) {
1013                 case TVBUFF_REAL_DATA:
1014                         g_assert_not_reached();
1015
1016                 case TVBUFF_SUBSET:
1017                         return tvb_memcpy(tvb->tvbuffs.subset.tvb, target,
1018                                         abs_offset - tvb->tvbuffs.subset.offset,
1019                                         abs_length);
1020
1021                 case TVBUFF_COMPOSITE:
1022                         return composite_memcpy(tvb, target, offset, length);
1023         }
1024
1025         g_assert_not_reached();
1026         return NULL;
1027 }
1028
1029
1030 /*
1031  * XXX - this doesn't treat a length of -1 as an error.
1032  * If it did, this could replace some code that calls
1033  * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
1034  * data to it.
1035  *
1036  * "composite_ensure_contiguous_no_exception()" depends on -1 not being
1037  * an error; does anything else depend on this routine treating -1 as
1038  * meaning "to the end of the buffer"?
1039  */
1040 guint8*
1041 tvb_memdup(tvbuff_t *tvb, gint offset, gint length)
1042 {
1043         guint   abs_offset, abs_length;
1044         guint8  *duped;
1045
1046         check_offset_length(tvb, offset, length, &abs_offset, &abs_length);
1047
1048         duped = g_malloc(abs_length);
1049         return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1050 }
1051
1052
1053
1054 const guint8*
1055 tvb_get_ptr(tvbuff_t *tvb, gint offset, gint length)
1056 {
1057         return ensure_contiguous(tvb, offset, length);
1058 }
1059
1060 guint8
1061 tvb_get_guint8(tvbuff_t *tvb, gint offset)
1062 {
1063         guint8* ptr;
1064
1065         ptr = ensure_contiguous(tvb, offset, sizeof(guint8));
1066         return *ptr;
1067 }
1068
1069 guint16
1070 tvb_get_ntohs(tvbuff_t *tvb, gint offset)
1071 {
1072         guint8* ptr;
1073
1074         ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1075         return pntohs(ptr);
1076 }
1077
1078 guint32
1079 tvb_get_ntoh24(tvbuff_t *tvb, gint offset)
1080 {
1081         guint8* ptr;
1082
1083         ptr = ensure_contiguous(tvb, offset, 3);
1084         return pntoh24(ptr);
1085 }
1086
1087 guint32
1088 tvb_get_ntohl(tvbuff_t *tvb, gint offset)
1089 {
1090         guint8* ptr;
1091
1092         ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1093         return pntohl(ptr);
1094 }
1095
1096 /*
1097  * Stuff for IEEE float handling on platforms that don't have IEEE
1098  * format as the native floating-point format.
1099  *
1100  * For now, we treat only the VAX as such a platform.
1101  *
1102  * XXX - other non-IEEE boxes that can run UNIX include some Crays,
1103  * and possibly other machines.
1104  *
1105  * It appears that the official Linux port to System/390 and
1106  * zArchitecture uses IEEE format floating point (not a
1107  * huge surprise).
1108  *
1109  * I don't know whether there are any other machines that
1110  * could run Ethereal and that don't use IEEE format.
1111  * As far as I know, all of the main commercial microprocessor
1112  * families on which OSes that support Ethereal can run
1113  * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
1114  * IA-64, and so on).
1115  */
1116
1117 #if defined(vax)
1118
1119 #include <math.h>
1120
1121 /*
1122  * Single-precision.
1123  */
1124 #define IEEE_SP_NUMBER_WIDTH    32      /* bits in number */
1125 #define IEEE_SP_EXP_WIDTH       8       /* bits in exponent */
1126 #define IEEE_SP_MANTISSA_WIDTH  23      /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1127
1128 #define IEEE_SP_SIGN_MASK       0x80000000
1129 #define IEEE_SP_EXPONENT_MASK   0x7F800000
1130 #define IEEE_SP_MANTISSA_MASK   0x007FFFFF
1131 #define IEEE_SP_INFINITY        IEEE_SP_EXPONENT_MASK
1132
1133 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1134 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1135 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1136
1137 static int
1138 ieee_float_is_zero(guint32 w)
1139 {
1140         return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1141 }
1142
1143 static gfloat
1144 get_ieee_float(guint32 w)
1145 {
1146         long sign;
1147         long exponent;
1148         long mantissa;
1149
1150         sign = w & IEEE_SP_SIGN_MASK;
1151         exponent = w & IEEE_SP_EXPONENT_MASK;
1152         mantissa = w & IEEE_SP_MANTISSA_MASK;
1153
1154         if (ieee_float_is_zero(w)) {
1155                 /* number is zero, unnormalized, or not-a-number */
1156                 return 0.0;
1157         }
1158 #if 0
1159         /*
1160          * XXX - how to handle this?
1161          */
1162         if (IEEE_SP_INFINITY == exponent) {
1163                 /*
1164                  * number is positive or negative infinity, or a special value
1165                  */
1166                 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1167         }
1168 #endif
1169
1170         exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1171             IEEE_SP_MANTISSA_WIDTH;
1172         mantissa |= IEEE_SP_IMPLIED_BIT;
1173
1174         if (sign)
1175                 return -mantissa * pow(2, exponent);
1176         else
1177                 return mantissa * pow(2, exponent);
1178 }
1179
1180 /*
1181  * Double-precision.
1182  * We assume that if you don't have IEEE floating-point, you have a
1183  * compiler that understands 64-bit integral quantities.
1184  */
1185 #define IEEE_DP_NUMBER_WIDTH    64      /* bits in number */
1186 #define IEEE_DP_EXP_WIDTH       11      /* bits in exponent */
1187 #define IEEE_DP_MANTISSA_WIDTH  52      /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1188
1189 #define IEEE_DP_SIGN_MASK       0x8000000000000000LL
1190 #define IEEE_DP_EXPONENT_MASK   0x7FF0000000000000LL
1191 #define IEEE_DP_MANTISSA_MASK   0x000FFFFFFFFFFFFFLL
1192 #define IEEE_DP_INFINITY        IEEE_DP_EXPONENT_MASK
1193
1194 #define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
1195 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1196 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1197
1198 static int
1199 ieee_double_is_zero(guint64 w)
1200 {
1201         return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1202 }
1203
1204 static gdouble
1205 get_ieee_double(guint64 w)
1206 {
1207         gint64 sign;
1208         gint64 exponent;
1209         gint64 mantissa;
1210
1211         sign = w & IEEE_DP_SIGN_MASK;
1212         exponent = w & IEEE_DP_EXPONENT_MASK;
1213         mantissa = w & IEEE_DP_MANTISSA_MASK;
1214
1215         if (ieee_double_is_zero(w)) {
1216                 /* number is zero, unnormalized, or not-a-number */
1217                 return 0.0;
1218         }
1219 #if 0
1220         /*
1221          * XXX - how to handle this?
1222          */
1223         if (IEEE_DP_INFINITY == exponent) {
1224                 /*
1225                  * number is positive or negative infinity, or a special value
1226                  */
1227                 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1228         }
1229 #endif
1230
1231         exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1232             IEEE_DP_MANTISSA_WIDTH;
1233         mantissa |= IEEE_DP_IMPLIED_BIT;
1234
1235         if (sign)
1236                 return -mantissa * pow(2, exponent);
1237         else
1238                 return mantissa * pow(2, exponent);
1239 }
1240 #endif
1241
1242 /*
1243  * Fetches an IEEE single-precision floating-point number, in
1244  * big-endian form, and returns a "float".
1245  *
1246  * XXX - should this be "double", in case there are IEEE single-
1247  * precision numbers that won't fit in some platform's native
1248  * "float" format?
1249  */
1250 gfloat
1251 tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
1252 {
1253 #if defined(vax)
1254         return get_ieee_float(tvb_get_ntohl(tvb, offset));
1255 #else
1256         union {
1257                 gfloat f;
1258                 guint32 w;
1259         } ieee_fp_union;
1260
1261         ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1262         return ieee_fp_union.f;
1263 #endif
1264 }
1265
1266 /*
1267  * Fetches an IEEE double-precision floating-point number, in
1268  * big-endian form, and returns a "double".
1269  */
1270 gdouble
1271 tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
1272 {
1273 #if defined(vax)
1274         union {
1275                 guint32 w[2];
1276                 guint64 dw;
1277         } ieee_fp_union;
1278 #else
1279         union {
1280                 gdouble d;
1281                 guint32 w[2];
1282         } ieee_fp_union;
1283 #endif
1284
1285 #ifdef WORDS_BIGENDIAN
1286         ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1287         ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1288 #else
1289         ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1290         ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1291 #endif
1292 #if defined(vax)
1293         return get_ieee_double(ieee_fp_union.dw);
1294 #else
1295         return ieee_fp_union.d;
1296 #endif
1297 }
1298
1299 guint16
1300 tvb_get_letohs(tvbuff_t *tvb, gint offset)
1301 {
1302         guint8* ptr;
1303
1304         ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1305         return pletohs(ptr);
1306 }
1307
1308 guint32
1309 tvb_get_letoh24(tvbuff_t *tvb, gint offset)
1310 {
1311         guint8* ptr;
1312
1313         ptr = ensure_contiguous(tvb, offset, 3);
1314         return pletoh24(ptr);
1315 }
1316
1317 guint32
1318 tvb_get_letohl(tvbuff_t *tvb, gint offset)
1319 {
1320         guint8* ptr;
1321
1322         ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1323         return pletohl(ptr);
1324 }
1325
1326 /*
1327  * Fetches an IEEE single-precision floating-point number, in
1328  * little-endian form, and returns a "float".
1329  *
1330  * XXX - should this be "double", in case there are IEEE single-
1331  * precision numbers that won't fit in some platform's native
1332  * "float" format?
1333  */
1334 gfloat
1335 tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
1336 {
1337 #if defined(vax)
1338         return get_ieee_float(tvb_get_letohl(tvb, offset));
1339 #else
1340         union {
1341                 gfloat f;
1342                 guint32 w;
1343         } ieee_fp_union;
1344
1345         ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1346         return ieee_fp_union.f;
1347 #endif
1348 }
1349
1350 /*
1351  * Fetches an IEEE double-precision floating-point number, in
1352  * little-endian form, and returns a "double".
1353  */
1354 gdouble
1355 tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
1356 {
1357 #if defined(vax)
1358         union {
1359                 guint32 w[2];
1360                 guint64 dw;
1361         } ieee_fp_union;
1362 #else
1363         union {
1364                 gdouble d;
1365                 guint32 w[2];
1366         } ieee_fp_union;
1367 #endif
1368
1369 #ifdef WORDS_BIGENDIAN
1370         ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1371         ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1372 #else
1373         ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1374         ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1375 #endif
1376 #if defined(vax)
1377         return get_ieee_double(ieee_fp_union.dw);
1378 #else
1379         return ieee_fp_union.d;
1380 #endif
1381 }
1382
1383 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1384  * at most maxlength number of bytes; if maxlength is -1, searches to
1385  * end of tvbuff.
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. */
1390 gint
1391 tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
1392 {
1393         const guint8    *result;
1394         guint           abs_offset, junk_length;
1395         guint           tvbufflen;
1396         guint           limit;
1397
1398         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1399
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. */
1404                 limit = tvbufflen;
1405         }
1406         else if (tvbufflen < (guint) maxlength) {
1407                 /* Maximum length goes past end of tvbuff; search to end
1408                    of tvbuff. */
1409                 limit = tvbufflen;
1410         }
1411         else {
1412                 /* Maximum length doesn't go past end of tvbuff; search
1413                    to that value. */
1414                 limit = maxlength;
1415         }
1416
1417         /* If we have real data, perform our search now. */
1418         if (tvb->real_data) {
1419                 result = guint8_find(tvb->real_data + abs_offset, limit, needle);
1420                 if (result == NULL) {
1421                         return -1;
1422                 }
1423                 else {
1424                         return result - tvb->real_data;
1425                 }
1426         }
1427
1428         switch(tvb->type) {
1429                 case TVBUFF_REAL_DATA:
1430                         g_assert_not_reached();
1431
1432                 case TVBUFF_SUBSET:
1433                         return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1434                                         abs_offset - tvb->tvbuffs.subset.offset,
1435                                         limit, needle);
1436
1437                 case TVBUFF_COMPOSITE:
1438                         g_assert_not_reached();
1439                         /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1440         }
1441
1442         g_assert_not_reached();
1443         return -1;
1444 }
1445
1446 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1447  * Searches at most maxlength number of bytes; if maxlength is -1, searches
1448  * to end of tvbuff.
1449  * Returns the offset of the found needle, or -1 if not found.
1450  * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1451  * in that case, -1 will be returned if the boundary is reached before
1452  * finding needle. */
1453 gint
1454 tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 *needles)
1455 {
1456         const guint8    *result;
1457         guint           abs_offset, junk_length;
1458         guint           tvbufflen;
1459         guint           limit;
1460
1461         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1462
1463         /* Only search to end of tvbuff, w/o throwing exception. */
1464         tvbufflen = tvb_length_remaining(tvb, abs_offset);
1465         if (maxlength == -1) {
1466                 /* No maximum length specified; search to end of tvbuff. */
1467                 limit = tvbufflen;
1468         }
1469         else if (tvbufflen < (guint) maxlength) {
1470                 /* Maximum length goes past end of tvbuff; search to end
1471                    of tvbuff. */
1472                 limit = tvbufflen;
1473         }
1474         else {
1475                 /* Maximum length doesn't go past end of tvbuff; search
1476                    to that value. */
1477                 limit = maxlength;
1478         }
1479
1480         /* If we have real data, perform our search now. */
1481         if (tvb->real_data) {
1482                 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
1483                 if (result == NULL) {
1484                         return -1;
1485                 }
1486                 else {
1487                         return result - tvb->real_data;
1488                 }
1489         }
1490
1491         switch(tvb->type) {
1492                 case TVBUFF_REAL_DATA:
1493                         g_assert_not_reached();
1494
1495                 case TVBUFF_SUBSET:
1496                         return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
1497                                         abs_offset - tvb->tvbuffs.subset.offset,
1498                                         limit, needles);
1499
1500                 case TVBUFF_COMPOSITE:
1501                         g_assert_not_reached();
1502                         /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
1503         }
1504
1505         g_assert_not_reached();
1506         return -1;
1507 }
1508
1509 /* Find size of stringz (NUL-terminated string) by looking for terminating
1510  * NUL.  The size of the string includes the terminating NUL.
1511  *
1512  * If the NUL isn't found, it throws the appropriate exception.
1513  */
1514 guint
1515 tvb_strsize(tvbuff_t *tvb, gint offset)
1516 {
1517         guint   abs_offset, junk_length;
1518         gint    nul_offset;
1519
1520         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1521         nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1522         if (nul_offset == -1) {
1523                 /*
1524                  * OK, we hit the end of the tvbuff, so we should throw
1525                  * an exception.
1526                  *
1527                  * Did we hit the end of the captured data, or the end
1528                  * of the actual data?  If there's less captured data
1529                  * than actual data, we presumably hit the end of the
1530                  * captured data, otherwise we hit the end of the actual
1531                  * data.
1532                  */
1533                 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
1534                         THROW(BoundsError);
1535                 } else {
1536                         THROW(ReportedBoundsError);
1537                 }
1538         }
1539         return (nul_offset - abs_offset) + 1;
1540 }
1541
1542 /* Find length of string by looking for end of string ('\0'), up to
1543  * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1544  * of tvbuff.
1545  * Returns -1 if 'maxlength' reached before finding EOS. */
1546 gint
1547 tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
1548 {
1549         gint    result_offset;
1550         guint   abs_offset, junk_length;
1551
1552         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1553
1554         result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1555
1556         if (result_offset == -1) {
1557                 return -1;
1558         }
1559         else {
1560                 return result_offset - abs_offset;
1561         }
1562 }
1563
1564 /*
1565  * Implement strneql etc
1566  */
1567
1568 /*
1569  * Call strncmp after checking if enough chars left, returning 0 if
1570  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1571  */
1572 gint
1573 tvb_strneql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1574 {
1575         guint8 *ptr;
1576
1577         ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1578
1579         if (ptr) {
1580                 int cmp = strncmp(ptr, str, size);
1581
1582                 /*
1583                  * Return 0 if equal, -1 otherwise.
1584                  */
1585                 return (cmp == 0 ? 0 : -1);
1586         } else {
1587                 /*
1588                  * Not enough characters in the tvbuff to match the
1589                  * string.
1590                  */
1591                 return -1;
1592         }
1593 }
1594
1595 /*
1596  * Call strncasecmp after checking if enough chars left, returning 0 if
1597  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1598  */
1599 gint
1600 tvb_strncaseeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1601 {
1602         guint8 *ptr;
1603
1604         ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1605
1606         if (ptr) {
1607                 int cmp = strncasecmp(ptr, str, size);
1608
1609                 /*
1610                  * Return 0 if equal, -1 otherwise.
1611                  */
1612                 return (cmp == 0 ? 0 : -1);
1613         } else {
1614                 /*
1615                  * Not enough characters in the tvbuff to match the
1616                  * string.
1617                  */
1618                 return -1;
1619         }
1620 }
1621
1622 /*
1623  * Call memcmp after checking if enough chars left, returning 0 if
1624  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1625  */
1626 gint
1627 tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1628 {
1629         guint8 *ptr;
1630
1631         ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1632
1633         if (ptr) {
1634                 int cmp = memcmp(ptr, str, size);
1635
1636                 /*
1637                  * Return 0 if equal, -1 otherwise.
1638                  */
1639                 return (cmp == 0 ? 0 : -1);
1640         } else {
1641                 /*
1642                  * Not enough characters in the tvbuff to match the
1643                  * string.
1644                  */
1645                 return -1;
1646         }
1647 }
1648
1649 /* Convert a string from Unicode to ASCII.  At the moment we fake it by
1650  * assuming all characters are ASCII  )-:  The caller must free the
1651  * result returned.  The len parameter is the number of guint16's to
1652  * convert from Unicode. */
1653 char *
1654 tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
1655 {
1656         char *buffer;
1657         int i;
1658         guint16 character;
1659
1660         /* Make sure we have enough data before allocating the buffer,
1661            so we don't blow up if the length is huge. */
1662         tvb_ensure_bytes_exist(tvb, offset, 2*len);
1663
1664         /* We know we won't throw an exception, so we don't have to worry
1665            about leaking this buffer. */
1666         buffer = g_malloc(len + 1);
1667
1668         for (i = 0; i < len; i++) {
1669                 character = little_endian ? tvb_get_letohs(tvb, offset)
1670                                           : tvb_get_ntohs(tvb, offset);
1671                 buffer[i] = character & 0xff;
1672                 offset += 2;
1673         }
1674
1675         buffer[len] = 0;
1676
1677         return buffer;
1678 }
1679
1680 /*
1681  * Format the data in the tvb from offset for length ...
1682  */
1683
1684 guint8 *
1685 tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
1686 {
1687   guint8 *ptr;
1688   gint len = size;
1689
1690   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1691
1692     len = tvb_length_remaining(tvb, offset);
1693     ptr = ensure_contiguous(tvb, offset, len);
1694
1695   }
1696
1697   return format_text(ptr, len);
1698
1699 }
1700
1701 /*
1702  * Given a tvbuff, an offset, and a length, allocate a buffer big enough
1703  * to hold a non-null-terminated string of that length at that offset,
1704  * plus a trailing '\0', copy the string into it, and return a pointer
1705  * to the string.
1706  *
1707  * Throws an exception if the tvbuff ends before the string does.
1708  */
1709 guint8 *
1710 tvb_get_string(tvbuff_t *tvb, gint offset, gint length)
1711 {
1712         guint8 *ptr, *strbuf;
1713
1714         ptr = ensure_contiguous(tvb, offset, length);
1715         strbuf = g_malloc(length + 1);
1716         if (length != 0)
1717                 memcpy(strbuf, ptr, length);
1718         strbuf[length] = '\0';
1719         return strbuf;
1720 }
1721
1722 /*
1723  * Given a tvbuff and an offset, with the offset assumed to refer to
1724  * a null-terminated string, find the length of that string (and throw
1725  * an exception if the tvbuff ends before we find the null), allocate
1726  * a buffer big enough to hold the string, copy the string into it,
1727  * and return a pointer to the string.  Also return the length of the
1728  * string (including the terminating null) through a pointer.
1729  */
1730 guint8 *
1731 tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
1732 {
1733         guint size;
1734         guint8 *strptr;
1735
1736         size = tvb_strsize(tvb, offset);
1737         strptr = g_malloc(size);
1738         tvb_memcpy(tvb, strptr, offset, size);
1739         *lengthp = size;
1740         return strptr;
1741 }
1742
1743 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1744  * no more than bufsize number of bytes, including terminating NUL, to buffer.
1745  * Returns length of string (not including terminating NUL), or -1 if the string was
1746  * truncated in the buffer due to not having reached the terminating NUL.
1747  * In this way, it acts like snprintf().
1748  *
1749  * bufsize MUST be greater than 0.
1750  *
1751  * When processing a packet where the remaining number of bytes is less
1752  * than bufsize, an exception is not thrown if the end of the packet
1753  * is reached before the NUL is found. If no NUL is found before reaching
1754  * the end of the short packet, -1 is still returned, and the string
1755  * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1756  * at the correct spot, terminating the string.
1757  *
1758  * *bytes_copied will contain the number of bytes actually copied,
1759  * including the terminating-NUL.
1760  */
1761 static gint
1762 _tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
1763                 gint *bytes_copied)
1764 {
1765         gint    stringlen;
1766         guint   abs_offset, junk_length;
1767         gint    limit, len;
1768         gboolean decreased_max = FALSE;
1769
1770         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1771
1772         /* There must at least be room for the terminating NUL. */
1773         g_assert(bufsize != 0);
1774
1775         /* If there's no room for anything else, just return the NUL. */
1776         if (bufsize == 1) {
1777                 buffer[0] = 0;
1778                 *bytes_copied = 1;
1779                 return 0;
1780         }
1781
1782         /* Only read to end of tvbuff, w/o throwing exception. */
1783         len = tvb_length_remaining(tvb, abs_offset);
1784
1785         /* check_offset_length() won't throw an exception if we're
1786          * looking at the byte immediately after the end of the tvbuff. */
1787         if (len == 0) {
1788                 THROW(ReportedBoundsError);
1789         }
1790
1791         /* This should not happen because check_offset_length() would
1792          * have already thrown an exception if 'offset' were out-of-bounds.
1793          */
1794         g_assert(len != -1);
1795
1796         /*
1797          * If we've been passed a negative number, bufsize will
1798          * be huge.
1799          */
1800         g_assert(bufsize <= G_MAXINT);
1801
1802         if ((guint)len < bufsize) {
1803                 limit = len;
1804                 decreased_max = TRUE;
1805         }
1806         else {
1807                 limit = bufsize;
1808         }
1809
1810         stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
1811         /* If NUL wasn't found, copy the data and return -1 */
1812         if (stringlen == -1) {
1813                 tvb_memcpy(tvb, buffer, abs_offset, limit);
1814                 if (decreased_max) {
1815                         buffer[limit] = 0;
1816                         /* Add 1 for the extra NUL that we set at buffer[limit],
1817                          * pretending that it was copied as part of the string. */
1818                         *bytes_copied = limit + 1;
1819                 }
1820                 else {
1821                         *bytes_copied = limit;
1822                 }
1823                 return -1;
1824         }
1825
1826         /* Copy the string to buffer */
1827         tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
1828         *bytes_copied = stringlen + 1;
1829         return stringlen;
1830 }
1831
1832 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1833  * no more than bufsize number of bytes, including terminating NUL, to buffer.
1834  * Returns length of string (not including terminating NUL), or -1 if the string was
1835  * truncated in the buffer due to not having reached the terminating NUL.
1836  * In this way, it acts like snprintf().
1837  *
1838  * When processing a packet where the remaining number of bytes is less
1839  * than bufsize, an exception is not thrown if the end of the packet
1840  * is reached before the NUL is found. If no NUL is found before reaching
1841  * the end of the short packet, -1 is still returned, and the string
1842  * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1843  * at the correct spot, terminating the string.
1844  */
1845 gint
1846 tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1847 {
1848         gint bytes_copied;
1849
1850         return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1851 }
1852
1853 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
1854  * have a terminating NUL. If the string was truncated when copied into buffer,
1855  * a NUL is placed at the end of buffer to terminate it.
1856  */
1857 gint
1858 tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1859 {
1860         gint    len, bytes_copied;
1861
1862         len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1863
1864         if (len == -1) {
1865                 buffer[bufsize - 1] = 0;
1866                 return bytes_copied - 1;
1867         }
1868         else {
1869                 return len;
1870         }
1871 }
1872
1873 /*
1874  * Given a tvbuff, an offset into the tvbuff, and a length that starts
1875  * at that offset (which may be -1 for "all the way to the end of the
1876  * tvbuff"), find the end of the (putative) line that starts at the
1877  * specified offset in the tvbuff, going no further than the specified
1878  * length.
1879  *
1880  * Return the length of the line (not counting the line terminator at
1881  * the end), or, if we don't find a line terminator:
1882  *
1883  *      if "deseg" is true, return -1;
1884  *
1885  *      if "deseg" is false, return the amount of data remaining in
1886  *      the buffer.
1887  *
1888  * Set "*next_offset" to the offset of the character past the line
1889  * terminator, or past the end of the buffer if we don't find a line
1890  * terminator.  (It's not set if we return -1.)
1891  */
1892 gint
1893 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
1894     gboolean desegment)
1895 {
1896         gint eob_offset;
1897         gint eol_offset;
1898         int linelen;
1899
1900         if (len == -1)
1901                 len = tvb_length_remaining(tvb, offset);
1902         /*
1903          * XXX - what if "len" is still -1, meaning "offset is past the
1904          * end of the tvbuff"?
1905          */
1906         eob_offset = offset + len;
1907
1908         /*
1909          * Look either for a CR or an LF.
1910          */
1911         eol_offset = tvb_pbrk_guint8(tvb, offset, len, "\r\n");
1912         if (eol_offset == -1) {
1913                 /*
1914                  * No CR or LF - line is presumably continued in next packet.
1915                  */
1916                 if (desegment) {
1917                         /*
1918                          * Tell our caller we saw no EOL, so they can
1919                          * try to desegment and get the entire line
1920                          * into one tvbuff.
1921                          */
1922                         return -1;
1923                 } else {
1924                         /*
1925                          * Pretend the line runs to the end of the tvbuff.
1926                          */
1927                         linelen = eob_offset - offset;
1928                         *next_offset = eob_offset;
1929                 }
1930         } else {
1931                 /*
1932                  * Find the number of bytes between the starting offset
1933                  * and the CR or LF.
1934                  */
1935                 linelen = eol_offset - offset;
1936
1937                 /*
1938                  * Is it a CR?
1939                  */
1940                 if (tvb_get_guint8(tvb, eol_offset) == '\r') {
1941                         /*
1942                          * Yes - is it followed by an LF?
1943                          */
1944                         if (eol_offset + 1 >= eob_offset) {
1945                                 /*
1946                                  * Dunno - the next byte isn't in this
1947                                  * tvbuff.
1948                                  */
1949                                 if (desegment) {
1950                                         /*
1951                                          * We'll return -1, although that
1952                                          * runs the risk that if the line
1953                                          * really *is* terminated with a CR,
1954                                          * we won't properly dissect this
1955                                          * tvbuff.
1956                                          *
1957                                          * It's probably more likely that
1958                                          * the line ends with CR-LF than
1959                                          * that it ends with CR by itself.
1960                                          */
1961                                         return -1;
1962                                 }
1963                         } else {
1964                                 /*
1965                                  * Well, we can at least look at the next
1966                                  * byte.
1967                                  */
1968                                 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
1969                                         /*
1970                                          * It's an LF; skip over the CR.
1971                                          */
1972                                         eol_offset++;
1973                                 }
1974                         }
1975                 }
1976
1977                 /*
1978                  * Return the offset of the character after the last
1979                  * character in the line, skipping over the last character
1980                  * in the line terminator.
1981                  */
1982                 *next_offset = eol_offset + 1;
1983         }
1984         return linelen;
1985 }
1986
1987 /*
1988  * Given a tvbuff, an offset into the tvbuff, and a length that starts
1989  * at that offset (which may be -1 for "all the way to the end of the
1990  * tvbuff"), find the end of the (putative) line that starts at the
1991  * specified offset in the tvbuff, going no further than the specified
1992  * length.
1993  *
1994  * However, treat quoted strings inside the buffer specially - don't
1995  * treat newlines in quoted strings as line terminators.
1996  *
1997  * Return the length of the line (not counting the line terminator at
1998  * the end), or the amount of data remaining in the buffer if we don't
1999  * find a line terminator.
2000  *
2001  * Set "*next_offset" to the offset of the character past the line
2002  * terminator, or past the end of the buffer if we don't find a line
2003  * terminator.
2004  */
2005 gint
2006 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
2007     gint *next_offset)
2008 {
2009         gint cur_offset, char_offset;
2010         gboolean is_quoted;
2011         guchar c;
2012         gint eob_offset;
2013         int linelen;
2014
2015         if (len == -1)
2016                 len = tvb_length_remaining(tvb, offset);
2017         /*
2018          * XXX - what if "len" is still -1, meaning "offset is past the
2019          * end of the tvbuff"?
2020          */
2021         eob_offset = offset + len;
2022
2023         cur_offset = offset;
2024         is_quoted = FALSE;
2025         for (;;) {
2026                 /*
2027                  * Is this part of the string quoted?
2028                  */
2029                 if (is_quoted) {
2030                         /*
2031                          * Yes - look only for the terminating quote.
2032                          */
2033                         char_offset = tvb_find_guint8(tvb, cur_offset, len,
2034                             '"');
2035                 } else {
2036                         /*
2037                          * Look either for a CR, an LF, or a '"'.
2038                          */
2039                         char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
2040                             "\r\n\"");
2041                 }
2042                 if (char_offset == -1) {
2043                         /*
2044                          * Not found - line is presumably continued in
2045                          * next packet.
2046                          * We pretend the line runs to the end of the tvbuff.
2047                          */
2048                         linelen = eob_offset - offset;
2049                         *next_offset = eob_offset;
2050                         break;
2051                 }
2052
2053                 if (is_quoted) {
2054                         /*
2055                          * We're processing a quoted string.
2056                          * We only looked for ", so we know it's a ";
2057                          * as we're processing a quoted string, it's a
2058                          * closing quote.
2059                          */
2060                         is_quoted = FALSE;
2061                 } else {
2062                         /*
2063                          * OK, what is it?
2064                          */
2065                         c = tvb_get_guint8(tvb, char_offset);
2066                         if (c == '"') {
2067                                 /*
2068                                  * Un-quoted "; it begins a quoted
2069                                  * string.
2070                                  */
2071                                 is_quoted = TRUE;
2072                         } else {
2073                                 /*
2074                                  * It's a CR or LF; we've found a line
2075                                  * terminator.
2076                                  *
2077                                  * Find the number of bytes between the
2078                                  * starting offset and the CR or LF.
2079                                  */
2080                                 linelen = char_offset - offset;
2081
2082                                 /*
2083                                  * Is it a CR?
2084                                  */
2085                                 if (c == '\r') {
2086                                         /*
2087                                          * Yes; is it followed by an LF?
2088                                          */
2089                                         if (char_offset + 1 < eob_offset &&
2090                                             tvb_get_guint8(tvb, char_offset + 1)
2091                                               == '\n') {
2092                                                 /*
2093                                                  * Yes; skip over the CR.
2094                                                  */
2095                                                 char_offset++;
2096                                         }
2097                                 }
2098
2099                                 /*
2100                                  * Return the offset of the character after
2101                                  * the last character in the line, skipping
2102                                  * over the last character in the line
2103                                  * terminator, and quit.
2104                                  */
2105                                 *next_offset = char_offset + 1;
2106                                 break;
2107                         }
2108                 }
2109
2110                 /*
2111                  * Step past the character we found.
2112                  */
2113                 cur_offset = char_offset + 1;
2114                 if (cur_offset >= eob_offset) {
2115                         /*
2116                          * The character we found was the last character
2117                          * in the tvbuff - line is presumably continued in
2118                          * next packet.
2119                          * We pretend the line runs to the end of the tvbuff.
2120                          */
2121                         linelen = eob_offset - offset;
2122                         *next_offset = eob_offset;
2123                         break;
2124                 }
2125         }
2126         return linelen;
2127 }
2128
2129 /*
2130  * Format a bunch of data from a tvbuff as bytes, returning a pointer
2131  * to the string with the formatted data.
2132  */
2133 gchar *
2134 tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
2135 {
2136         return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
2137 }
2138
2139 tvbuff_t *
2140 tvb_get_ds_tvb(tvbuff_t *tvb)
2141 {
2142         return tvb->ds_tvb;
2143 }
2144
2145 /* Find a needle tvbuff within a haystack tvbuff. */
2146 gint
2147 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
2148 {
2149         guint           haystack_abs_offset, haystack_abs_length;
2150         const guint8    *haystack_data;
2151         const guint8    *needle_data;
2152         const guint     needle_len = needle_tvb->length;
2153         const guint8    *location;
2154
2155         /* Get pointers to the tvbuffs' data. */
2156         haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
2157         needle_data = tvb_get_ptr(needle_tvb, 0, -1);
2158
2159         check_offset_length(haystack_tvb, haystack_offset, -1,
2160                         &haystack_abs_offset, &haystack_abs_length);
2161
2162         location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
2163                         needle_data, needle_len);
2164
2165         if (location) {
2166                 return location - haystack_data;
2167         }
2168         else {
2169                 return -1;
2170         }
2171
2172         return -1;
2173 }