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