a5d2df33303bdfed54fb11ee87afe54aaf58fbdc
[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$
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  * Wireshark - Network traffic analyzer
20  * By Gerald Combs <gerald@wireshark.org>
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 #ifdef HAVE_LIBZ
45 #include <zlib.h>
46 #endif
47
48 #include "pint.h"
49 #include "tvbuff.h"
50 #include "tvbuff-int.h"
51 #include "strutil.h"
52 #include "emem.h"
53 #include "charsets.h"
54 #include "proto.h"      /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
55
56 static const guint8*
57 ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint length,
58                 int *exception);
59
60 static const guint8*
61 ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length);
62
63 #if GLIB_CHECK_VERSION(2,10,0)
64 #else
65 /* We dole out tvbuff's from this memchunk. */
66 static GMemChunk *tvbuff_mem_chunk = NULL;
67 #endif
68
69 void
70 tvbuff_init(void)
71 {
72 #if GLIB_CHECK_VERSION(2,10,0)
73 #else
74         if (!tvbuff_mem_chunk)
75                 tvbuff_mem_chunk = g_mem_chunk_create(tvbuff_t, 20, G_ALLOC_AND_FREE);
76 #endif
77 }
78
79 void
80 tvbuff_cleanup(void)
81 {
82 #if GLIB_CHECK_VERSION(2,10,0)
83 #else
84         if (tvbuff_mem_chunk)
85                 g_mem_chunk_destroy(tvbuff_mem_chunk);
86
87         tvbuff_mem_chunk = NULL;
88 #endif
89 }
90
91 static void
92 tvb_init(tvbuff_t *tvb, const tvbuff_type type)
93 {
94         tvb_backing_t   *backing;
95         tvb_comp_t      *composite;
96
97         tvb->type               = type;
98         tvb->initialized        = FALSE;
99         tvb->usage_count        = 1;
100         tvb->length             = 0;
101         tvb->reported_length    = 0;
102         tvb->free_cb            = NULL;
103         tvb->real_data          = NULL;
104         tvb->raw_offset         = -1;
105         tvb->used_in            = NULL;
106         tvb->ds_tvb             = NULL;
107
108         switch(type) {
109                 case TVBUFF_REAL_DATA:
110                         /* Nothing */
111                         break;
112
113                 case TVBUFF_SUBSET:
114                         backing = &tvb->tvbuffs.subset;
115                         backing->tvb    = NULL;
116                         backing->offset = 0;
117                         backing->length = 0;
118                         break;
119
120                 case TVBUFF_COMPOSITE:
121                         composite = &tvb->tvbuffs.composite;
122                         composite->tvbs                 = NULL;
123                         composite->start_offsets        = NULL;
124                         composite->end_offsets          = NULL;
125                         break;
126
127                 default:
128                         DISSECTOR_ASSERT_NOT_REACHED();
129                         break;
130         }
131 }
132
133
134 tvbuff_t*
135 tvb_new(const tvbuff_type type)
136 {
137         tvbuff_t        *tvb;
138
139 #if GLIB_CHECK_VERSION(2,10,0)
140         tvb = g_slice_new(tvbuff_t);
141 #else
142         tvb = g_chunk_new(tvbuff_t, tvbuff_mem_chunk);
143 #endif
144
145         tvb_init(tvb, type);
146
147         return tvb;
148 }
149
150 static tvbuff_t*
151 tvb_new_with_subset(const guint subset_tvb_offset, const guint subset_tvb_length)
152 {
153         tvbuff_t *tvb = tvb_new(TVBUFF_SUBSET);
154         tvb->tvbuffs.subset.offset = subset_tvb_offset;
155         tvb->tvbuffs.subset.length = subset_tvb_length;
156
157         return tvb;
158 }
159
160 void
161 tvb_free(tvbuff_t* tvb)
162 {
163         tvbuff_t        *member_tvb;
164         tvb_comp_t      *composite;
165         GSList          *slist;
166
167         tvb->usage_count--;
168
169         if (tvb->usage_count == 0) {
170                 switch (tvb->type) {
171                 case TVBUFF_REAL_DATA:
172                         if (tvb->free_cb) {
173                                 /*
174                                  * XXX - do this with a union?
175                                  */
176                                 tvb->free_cb((gpointer)tvb->real_data);
177                         }
178                         break;
179
180                 case TVBUFF_SUBSET:
181                         /* This will be NULL if tvb_new_subset() fails because
182                          * reported_length < -1 */
183                         if (tvb->tvbuffs.subset.tvb) {
184                                 tvb_decrement_usage_count(tvb->tvbuffs.subset.tvb, 1);
185                         }
186                         break;
187
188                 case TVBUFF_COMPOSITE:
189                         composite = &tvb->tvbuffs.composite;
190                         for (slist = composite->tvbs; slist != NULL ; slist = slist->next) {
191                                 member_tvb = slist->data;
192                                 tvb_decrement_usage_count(member_tvb, 1);
193                         }
194
195                         g_slist_free(composite->tvbs);
196
197                         g_free(composite->start_offsets);
198                         g_free(composite->end_offsets);
199                         if (tvb->real_data) {
200                                 /*
201                                  * XXX - do this with a union?
202                                  */
203                                 g_free((gpointer)tvb->real_data);
204                         }
205
206                         break;
207                 }
208
209                 if (tvb->used_in) {
210                         g_slist_free(tvb->used_in);
211                 }
212
213 #if GLIB_CHECK_VERSION(2,10,0)
214                 g_slice_free(tvbuff_t, tvb);
215 #else
216                 g_chunk_free(tvb, tvbuff_mem_chunk);
217 #endif
218         }
219 }
220
221 guint
222 tvb_increment_usage_count(tvbuff_t* tvb, const guint count)
223 {
224         tvb->usage_count += count;
225
226         return tvb->usage_count;
227 }
228
229 guint
230 tvb_decrement_usage_count(tvbuff_t* tvb, const guint count)
231 {
232         if (tvb->usage_count <= count) {
233                 tvb->usage_count = 1;
234                 tvb_free(tvb);
235                 return 0;
236         }
237         else {
238                 tvb->usage_count -= count;
239                 return tvb->usage_count;
240         }
241
242 }
243
244 void
245 tvb_free_chain(tvbuff_t* tvb)
246 {
247         GSList          *slist;
248
249         /* Recursively call tvb_free_chain() */
250         for (slist = tvb->used_in; slist != NULL ; slist = slist->next) {
251                 tvb_free_chain( (tvbuff_t*)slist->data );
252         }
253
254         /* Stop the recursion */
255         tvb_free(tvb);
256 }
257
258
259
260 void
261 tvb_set_free_cb(tvbuff_t* tvb, const tvbuff_free_cb_t func)
262 {
263         DISSECTOR_ASSERT(tvb);
264         DISSECTOR_ASSERT(tvb->type == TVBUFF_REAL_DATA);
265         tvb->free_cb = func;
266 }
267
268 static void
269 add_to_used_in_list(tvbuff_t *tvb, tvbuff_t *used_in)
270 {
271         tvb->used_in = g_slist_prepend(tvb->used_in, used_in);
272         tvb_increment_usage_count(tvb, 1);
273 }
274
275 void
276 tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child)
277 {
278         DISSECTOR_ASSERT(parent && child);
279         DISSECTOR_ASSERT(parent->initialized);
280         DISSECTOR_ASSERT(child->initialized);
281         DISSECTOR_ASSERT(child->type == TVBUFF_REAL_DATA);
282         add_to_used_in_list(parent, child);
283 }
284
285 static void
286 tvb_set_real_data_no_exceptions(tvbuff_t* tvb, const guint8* data, const guint length, const gint reported_length)
287 {
288         tvb->real_data = data;
289         tvb->length = length;
290         tvb->reported_length = reported_length;
291         tvb->initialized = TRUE;
292 }
293
294 void
295 tvb_set_real_data(tvbuff_t* tvb, const guint8* data, const guint length, const gint reported_length)
296 {
297         DISSECTOR_ASSERT(tvb);
298         DISSECTOR_ASSERT(tvb->type == TVBUFF_REAL_DATA);
299         DISSECTOR_ASSERT(!tvb->initialized);
300
301         THROW_ON(reported_length < -1, ReportedBoundsError);
302
303         tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
304 }
305
306 tvbuff_t*
307 tvb_new_real_data(const guint8* data, const guint length, const gint reported_length)
308 {
309         tvbuff_t        *tvb;
310
311         THROW_ON(reported_length < -1, ReportedBoundsError);
312
313         tvb = tvb_new(TVBUFF_REAL_DATA);
314
315         tvb_set_real_data_no_exceptions(tvb, data, length, reported_length);
316
317         /*
318          * This is the top-level real tvbuff for this data source,
319          * so its data source tvbuff is itself.
320          */
321         tvb->ds_tvb = tvb;
322
323         return tvb;
324 }
325
326 tvbuff_t*
327 tvb_new_child_real_data(tvbuff_t *parent, const guint8* data, const guint length, const gint reported_length)
328 {
329         tvbuff_t *tvb = tvb_new_real_data(data, length, reported_length);
330         if (tvb) {
331                 tvb_set_child_real_data_tvbuff (parent, tvb);
332         }
333
334         return tvb;
335 }
336
337 /* Computes the absolute offset and length based on a possibly-negative offset
338  * and a length that is possible -1 (which means "to the end of the data").
339  * Returns TRUE/FALSE indicating whether the offset is in bounds or
340  * not. The integer ptrs are modified with the new offset and length.
341  * No exception is thrown.
342  *
343  * XXX - we return TRUE, not FALSE, if the offset is positive and right
344  * after the end of the tvbuff (i.e., equal to the length).  We do this
345  * so that a dissector constructing a subset tvbuff for the next protocol
346  * will get a zero-length tvbuff, not an exception, if there's no data
347  * left for the next protocol - we want the next protocol to be the one
348  * that gets an exception, so the error is reported as an error in that
349  * protocol rather than the containing protocol.  */
350 static gboolean
351 compute_offset_length(const guint tvb_length_val, const guint tvb_reported_length_val, const gint offset, const gint length_val,
352                 guint *offset_ptr, guint *length_ptr, int *exception)
353 {
354         DISSECTOR_ASSERT(offset_ptr);
355         DISSECTOR_ASSERT(length_ptr);
356
357         /* Compute the offset */
358         if (offset >= 0) {
359                 /* Positive offset - relative to the beginning of the packet. */
360                 if ((guint) offset > tvb_reported_length_val) {
361                         if (exception) {
362                                 *exception = ReportedBoundsError;
363                         }
364                         return FALSE;
365                 }
366                 else if ((guint) offset > tvb_length_val) {
367                         if (exception) {
368                                 *exception = BoundsError;
369                         }
370                         return FALSE;
371                 }
372                 else {
373                         *offset_ptr = offset;
374                 }
375         }
376         else {
377                 /* Negative offset - relative to the end of the packet. */
378                 if ((guint) -offset > tvb_reported_length_val) {
379                         if (exception) {
380                                 *exception = ReportedBoundsError;
381                         }
382                         return FALSE;
383                 }
384                 else if ((guint) -offset > tvb_length_val) {
385                         if (exception) {
386                                 *exception = BoundsError;
387                         }
388                         return FALSE;
389                 }
390                 else {
391                         *offset_ptr = tvb_length_val + offset;
392                 }
393         }
394
395         /* Compute the length */
396         if (length_val < -1) {
397                 if (exception) {
398                         /* XXX - ReportedBoundsError? */
399                         *exception = BoundsError;
400                 }
401                 return FALSE;
402         }
403         else if (length_val == -1) {
404                 *length_ptr = tvb_length_val - *offset_ptr;
405         }
406         else {
407                 *length_ptr = length_val;
408         }
409
410         return TRUE;
411 }
412
413
414 static gboolean
415 check_offset_length_no_exception(const guint tvb_length_val, const guint tvb_reported_length_val, const gint offset, gint const length_val,
416                 guint *offset_ptr, guint *length_ptr, int *exception)
417 {
418         guint   end_offset;
419
420         if (!compute_offset_length(tvb_length_val, tvb_reported_length_val, offset, length_val, offset_ptr, length_ptr, exception)) {
421                 return FALSE;
422         }
423
424         /*
425          * Compute the offset of the first byte past the length.
426          */
427         end_offset = *offset_ptr + *length_ptr;
428
429         /*
430          * Check for an overflow, and clamp "end_offset" at the maximum
431          * if we got an overflow - that should force us to indicate that
432          * we're past the end of the tvbuff.
433          */
434         if (end_offset < *offset_ptr)
435                 end_offset = UINT_MAX;
436
437         /*
438          * Check whether that offset goes more than one byte past the
439          * end of the buffer.
440          *
441          * If not, return TRUE; otherwise, return FALSE and, if "exception"
442          * is non-null, return the appropriate exception through it.
443          */
444         if (end_offset <= tvb_length_val) {
445                 return TRUE;
446         }
447         else if (end_offset <= tvb_reported_length_val) {
448                 if (exception) {
449                         *exception = BoundsError;
450                 }
451         }
452         else {
453                 if (exception) {
454                         *exception = ReportedBoundsError;
455                 }
456         }
457
458         return FALSE;
459 }
460
461 /* Checks (+/-) offset and length and throws an exception if
462  * either is out of bounds. Sets integer ptrs to the new offset
463  * and length. */
464 static void
465 check_offset_length(const guint tvb_length_val, const guint tvb_reported_length_val, const gint offset, gint const length_val,
466                 guint *offset_ptr, guint *length_ptr)
467 {
468         int exception = 0;
469
470         if (!check_offset_length_no_exception(tvb_length_val, tvb_reported_length_val, offset, length_val, offset_ptr, length_ptr, &exception)) {
471                 DISSECTOR_ASSERT(exception > 0);
472                 THROW(exception);
473         }
474 }
475
476 static void
477 tvb_set_subset_no_exceptions(tvbuff_t *tvb, tvbuff_t *backing, const gint reported_length)
478 {
479         tvb->tvbuffs.subset.tvb         = backing;
480         tvb->length                     = tvb->tvbuffs.subset.length;
481
482         if (reported_length == -1) {
483                 tvb->reported_length    = backing->reported_length - tvb->tvbuffs.subset.offset;
484         }
485         else {
486                 tvb->reported_length    = reported_length;
487         }
488         tvb->initialized                = TRUE;
489         add_to_used_in_list(backing, tvb);
490
491         /* Optimization. If the backing buffer has a pointer to contiguous, real data,
492          * then we can point directly to our starting offset in that buffer */
493         if (backing->real_data != NULL) {
494                 tvb->real_data = backing->real_data + tvb->tvbuffs.subset.offset;
495         }
496 }
497
498 void
499 tvb_set_subset(tvbuff_t *tvb, tvbuff_t *backing,
500                 const gint backing_offset, const gint backing_length, const gint reported_length)
501 {
502         DISSECTOR_ASSERT(tvb);
503         DISSECTOR_ASSERT(tvb->type == TVBUFF_SUBSET);
504         DISSECTOR_ASSERT(!tvb->initialized);
505
506         THROW_ON(reported_length < -1, ReportedBoundsError);
507
508         check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
509                         &tvb->tvbuffs.subset.offset,
510                         &tvb->tvbuffs.subset.length);
511
512         tvb_set_subset_no_exceptions(tvb, backing, reported_length);
513 }
514
515 tvbuff_t*
516 tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
517 {
518         tvbuff_t        *tvb;
519         guint           subset_tvb_offset;
520         guint           subset_tvb_length;
521
522         DISSECTOR_ASSERT(backing && backing->initialized);
523
524         THROW_ON(reported_length < -1, ReportedBoundsError);
525
526         check_offset_length(backing->length, backing->reported_length, backing_offset, backing_length,
527                         &subset_tvb_offset,
528                         &subset_tvb_length);
529
530         tvb = tvb_new_with_subset(subset_tvb_offset, subset_tvb_length);
531
532         tvb_set_subset_no_exceptions(tvb, backing, reported_length);
533
534         /*
535          * The top-level data source of this tvbuff is the top-level
536          * data source of its parent.
537          */
538         tvb->ds_tvb = backing->ds_tvb;
539
540         return tvb;
541 }
542
543 tvbuff_t*
544 tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
545 {
546         tvbuff_t        *tvb;
547         guint           subset_tvb_offset;
548         guint           subset_tvb_length;
549
550         check_offset_length(backing->length, backing->reported_length, backing_offset, -1 /* backing_length */,
551                         &subset_tvb_offset,
552                         &subset_tvb_length);
553
554         tvb = tvb_new_with_subset(subset_tvb_offset, subset_tvb_length);
555
556         tvb_set_subset_no_exceptions(tvb, backing, -1 /* reported_length */);
557
558         /*
559          * The top-level data source of this tvbuff is the top-level
560          * data source of its parent.
561          */
562         tvb->ds_tvb = backing->ds_tvb;
563
564         return tvb;
565 }
566
567 void
568 tvb_composite_append(tvbuff_t* tvb, tvbuff_t* member)
569 {
570         tvb_comp_t      *composite;
571
572         DISSECTOR_ASSERT(tvb && !tvb->initialized);
573         DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
574         composite = &tvb->tvbuffs.composite;
575         composite->tvbs = g_slist_append( composite->tvbs, member );
576         add_to_used_in_list(tvb, member);
577 }
578
579 void
580 tvb_composite_prepend(tvbuff_t* tvb, tvbuff_t* member)
581 {
582         tvb_comp_t      *composite;
583
584         DISSECTOR_ASSERT(tvb && !tvb->initialized);
585         DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
586         composite = &tvb->tvbuffs.composite;
587         composite->tvbs = g_slist_prepend( composite->tvbs, member );
588         add_to_used_in_list(tvb, member);
589 }
590
591 tvbuff_t*
592 tvb_new_composite(void)
593 {
594         return tvb_new(TVBUFF_COMPOSITE);
595 }
596
597 void
598 tvb_composite_finalize(tvbuff_t* tvb)
599 {
600         GSList          *slist;
601         guint           num_members;
602         tvbuff_t        *member_tvb;
603         tvb_comp_t      *composite;
604         int             i = 0;
605
606         DISSECTOR_ASSERT(tvb && !tvb->initialized);
607         DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
608         DISSECTOR_ASSERT(tvb->length == 0);
609         DISSECTOR_ASSERT(tvb->reported_length == 0);
610
611         composite = &tvb->tvbuffs.composite;
612         num_members = g_slist_length(composite->tvbs);
613
614         composite->start_offsets = g_new(guint, num_members);
615         composite->end_offsets = g_new(guint, num_members);
616
617         for (slist = composite->tvbs; slist != NULL; slist = slist->next) {
618                 DISSECTOR_ASSERT((guint) i < num_members);
619                 member_tvb = slist->data;
620                 composite->start_offsets[i] = tvb->length;
621                 tvb->length += member_tvb->length;
622                 tvb->reported_length += member_tvb->reported_length;
623                 composite->end_offsets[i] = tvb->length - 1;
624                 i++;
625         }
626
627         tvb->initialized = TRUE;
628 }
629
630
631
632 guint
633 tvb_length(const tvbuff_t* tvb)
634 {
635         DISSECTOR_ASSERT(tvb && tvb->initialized);
636
637         return tvb->length;
638 }
639
640 gint
641 tvb_length_remaining(const tvbuff_t *tvb, const gint offset)
642 {
643         guint   abs_offset, abs_length;
644
645         DISSECTOR_ASSERT(tvb && tvb->initialized);
646
647         if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
648                 return abs_length;
649         }
650         else {
651                 return -1;
652         }
653 }
654
655 guint
656 tvb_ensure_length_remaining(const tvbuff_t *tvb, const gint offset)
657 {
658         guint   abs_offset, abs_length;
659         int     exception;
660
661         DISSECTOR_ASSERT(tvb && tvb->initialized);
662
663         if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, &exception)) {
664                 THROW(exception);
665         }
666         if (abs_length == 0) {
667                 /*
668                  * This routine ensures there's at least one byte available.
669                  * There aren't any bytes available, so throw the appropriate
670                  * exception.
671                  */
672                 if (abs_offset >= tvb->reported_length)
673                         THROW(ReportedBoundsError);
674                 else
675                         THROW(BoundsError);
676         }
677         return abs_length;
678 }
679
680
681
682
683 /* Validates that 'length' bytes are available starting from
684  * offset (pos/neg). Does not throw an exception. */
685 gboolean
686 tvb_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
687 {
688         guint           abs_offset, abs_length;
689
690         DISSECTOR_ASSERT(tvb && tvb->initialized);
691
692         if (!compute_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length, NULL))
693                 return FALSE;
694
695         if (abs_offset + abs_length <= tvb->length) {
696                 return TRUE;
697         }
698         else {
699                 return FALSE;
700         }
701 }
702
703 /* Validates that 'length' bytes are available starting from
704  * offset (pos/neg). Throws an exception if they aren't. */
705 void
706 tvb_ensure_bytes_exist(const tvbuff_t *tvb, const gint offset, const gint length)
707 {
708         guint           abs_offset, abs_length;
709
710         DISSECTOR_ASSERT(tvb && tvb->initialized);
711
712         /*
713          * -1 doesn't mean "until end of buffer", as that's pointless
714          * for this routine.  We must treat it as a Really Large Positive
715          * Number, so that we throw an exception; we throw
716          * ReportedBoundsError, as if it were past even the end of a
717          * reassembled packet, and past the end of even the data we
718          * didn't capture.
719          *
720          * We do the same with other negative lengths.
721          */
722         if (length < 0) {
723                 THROW(ReportedBoundsError);
724         }
725         check_offset_length(tvb->length, tvb->reported_length, offset, length, &abs_offset, &abs_length);
726 }
727
728 gboolean
729 tvb_offset_exists(const tvbuff_t *tvb, const gint offset)
730 {
731         guint           abs_offset, abs_length;
732
733         DISSECTOR_ASSERT(tvb && tvb->initialized);
734         if (!compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL))
735                 return FALSE;
736
737         if (abs_offset < tvb->length) {
738                 return TRUE;
739         }
740         else {
741                 return FALSE;
742         }
743 }
744
745 guint
746 tvb_reported_length(const tvbuff_t* tvb)
747 {
748         DISSECTOR_ASSERT(tvb && tvb->initialized);
749
750         return tvb->reported_length;
751 }
752
753 gint
754 tvb_reported_length_remaining(const tvbuff_t *tvb, const gint offset)
755 {
756         guint   abs_offset, abs_length;
757
758         DISSECTOR_ASSERT(tvb && tvb->initialized);
759
760         if (compute_offset_length(tvb->length, tvb->reported_length, offset, -1, &abs_offset, &abs_length, NULL)) {
761                 if (tvb->reported_length >= abs_offset)
762                         return tvb->reported_length - abs_offset;
763                 else
764                         return -1;
765         }
766         else {
767                 return -1;
768         }
769 }
770
771 /* Set the reported length of a tvbuff to a given value; used for protocols
772    whose headers contain an explicit length and where the calling
773    dissector's payload may include padding as well as the packet for
774    this protocol.
775
776    Also adjusts the data length. */
777 void
778 tvb_set_reported_length(tvbuff_t* tvb, const guint reported_length)
779 {
780         DISSECTOR_ASSERT(tvb && tvb->initialized);
781
782         if (reported_length > tvb->reported_length)
783                 THROW(ReportedBoundsError);
784
785         tvb->reported_length = reported_length;
786         if (reported_length < tvb->length)
787                 tvb->length = reported_length;
788 }
789
790
791 #if 0
792 static const guint8*
793 first_real_data_ptr(tvbuff_t *tvb)
794 {
795         tvbuff_t        *member;
796
797         switch(tvb->type) {
798                 case TVBUFF_REAL_DATA:
799                         return tvb->real_data;
800                 case TVBUFF_SUBSET:
801                         member = tvb->tvbuffs.subset.tvb;
802                         return first_real_data_ptr(member);
803                 case TVBUFF_COMPOSITE:
804                         member = tvb->tvbuffs.composite.tvbs->data;
805                         return first_real_data_ptr(member);
806         }
807
808         DISSECTOR_ASSERT_NOT_REACHED();
809         return NULL;
810 }
811 #endif
812
813 static guint
814 offset_from_real_beginning(const tvbuff_t *tvb, const guint counter)
815 {
816         tvbuff_t        *member;
817
818         switch(tvb->type) {
819                 case TVBUFF_REAL_DATA:
820                         return counter;
821                 case TVBUFF_SUBSET:
822                         member = tvb->tvbuffs.subset.tvb;
823                         return offset_from_real_beginning(member, counter + tvb->tvbuffs.subset.offset);
824                 case TVBUFF_COMPOSITE:
825                         member = tvb->tvbuffs.composite.tvbs->data;
826                         return offset_from_real_beginning(member, counter);
827         }
828
829         DISSECTOR_ASSERT_NOT_REACHED();
830         return 0;
831 }
832
833 guint
834 tvb_offset_from_real_beginning(const tvbuff_t *tvb)
835 {
836         return offset_from_real_beginning(tvb, 0);
837 }
838
839 static const guint8*
840 composite_ensure_contiguous_no_exception(tvbuff_t *tvb, const guint abs_offset,
841                 const guint abs_length)
842 {
843         guint           i, num_members;
844         tvb_comp_t      *composite;
845         tvbuff_t        *member_tvb = NULL;
846         guint           member_offset, member_length;
847         GSList          *slist;
848
849         DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
850
851         /* Maybe the range specified by offset/length
852          * is contiguous inside one of the member tvbuffs */
853         composite = &tvb->tvbuffs.composite;
854         num_members = g_slist_length(composite->tvbs);
855
856         for (i = 0; i < num_members; i++) {
857                 if (abs_offset <= composite->end_offsets[i]) {
858                         slist = g_slist_nth(composite->tvbs, i);
859                         member_tvb = slist->data;
860                         break;
861                 }
862         }
863         DISSECTOR_ASSERT(member_tvb);
864
865         if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
866                                 abs_length, &member_offset, &member_length, NULL)) {
867
868                 /*
869                  * The range is, in fact, contiguous within member_tvb.
870                  */
871                 DISSECTOR_ASSERT(!tvb->real_data);
872                 return ensure_contiguous_no_exception(member_tvb, member_offset, member_length, NULL);
873         }
874         else {
875                 tvb->real_data = tvb_memdup(tvb, 0, -1);
876                 return tvb->real_data + abs_offset;
877         }
878
879         DISSECTOR_ASSERT_NOT_REACHED();
880 }
881
882 static const guint8*
883 ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint length,
884                 int *exception)
885 {
886         guint   abs_offset, abs_length;
887
888         if (!check_offset_length_no_exception(tvb->length, tvb->reported_length, offset, length,
889                 &abs_offset, &abs_length, exception)) {
890                 return NULL;
891         }
892
893         /*
894          * We know that all the data is present in the tvbuff, so
895          * no exceptions should be thrown.
896          */
897         if (tvb->real_data) {
898                 return tvb->real_data + abs_offset;
899         }
900         else {
901                 switch(tvb->type) {
902                         case TVBUFF_REAL_DATA:
903                                 DISSECTOR_ASSERT_NOT_REACHED();
904                         case TVBUFF_SUBSET:
905                                 return ensure_contiguous_no_exception(tvb->tvbuffs.subset.tvb,
906                                                 abs_offset - tvb->tvbuffs.subset.offset,
907                                                 abs_length, NULL);
908                         case TVBUFF_COMPOSITE:
909                                 return composite_ensure_contiguous_no_exception(tvb, abs_offset, abs_length);
910                 }
911         }
912
913         DISSECTOR_ASSERT_NOT_REACHED();
914         return NULL;
915 }
916
917 static const guint8*
918 ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length)
919 {
920         int exception;
921         const guint8 *p;
922
923         p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
924         if (p == NULL) {
925                 DISSECTOR_ASSERT(exception > 0);
926                 THROW(exception);
927         }
928         return p;
929 }
930
931 static const guint8*
932 fast_ensure_contiguous(tvbuff_t *tvb, const gint offset, const guint length)
933 {
934         guint   end_offset;
935         guint   u_offset;
936
937         DISSECTOR_ASSERT(tvb && tvb->initialized);
938         /* We don't check for overflow in this fast path so we only handle simple types */
939         DISSECTOR_ASSERT(length <= 8);
940
941         if (offset < 0 || !tvb->real_data) {
942                 return ensure_contiguous(tvb, offset, length);
943         }
944
945         u_offset = offset;
946         end_offset = u_offset + length;
947
948         if (end_offset <= tvb->length) {
949                 return tvb->real_data + u_offset;
950         }
951
952         if (end_offset > tvb->reported_length) {
953                 THROW(ReportedBoundsError);
954         }
955         THROW(BoundsError);
956         /* not reached */
957         return NULL;
958 }
959
960 static const guint8*
961 guint8_pbrk(const guint8* haystack, size_t haystacklen, const guint8 *needles, guchar *found_needle)
962 {
963         gchar tmp[256] = { 0 };
964         const guint8 *haystack_end;
965
966         while (*needles)
967                 tmp[*needles++] = 1;
968
969         haystack_end = haystack + haystacklen;
970         while (haystack < haystack_end) {
971                 if (tmp[*haystack]) {
972                         if(found_needle)
973                                 *found_needle = *haystack;
974                         return haystack;
975                 }
976                 haystack++;
977         }
978
979         return NULL;
980 }
981
982
983
984 /************** ACCESSORS **************/
985
986 static void*
987 composite_memcpy(tvbuff_t *tvb, guint8* target, guint abs_offset, size_t abs_length)
988 {
989         guint           i, num_members;
990         tvb_comp_t      *composite;
991         tvbuff_t        *member_tvb = NULL;
992         guint           member_offset, member_length;
993         gboolean        retval;
994         GSList          *slist;
995
996         DISSECTOR_ASSERT(tvb->type == TVBUFF_COMPOSITE);
997
998         /* Maybe the range specified by offset/length
999          * is contiguous inside one of the member tvbuffs */
1000         composite = &tvb->tvbuffs.composite;
1001         num_members = g_slist_length(composite->tvbs);
1002
1003         for (i = 0; i < num_members; i++) {
1004                 if (abs_offset <= composite->end_offsets[i]) {
1005                         slist = g_slist_nth(composite->tvbs, i);
1006                         member_tvb = slist->data;
1007                         break;
1008                 }
1009         }
1010         DISSECTOR_ASSERT(member_tvb);
1011
1012         if (check_offset_length_no_exception(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i],
1013                                 (gint) abs_length, &member_offset, &member_length, NULL)) {
1014
1015                 DISSECTOR_ASSERT(!tvb->real_data);
1016                 return tvb_memcpy(member_tvb, target, member_offset, member_length);
1017         }
1018         else {
1019                 /* The requested data is non-contiguous inside
1020                  * the member tvb. We have to memcpy() the part that's in the member tvb,
1021                  * then iterate across the other member tvb's, copying their portions
1022                  * until we have copied all data.
1023                  */
1024                 retval = compute_offset_length(member_tvb->length, member_tvb->reported_length, abs_offset - composite->start_offsets[i], -1,
1025                                 &member_offset, &member_length, NULL);
1026                 DISSECTOR_ASSERT(retval);
1027
1028                 tvb_memcpy(member_tvb, target, member_offset, member_length);
1029                 abs_offset      += member_length;
1030                 abs_length      -= member_length;
1031
1032                 /* Recurse */
1033                 if (abs_length > 0) {
1034                         composite_memcpy(tvb, target + member_length, abs_offset, abs_length);
1035                 }
1036
1037                 return target;
1038         }
1039
1040         DISSECTOR_ASSERT_NOT_REACHED();
1041 }
1042
1043 void*
1044 tvb_memcpy(tvbuff_t *tvb, void* target, const gint offset, size_t length)
1045 {
1046         guint   abs_offset, abs_length;
1047
1048         DISSECTOR_ASSERT(tvb && tvb->initialized);
1049
1050         /*
1051          * XXX - we should eliminate the "length = -1 means 'to the end
1052          * of the tvbuff'" convention, and use other means to achieve
1053          * that; this would let us eliminate a bunch of checks for
1054          * negative lengths in cases where the protocol has a 32-bit
1055          * length field.
1056          *
1057          * Allowing -1 but throwing an assertion on other negative
1058          * lengths is a bit more work with the length being a size_t;
1059          * instead, we check for a length <= 2^31-1.
1060          */
1061         DISSECTOR_ASSERT(length <= 0x7FFFFFFF);
1062         check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
1063
1064         if (tvb->real_data) {
1065                 return memcpy(target, tvb->real_data + abs_offset, abs_length);
1066         }
1067
1068         switch(tvb->type) {
1069                 case TVBUFF_REAL_DATA:
1070                         DISSECTOR_ASSERT_NOT_REACHED();
1071
1072                 case TVBUFF_SUBSET:
1073                         return tvb_memcpy(tvb->tvbuffs.subset.tvb, target,
1074                                         abs_offset - tvb->tvbuffs.subset.offset,
1075                                         abs_length);
1076
1077                 case TVBUFF_COMPOSITE:
1078                         return composite_memcpy(tvb, target, offset, length);
1079         }
1080
1081         DISSECTOR_ASSERT_NOT_REACHED();
1082         return NULL;
1083 }
1084
1085
1086 /*
1087  * XXX - this doesn't treat a length of -1 as an error.
1088  * If it did, this could replace some code that calls
1089  * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
1090  * data to it.
1091  *
1092  * "composite_ensure_contiguous_no_exception()" depends on -1 not being
1093  * an error; does anything else depend on this routine treating -1 as
1094  * meaning "to the end of the buffer"?
1095  */
1096 void*
1097 tvb_memdup(tvbuff_t *tvb, const gint offset, size_t length)
1098 {
1099         guint   abs_offset, abs_length;
1100         void    *duped;
1101
1102         DISSECTOR_ASSERT(tvb && tvb->initialized);
1103
1104         check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
1105
1106         duped = g_malloc(abs_length);
1107         return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1108 }
1109
1110 /*
1111  * XXX - this doesn't treat a length of -1 as an error.
1112  * If it did, this could replace some code that calls
1113  * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
1114  * data to it.
1115  *
1116  * "composite_ensure_contiguous_no_exception()" depends on -1 not being
1117  * an error; does anything else depend on this routine treating -1 as
1118  * meaning "to the end of the buffer"?
1119  *
1120  * This function allocates memory from a buffer with packet lifetime.
1121  * You do not have to free this buffer, it will be automatically freed
1122  * when wireshark starts decoding the next packet.
1123  * Do not use this function if you want the allocated memory to be persistent
1124  * after the current packet has been dissected.
1125  */
1126 void*
1127 ep_tvb_memdup(tvbuff_t *tvb, const gint offset, size_t length)
1128 {
1129         guint   abs_offset, abs_length;
1130         void    *duped;
1131
1132         DISSECTOR_ASSERT(tvb && tvb->initialized);
1133
1134         check_offset_length(tvb->length, tvb->reported_length, offset, (gint) length, &abs_offset, &abs_length);
1135
1136         duped = ep_alloc(abs_length);
1137         return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1138 }
1139
1140
1141
1142 const guint8*
1143 tvb_get_ptr(tvbuff_t *tvb, const gint offset, const gint length)
1144 {
1145         return ensure_contiguous(tvb, offset, length);
1146 }
1147
1148 /* ---------------- */
1149 guint8
1150 tvb_get_guint8(tvbuff_t *tvb, const gint offset)
1151 {
1152         const guint8* ptr;
1153
1154         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint8));
1155         return *ptr;
1156 }
1157
1158 guint16
1159 tvb_get_ntohs(tvbuff_t *tvb, const gint offset)
1160 {
1161         const guint8* ptr;
1162
1163         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
1164         return pntohs(ptr);
1165 }
1166
1167 guint32
1168 tvb_get_ntoh24(tvbuff_t *tvb, const gint offset)
1169 {
1170         const guint8* ptr;
1171
1172         ptr = fast_ensure_contiguous(tvb, offset, 3);
1173         return pntoh24(ptr);
1174 }
1175
1176 guint32
1177 tvb_get_ntohl(tvbuff_t *tvb, const gint offset)
1178 {
1179         const guint8* ptr;
1180
1181         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1182         return pntohl(ptr);
1183 }
1184
1185 guint64
1186 tvb_get_ntoh40(tvbuff_t *tvb, const gint offset)
1187 {
1188         const guint8* ptr;
1189
1190         ptr = fast_ensure_contiguous(tvb, offset, 5);
1191         return pntoh40(ptr);
1192 }
1193
1194 guint64
1195 tvb_get_ntoh48(tvbuff_t *tvb, const gint offset)
1196 {
1197         const guint8* ptr;
1198
1199         ptr = fast_ensure_contiguous(tvb, offset, 6);
1200         return pntoh48(ptr);
1201 }
1202
1203 guint64
1204 tvb_get_ntoh56(tvbuff_t *tvb, const gint offset)
1205 {
1206         const guint8* ptr;
1207
1208         ptr = fast_ensure_contiguous(tvb, offset, 7);
1209         return pntoh56(ptr);
1210 }
1211
1212 guint64
1213 tvb_get_ntoh64(tvbuff_t *tvb, const gint offset)
1214 {
1215         const guint8* ptr;
1216
1217         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
1218         return pntoh64(ptr);
1219 }
1220
1221 /*
1222  * Stuff for IEEE float handling on platforms that don't have IEEE
1223  * format as the native floating-point format.
1224  *
1225  * For now, we treat only the VAX as such a platform.
1226  *
1227  * XXX - other non-IEEE boxes that can run UNIX include some Crays,
1228  * and possibly other machines.
1229  *
1230  * It appears that the official Linux port to System/390 and
1231  * zArchitecture uses IEEE format floating point (not a
1232  * huge surprise).
1233  *
1234  * I don't know whether there are any other machines that
1235  * could run Wireshark and that don't use IEEE format.
1236  * As far as I know, all of the main commercial microprocessor
1237  * families on which OSes that support Wireshark can run
1238  * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
1239  * IA-64, and so on).
1240  */
1241
1242 #if defined(vax)
1243
1244 #include <math.h>
1245
1246 /*
1247  * Single-precision.
1248  */
1249 #define IEEE_SP_NUMBER_WIDTH    32      /* bits in number */
1250 #define IEEE_SP_EXP_WIDTH       8       /* bits in exponent */
1251 #define IEEE_SP_MANTISSA_WIDTH  23      /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1252
1253 #define IEEE_SP_SIGN_MASK       0x80000000
1254 #define IEEE_SP_EXPONENT_MASK   0x7F800000
1255 #define IEEE_SP_MANTISSA_MASK   0x007FFFFF
1256 #define IEEE_SP_INFINITY        IEEE_SP_EXPONENT_MASK
1257
1258 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1259 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1260 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1261
1262 static int
1263 ieee_float_is_zero(const guint32 w)
1264 {
1265         return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1266 }
1267
1268 static gfloat
1269 get_ieee_float(const guint32 w)
1270 {
1271         long sign;
1272         long exponent;
1273         long mantissa;
1274
1275         sign = w & IEEE_SP_SIGN_MASK;
1276         exponent = w & IEEE_SP_EXPONENT_MASK;
1277         mantissa = w & IEEE_SP_MANTISSA_MASK;
1278
1279         if (ieee_float_is_zero(w)) {
1280                 /* number is zero, unnormalized, or not-a-number */
1281                 return 0.0;
1282         }
1283 #if 0
1284         /*
1285          * XXX - how to handle this?
1286          */
1287         if (IEEE_SP_INFINITY == exponent) {
1288                 /*
1289                  * number is positive or negative infinity, or a special value
1290                  */
1291                 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1292         }
1293 #endif
1294
1295         exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1296                 IEEE_SP_MANTISSA_WIDTH;
1297         mantissa |= IEEE_SP_IMPLIED_BIT;
1298
1299         if (sign)
1300                 return -mantissa * pow(2, exponent);
1301         else
1302                 return mantissa * pow(2, exponent);
1303 }
1304
1305 /*
1306  * Double-precision.
1307  * We assume that if you don't have IEEE floating-point, you have a
1308  * compiler that understands 64-bit integral quantities.
1309  */
1310 #define IEEE_DP_NUMBER_WIDTH    64      /* bits in number */
1311 #define IEEE_DP_EXP_WIDTH       11      /* bits in exponent */
1312 #define IEEE_DP_MANTISSA_WIDTH  52      /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1313
1314 #define IEEE_DP_SIGN_MASK       0x8000000000000000LL
1315 #define IEEE_DP_EXPONENT_MASK   0x7FF0000000000000LL
1316 #define IEEE_DP_MANTISSA_MASK   0x000FFFFFFFFFFFFFLL
1317 #define IEEE_DP_INFINITY        IEEE_DP_EXPONENT_MASK
1318
1319 #define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
1320 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1321 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1322
1323 static int
1324 ieee_double_is_zero(const guint64 w)
1325 {
1326         return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1327 }
1328
1329 static gdouble
1330 get_ieee_double(const guint64 w)
1331 {
1332         gint64 sign;
1333         gint64 exponent;
1334         gint64 mantissa;
1335
1336         sign = w & IEEE_DP_SIGN_MASK;
1337         exponent = w & IEEE_DP_EXPONENT_MASK;
1338         mantissa = w & IEEE_DP_MANTISSA_MASK;
1339
1340         if (ieee_double_is_zero(w)) {
1341                 /* number is zero, unnormalized, or not-a-number */
1342                 return 0.0;
1343         }
1344 #if 0
1345         /*
1346          * XXX - how to handle this?
1347          */
1348         if (IEEE_DP_INFINITY == exponent) {
1349                 /*
1350                  * number is positive or negative infinity, or a special value
1351                  */
1352                 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1353         }
1354 #endif
1355
1356         exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1357                 IEEE_DP_MANTISSA_WIDTH;
1358         mantissa |= IEEE_DP_IMPLIED_BIT;
1359
1360         if (sign)
1361                 return -mantissa * pow(2, exponent);
1362         else
1363                 return mantissa * pow(2, exponent);
1364 }
1365 #endif
1366
1367 /*
1368  * Fetches an IEEE single-precision floating-point number, in
1369  * big-endian form, and returns a "float".
1370  *
1371  * XXX - should this be "double", in case there are IEEE single-
1372  * precision numbers that won't fit in some platform's native
1373  * "float" format?
1374  */
1375 gfloat
1376 tvb_get_ntohieee_float(tvbuff_t *tvb, const int offset)
1377 {
1378 #if defined(vax)
1379         return get_ieee_float(tvb_get_ntohl(tvb, offset));
1380 #else
1381         union {
1382                 gfloat f;
1383                 guint32 w;
1384         } ieee_fp_union;
1385
1386         ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1387         return ieee_fp_union.f;
1388 #endif
1389 }
1390
1391 /*
1392  * Fetches an IEEE double-precision floating-point number, in
1393  * big-endian form, and returns a "double".
1394  */
1395 gdouble
1396 tvb_get_ntohieee_double(tvbuff_t *tvb, const int offset)
1397 {
1398 #if defined(vax)
1399         union {
1400                 guint32 w[2];
1401                 guint64 dw;
1402         } ieee_fp_union;
1403 #else
1404         union {
1405                 gdouble d;
1406                 guint32 w[2];
1407         } ieee_fp_union;
1408 #endif
1409
1410 #ifdef WORDS_BIGENDIAN
1411         ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1412         ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1413 #else
1414         ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1415         ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1416 #endif
1417 #if defined(vax)
1418         return get_ieee_double(ieee_fp_union.dw);
1419 #else
1420         return ieee_fp_union.d;
1421 #endif
1422 }
1423
1424 guint16
1425 tvb_get_letohs(tvbuff_t *tvb, const gint offset)
1426 {
1427         const guint8* ptr;
1428
1429         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint16));
1430         return pletohs(ptr);
1431 }
1432
1433 guint32
1434 tvb_get_letoh24(tvbuff_t *tvb, const gint offset)
1435 {
1436         const guint8* ptr;
1437
1438         ptr = fast_ensure_contiguous(tvb, offset, 3);
1439         return pletoh24(ptr);
1440 }
1441
1442 guint32
1443 tvb_get_letohl(tvbuff_t *tvb, const gint offset)
1444 {
1445         const guint8* ptr;
1446
1447         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1448         return pletohl(ptr);
1449 }
1450
1451 guint64
1452 tvb_get_letoh40(tvbuff_t *tvb, const gint offset)
1453 {
1454         const guint8* ptr;
1455
1456         ptr = fast_ensure_contiguous(tvb, offset, 5);
1457         return pletoh40(ptr);
1458 }
1459
1460 guint64
1461 tvb_get_letoh48(tvbuff_t *tvb, const gint offset)
1462 {
1463         const guint8* ptr;
1464
1465         ptr = fast_ensure_contiguous(tvb, offset, 6);
1466         return pletoh48(ptr);
1467 }
1468
1469 guint64
1470 tvb_get_letoh56(tvbuff_t *tvb, const gint offset)
1471 {
1472         const guint8* ptr;
1473
1474         ptr = fast_ensure_contiguous(tvb, offset, 7);
1475         return pletoh56(ptr);
1476 }
1477
1478 guint64
1479 tvb_get_letoh64(tvbuff_t *tvb, const gint offset)
1480 {
1481         const guint8* ptr;
1482
1483         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint64));
1484         return pletoh64(ptr);
1485 }
1486
1487 /*
1488  * Fetches an IEEE single-precision floating-point number, in
1489  * little-endian form, and returns a "float".
1490  *
1491  * XXX - should this be "double", in case there are IEEE single-
1492  * precision numbers that won't fit in some platform's native
1493  * "float" format?
1494  */
1495 gfloat
1496 tvb_get_letohieee_float(tvbuff_t *tvb, const int offset)
1497 {
1498 #if defined(vax)
1499         return get_ieee_float(tvb_get_letohl(tvb, offset));
1500 #else
1501         union {
1502                 gfloat f;
1503                 guint32 w;
1504         } ieee_fp_union;
1505
1506         ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1507         return ieee_fp_union.f;
1508 #endif
1509 }
1510
1511 /*
1512  * Fetches an IEEE double-precision floating-point number, in
1513  * little-endian form, and returns a "double".
1514  */
1515 gdouble
1516 tvb_get_letohieee_double(tvbuff_t *tvb, const int offset)
1517 {
1518 #if defined(vax)
1519         union {
1520                 guint32 w[2];
1521                 guint64 dw;
1522         } ieee_fp_union;
1523 #else
1524         union {
1525                 gdouble d;
1526                 guint32 w[2];
1527         } ieee_fp_union;
1528 #endif
1529
1530 #ifdef WORDS_BIGENDIAN
1531         ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1532         ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1533 #else
1534         ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1535         ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1536 #endif
1537 #if defined(vax)
1538         return get_ieee_double(ieee_fp_union.dw);
1539 #else
1540         return ieee_fp_union.d;
1541 #endif
1542 }
1543
1544 /* Fetch an IPv4 address, in network byte order.
1545  * We do *not* convert them to host byte order; we leave them in
1546  * network byte order. */
1547 guint32
1548 tvb_get_ipv4(tvbuff_t *tvb, const gint offset)
1549 {
1550         const guint8* ptr;
1551         guint32 addr;
1552
1553         ptr = fast_ensure_contiguous(tvb, offset, sizeof(guint32));
1554         memcpy(&addr, ptr, sizeof addr);
1555         return addr;
1556 }
1557
1558 /* Fetch an IPv6 address. */
1559 void
1560 tvb_get_ipv6(tvbuff_t *tvb, const gint offset, struct e_in6_addr *addr)
1561 {
1562         const guint8* ptr;
1563
1564         ptr = ensure_contiguous(tvb, offset, sizeof(*addr));
1565         memcpy(addr, ptr, sizeof *addr);
1566 }
1567
1568 /* Fetch a GUID. */
1569 void
1570 tvb_get_ntohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid)
1571 {
1572         ensure_contiguous(tvb, offset, sizeof(*guid));
1573         guid->data1 = tvb_get_ntohl(tvb, offset);
1574         guid->data2 = tvb_get_ntohs(tvb, offset + 4);
1575         guid->data3 = tvb_get_ntohs(tvb, offset + 6);
1576         tvb_memcpy(tvb, guid->data4, offset + 8, sizeof guid->data4);
1577 }
1578
1579 void
1580 tvb_get_letohguid(tvbuff_t *tvb, const gint offset, e_guid_t *guid)
1581 {
1582         ensure_contiguous(tvb, offset, sizeof(*guid));
1583         guid->data1 = tvb_get_letohl(tvb, offset);
1584         guid->data2 = tvb_get_letohs(tvb, offset + 4);
1585         guid->data3 = tvb_get_letohs(tvb, offset + 6);
1586         tvb_memcpy(tvb, guid->data4, offset + 8, sizeof guid->data4);
1587 }
1588
1589 /*
1590  * NOTE: to support code written when proto_tree_add_item() took a
1591  * gboolean as its last argument, with FALSE meaning "big-endian"
1592  * and TRUE meaning "little-endian", we treat any non-zero value of
1593  * "representation" as meaning "little-endian".
1594  */
1595 void
1596 tvb_get_guid(tvbuff_t *tvb, const gint offset, e_guid_t *guid, const guint representation)
1597 {
1598         if (representation) {
1599                 tvb_get_letohguid(tvb, offset, guid);
1600         } else {
1601                 tvb_get_ntohguid(tvb, offset, guid);
1602         }
1603 }
1604
1605 static const guint8 bit_mask8[] = {
1606         0xff,
1607         0x7f,
1608         0x3f,
1609         0x1f,
1610         0x0f,
1611         0x07,
1612         0x03,
1613         0x01
1614 };
1615
1616 /* Bit offset mask for number of bits = 8 - 16 */
1617 static const guint16 bit_mask16[] = {
1618         0xffff,
1619         0x7fff,
1620         0x3fff,
1621         0x1fff,
1622         0x0fff,
1623         0x07ff,
1624         0x03ff,
1625         0x01ff
1626 };
1627
1628 /* Get 1 - 8 bits */
1629 guint8
1630 tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits)
1631 {
1632         gint    offset;
1633         guint16 value = 0;
1634         guint8  tot_no_bits;
1635
1636         if (no_of_bits>8) {
1637                 DISSECTOR_ASSERT_NOT_REACHED();
1638         }
1639         /* Byte align offset */
1640         offset = bit_offset>>3;
1641
1642         /* Find out which mask to use for the most significant octet
1643          * by convering bit_offset into the offset into the first
1644          * fetched octet.
1645          */
1646         bit_offset = bit_offset & 0x7;
1647         tot_no_bits = bit_offset+no_of_bits;
1648         if(tot_no_bits<=8){
1649                 /* Read one octet, mask off bit_offset bits and left shift out the unused bits */
1650                 value = tvb_get_guint8(tvb,offset) & bit_mask8[bit_offset];
1651                 value = value >> (8-tot_no_bits);
1652         }else{
1653                 /* Read two octets, mask off bit_offset bits and left shift out the unused bits */
1654                 value = tvb_get_ntohs(tvb,offset) & bit_mask16[bit_offset];
1655                 value = value >> (16 - tot_no_bits);
1656         }
1657
1658         return (guint8)value;
1659 }
1660
1661 void
1662 tvb_get_bits_buf(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint8 *buf, gboolean lsb0)
1663 {
1664         guint8 bit_mask, bit_shift;
1665         /* Byte align offset */
1666         gint offset = bit_offset >> 3;
1667         bit_offset = bit_offset & 0x7;
1668
1669         bit_mask = (lsb0) ? 0xff : bit_mask8[bit_offset];
1670         bit_shift = (lsb0) ? bit_offset : (8 - bit_offset);
1671
1672         if (G_LIKELY(bit_offset != 0)) {
1673                 guint16 value = (guint16) tvb_get_guint8(tvb, offset);
1674
1675                 while (no_of_bits >= 8) {
1676                         offset++;
1677                         value = ((value & bit_mask) << 8) | tvb_get_guint8(tvb, offset);
1678
1679                         if (lsb0)
1680                                 *buf++ = (guint8) (GUINT16_SWAP_LE_BE(value) >> bit_shift);
1681                         else
1682                                 *buf++ = (guint8) (value >> bit_shift);
1683                         no_of_bits -= 8;
1684                 }
1685
1686                 /* something left? */
1687                 if (no_of_bits > 0) {
1688                         guint8 tot_no_bits = bit_offset+no_of_bits;
1689
1690                         /* Overlaps with next byte? Get next byte */
1691                         if (tot_no_bits > 8) {
1692                                 offset++;
1693                                 value = ((value & bit_mask) << 8) | tvb_get_guint8(tvb, offset);
1694                         }
1695
1696                         if (lsb0) {
1697                                 if (tot_no_bits > 8)
1698                                         value = (GUINT16_SWAP_LE_BE(value) >> bit_offset) & (bit_mask8[8-no_of_bits]);
1699                                 else
1700                                         value = (value >> bit_offset) & (bit_mask8[8-no_of_bits]);
1701
1702                                 /* value = (value & ((1 << tot_no_bits)-1)) >> bit_offset; */
1703
1704                         } else {
1705                                 if (tot_no_bits > 8)
1706                                         value = value >> (16 - tot_no_bits);
1707                                 else
1708                                         value = (value & bit_mask) >> (8-tot_no_bits);
1709                         }
1710                         *buf = (guint8) value;
1711                 }
1712
1713         } else {
1714                 /* fast code path for bit_offset == 0 */
1715                 while (no_of_bits >= 8) {
1716                         *buf++ = tvb_get_guint8(tvb, offset);
1717                         offset++;
1718                         no_of_bits -= 8;
1719                 }
1720
1721                 /* something left? */
1722                 if (no_of_bits > 0) {
1723                         if (lsb0)
1724                                 *buf = tvb_get_guint8(tvb, offset) & bit_mask8[8-no_of_bits]; /* read: ((1 << no_of_bits)-1) */
1725                         else
1726                                 *buf = tvb_get_guint8(tvb, offset) >> (8-no_of_bits);
1727                 }
1728         }
1729 }
1730
1731 guint8 *
1732 ep_tvb_get_bits(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean lsb0)
1733 {
1734         gint no_of_bytes;
1735         guint8 *buf;
1736
1737         /* XXX, no_of_bits == -1 -> to end of tvb? */
1738
1739         if (no_of_bits < 0 || bit_offset < 0) {
1740                 DISSECTOR_ASSERT_NOT_REACHED();
1741         }
1742
1743         no_of_bytes = (no_of_bits >> 3) + ((no_of_bits & 0x7) != 0);    /* ceil(no_of_bits / 8.0) */
1744         buf = ep_alloc(no_of_bytes);
1745         tvb_get_bits_buf(tvb, bit_offset, no_of_bits, buf, lsb0);
1746         return buf;
1747 }
1748
1749 /* Get 9 - 16 bits */
1750 /* Bit offset mask for number of bits = 16 - 32 */
1751 static const guint32 bit_mask32[] = {
1752         0xffffffff,
1753         0x7fffffff,
1754         0x3fffffff,
1755         0x1fffffff,
1756         0x0fffffff,
1757         0x07ffffff,
1758         0x03ffffff,
1759         0x01ffffff
1760 };
1761
1762 guint16
1763 tvb_get_bits16(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits,const gboolean little_endian)
1764 {
1765         gint    offset;
1766         guint16 value = 0;
1767         guint16 tempval = 0;
1768         guint8  tot_no_bits;
1769
1770         if ((no_of_bits<=8)||(no_of_bits>16)) {
1771                 /* If bits <= 8 use tvb_get_bits8 */
1772                 DISSECTOR_ASSERT_NOT_REACHED();
1773         }
1774         if(little_endian){
1775                 DISSECTOR_ASSERT_NOT_REACHED();
1776                 /* This part is not implemented yet */
1777         }
1778
1779         /* Byte align offset */
1780         offset = bit_offset>>3;
1781
1782         /* Find out which mask to use for the most significant octet
1783          * by convering bit_offset into the offset into the first
1784          * fetched octet.
1785          */
1786         bit_offset = bit_offset & 0x7;
1787         tot_no_bits = bit_offset+no_of_bits;
1788         /* Read two octets and mask off bit_offset bits */
1789         value = tvb_get_ntohs(tvb,offset) & bit_mask16[bit_offset];
1790         if(tot_no_bits < 16){
1791                 /* Left shift out the unused bits */
1792                 value = value >> (16 - tot_no_bits);
1793         }else if(tot_no_bits > 16){
1794                 /* Spans three octets, read next octet and shift as needed */
1795                 value = value << (tot_no_bits - 16);
1796                 tempval = tvb_get_guint8(tvb,offset+2);
1797                 tempval = tempval >> (24-tot_no_bits);
1798                 value = value | tempval;
1799         }
1800
1801         return value;
1802 }
1803
1804 /* Bit offset mask for number of bits = 32 - 64 */
1805 static const guint64 bit_mask64[] = {
1806         G_GINT64_CONSTANT(0xffffffffffffffffU),
1807         G_GINT64_CONSTANT(0x7fffffffffffffffU),
1808         G_GINT64_CONSTANT(0x3fffffffffffffffU),
1809         G_GINT64_CONSTANT(0x1fffffffffffffffU),
1810         G_GINT64_CONSTANT(0x0fffffffffffffffU),
1811         G_GINT64_CONSTANT(0x07ffffffffffffffU),
1812         G_GINT64_CONSTANT(0x03ffffffffffffffU),
1813         G_GINT64_CONSTANT(0x01ffffffffffffffU)
1814 };
1815
1816 guint32
1817 tvb_get_bits32(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const gboolean little_endian)
1818 {
1819         gint    offset;
1820         guint32 value = 0;
1821         guint32 tempval = 0;
1822         guint8  tot_no_bits;
1823         guint8  tot_no_octets = 0;
1824         guint8  i = 0;
1825         gint8   shift = 0;
1826
1827         if ((no_of_bits<=16)||(no_of_bits>32)) {
1828                 /* If bits <= 16 use tvb_get_bits8 or tvb_get_bits16 */
1829                 DISSECTOR_ASSERT_NOT_REACHED();
1830         }
1831         if(little_endian){
1832                 DISSECTOR_ASSERT_NOT_REACHED();
1833                 /* This part is not implemented yet */
1834         }
1835
1836         /* Byte align offset */
1837         offset = bit_offset>>3;
1838
1839         bit_offset = bit_offset & 0x7;
1840         tot_no_bits = bit_offset+no_of_bits;
1841         tot_no_octets = tot_no_bits / 8;
1842         if (tot_no_bits % 8)
1843                 tot_no_octets++;
1844         shift = no_of_bits - (8 - bit_offset);
1845
1846         value = tvb_get_guint8(tvb, offset) & bit_mask8[bit_offset];
1847         value = value << shift;
1848
1849         for (i = 1; i < tot_no_octets; i++)
1850         {
1851                 shift = shift - 8;
1852                 tempval = tvb_get_guint8(tvb, offset+i);
1853                 if (shift >= 0)
1854                 {
1855                         tempval = tempval << shift;
1856                 }
1857                 else
1858                 {
1859                         tempval = tempval >> (- shift);
1860                 }
1861                 value = value | tempval;
1862         }
1863
1864         return value;
1865 }
1866
1867 guint64
1868 tvb_get_bits64(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const gboolean little_endian)
1869 {
1870         gint    offset;
1871         guint64 value = 0;
1872         guint64 tempval = 0;
1873         guint8  tot_no_bits;
1874
1875         if ((no_of_bits<=32)||(no_of_bits>64)) {
1876                 /* If bits <= 32 use tvb_get_bits8, tvb_get_bits16 or tvb_get_bits32 */
1877                 DISSECTOR_ASSERT_NOT_REACHED();
1878         }
1879         if(little_endian){
1880                 DISSECTOR_ASSERT_NOT_REACHED();
1881                 /* This part is not implemented yet */
1882         }
1883
1884         /* Byte align offset */
1885         offset = bit_offset>>3;
1886
1887         /* Find out which mask to use for the most significant octet
1888          * by convering bit_offset into the offset into the first
1889          * fetched octet.
1890          */
1891         bit_offset = bit_offset & 0x7;
1892         tot_no_bits = bit_offset+no_of_bits;
1893         /* Read eight octets and mask off bit_offset bits */
1894         value = tvb_get_ntoh64(tvb,offset) & bit_mask64[bit_offset];
1895         if (tot_no_bits < 64){
1896                 /* Left shift out the unused bits */
1897                 value = value >> (64 - tot_no_bits);
1898         }else if (tot_no_bits > 64){
1899                 /* Spans nine octets, read next octet and shift as needed */
1900                 value = value << (tot_no_bits - 64);
1901                 tempval = tvb_get_guint8(tvb,offset+8);
1902                 tempval = tempval >> (72-tot_no_bits);
1903                 value = value | tempval;
1904         }
1905
1906         return value;
1907 }
1908
1909 guint32
1910 tvb_get_bits(tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, const gboolean little_endian)
1911 {
1912         /* This function can handle only up to 32 requested bits */
1913         if (no_of_bits > 32)
1914                 DISSECTOR_ASSERT_NOT_REACHED();
1915
1916         if (no_of_bits == 0)
1917                 return 0;
1918
1919         /* Number of requested bits is in range [17, 32] */
1920         if (no_of_bits > 16)
1921                 return tvb_get_bits32(tvb, bit_offset, no_of_bits, little_endian);
1922
1923         /* Number of requested bits is in range [9, 16] */
1924         if (no_of_bits > 8)
1925                 return tvb_get_bits16(tvb, bit_offset, no_of_bits, little_endian);
1926
1927         /* Number of requested bits is in range [1, 8] */
1928         return tvb_get_bits8(tvb, bit_offset, no_of_bits);
1929 }
1930
1931 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1932  * at most maxlength number of bytes; if maxlength is -1, searches to
1933  * end of tvbuff.
1934  * Returns the offset of the found needle, or -1 if not found.
1935  * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1936  * in that case, -1 will be returned if the boundary is reached before
1937  * finding needle. */
1938 gint
1939 tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 needle)
1940 {
1941         const guint8    *result;
1942         guint           abs_offset, junk_length;
1943         guint           tvbufflen;
1944         guint           limit;
1945
1946         DISSECTOR_ASSERT(tvb && tvb->initialized);
1947
1948         check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
1949
1950         /* Only search to end of tvbuff, w/o throwing exception. */
1951         tvbufflen = tvb_length_remaining(tvb, abs_offset);
1952         if (maxlength == -1) {
1953                 /* No maximum length specified; search to end of tvbuff. */
1954                 limit = tvbufflen;
1955         }
1956         else if (tvbufflen < (guint) maxlength) {
1957                 /* Maximum length goes past end of tvbuff; search to end
1958                    of tvbuff. */
1959                 limit = tvbufflen;
1960         }
1961         else {
1962                 /* Maximum length doesn't go past end of tvbuff; search
1963                    to that value. */
1964                 limit = maxlength;
1965         }
1966
1967         /* If we have real data, perform our search now. */
1968         if (tvb->real_data) {
1969                 result = memchr(tvb->real_data + abs_offset, needle, limit);
1970                 if (result == NULL) {
1971                         return -1;
1972                 }
1973                 else {
1974                         return (gint) (result - tvb->real_data);
1975                 }
1976         }
1977
1978         switch(tvb->type) {
1979                 case TVBUFF_REAL_DATA:
1980                         DISSECTOR_ASSERT_NOT_REACHED();
1981
1982                 case TVBUFF_SUBSET:
1983                         return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1984                                         abs_offset - tvb->tvbuffs.subset.offset,
1985                                         limit, needle);
1986
1987                 case TVBUFF_COMPOSITE:
1988                         DISSECTOR_ASSERT_NOT_REACHED();
1989                         /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1990         }
1991
1992         DISSECTOR_ASSERT_NOT_REACHED();
1993         return -1;
1994 }
1995
1996 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1997  * Searches at most maxlength number of bytes; if maxlength is -1, searches
1998  * to end of tvbuff.
1999  * Returns the offset of the found needle, or -1 if not found.
2000  * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
2001  * in that case, -1 will be returned if the boundary is reached before
2002  * finding needle. */
2003 gint
2004 tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const guint8 *needles, guchar *found_needle)
2005 {
2006         const guint8    *result;
2007         guint           abs_offset, junk_length;
2008         guint           tvbufflen;
2009         guint           limit;
2010
2011         DISSECTOR_ASSERT(tvb && tvb->initialized);
2012
2013         check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
2014
2015         /* Only search to end of tvbuff, w/o throwing exception. */
2016         tvbufflen = tvb_length_remaining(tvb, abs_offset);
2017         if (maxlength == -1) {
2018                 /* No maximum length specified; search to end of tvbuff. */
2019                 limit = tvbufflen;
2020         }
2021         else if (tvbufflen < (guint) maxlength) {
2022                 /* Maximum length goes past end of tvbuff; search to end
2023                    of tvbuff. */
2024                 limit = tvbufflen;
2025         }
2026         else {
2027                 /* Maximum length doesn't go past end of tvbuff; search
2028                    to that value. */
2029                 limit = maxlength;
2030         }
2031
2032         /* If we have real data, perform our search now. */
2033         if (tvb->real_data) {
2034                 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles, found_needle);
2035                 if (result == NULL) {
2036                         return -1;
2037                 }
2038                 else {
2039                         return (gint) (result - tvb->real_data);
2040                 }
2041         }
2042
2043         switch(tvb->type) {
2044                 case TVBUFF_REAL_DATA:
2045                         DISSECTOR_ASSERT_NOT_REACHED();
2046
2047                 case TVBUFF_SUBSET:
2048                         return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
2049                                         abs_offset - tvb->tvbuffs.subset.offset,
2050                                         limit, needles, found_needle);
2051
2052                 case TVBUFF_COMPOSITE:
2053                         DISSECTOR_ASSERT_NOT_REACHED();
2054                         /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
2055         }
2056
2057         DISSECTOR_ASSERT_NOT_REACHED();
2058         return -1;
2059 }
2060
2061 /* Find size of stringz (NUL-terminated string) by looking for terminating
2062  * NUL.  The size of the string includes the terminating NUL.
2063  *
2064  * If the NUL isn't found, it throws the appropriate exception.
2065  */
2066 guint
2067 tvb_strsize(tvbuff_t *tvb, const gint offset)
2068 {
2069         guint   abs_offset, junk_length;
2070         gint    nul_offset;
2071
2072         DISSECTOR_ASSERT(tvb && tvb->initialized);
2073
2074         check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
2075         nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
2076         if (nul_offset == -1) {
2077                 /*
2078                  * OK, we hit the end of the tvbuff, so we should throw
2079                  * an exception.
2080                  *
2081                  * Did we hit the end of the captured data, or the end
2082                  * of the actual data?  If there's less captured data
2083                  * than actual data, we presumably hit the end of the
2084                  * captured data, otherwise we hit the end of the actual
2085                  * data.
2086                  */
2087                 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
2088                         THROW(BoundsError);
2089                 } else {
2090                         THROW(ReportedBoundsError);
2091                 }
2092         }
2093         return (nul_offset - abs_offset) + 1;
2094 }
2095
2096 /* Unicode (UTF-16) version of tvb_strsize */
2097 /* Returns number of *UTF-16 characters* (not bytes) excluding the null terminator */
2098 guint
2099 tvb_unicode_strsize(tvbuff_t *tvb, const gint offset)
2100 {
2101         guint      i = 0;
2102         gunichar2  uchar;
2103
2104         DISSECTOR_ASSERT(tvb && tvb->initialized);
2105
2106         do {
2107                 /* Endianness doesn't matter when looking for null */
2108                 uchar = tvb_get_ntohs(tvb, offset + i);
2109                 i += 2;
2110         } while(uchar != 0);
2111
2112         return i; /* Number of *UTF-16* characters */
2113 }
2114
2115 /* Find length of string by looking for end of string ('\0'), up to
2116  * 'maxlength' characters'; if 'maxlength' is -1, searches to end
2117  * of tvbuff.
2118  * Returns -1 if 'maxlength' reached before finding EOS. */
2119 gint
2120 tvb_strnlen(tvbuff_t *tvb, const gint offset, const guint maxlength)
2121 {
2122         gint    result_offset;
2123         guint   abs_offset, junk_length;
2124
2125         DISSECTOR_ASSERT(tvb && tvb->initialized);
2126
2127         check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
2128
2129         result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
2130
2131         if (result_offset == -1) {
2132                 return -1;
2133         }
2134         else {
2135                 return result_offset - abs_offset;
2136         }
2137 }
2138
2139 /*
2140  * Implement strneql etc
2141  */
2142
2143 /*
2144  * Call strncmp after checking if enough chars left, returning 0 if
2145  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2146  */
2147 gint
2148 tvb_strneql(tvbuff_t *tvb, const gint offset, const gchar *str, const size_t size)
2149 {
2150         const guint8 *ptr;
2151
2152         ptr = ensure_contiguous_no_exception(tvb, offset, (gint)size, NULL);
2153
2154         if (ptr) {
2155                 int cmp = strncmp((const char *)ptr, str, size);
2156
2157                 /*
2158                  * Return 0 if equal, -1 otherwise.
2159                  */
2160                 return (cmp == 0 ? 0 : -1);
2161         } else {
2162                 /*
2163                  * Not enough characters in the tvbuff to match the
2164                  * string.
2165                  */
2166                 return -1;
2167         }
2168 }
2169
2170 /*
2171  * Call g_ascii_strncasecmp after checking if enough chars left, returning
2172  * 0 if it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2173  */
2174 gint
2175 tvb_strncaseeql(tvbuff_t *tvb, const gint offset, const gchar *str, const size_t size)
2176 {
2177         const guint8 *ptr;
2178
2179         ptr = ensure_contiguous_no_exception(tvb, offset, (gint)size, NULL);
2180
2181         if (ptr) {
2182                 int cmp = g_ascii_strncasecmp((const char *)ptr, str, size);
2183
2184                 /*
2185                  * Return 0 if equal, -1 otherwise.
2186                  */
2187                 return (cmp == 0 ? 0 : -1);
2188         } else {
2189                 /*
2190                  * Not enough characters in the tvbuff to match the
2191                  * string.
2192                  */
2193                 return -1;
2194         }
2195 }
2196
2197 /*
2198  * Call memcmp after checking if enough chars left, returning 0 if
2199  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2200  */
2201 gint
2202 tvb_memeql(tvbuff_t *tvb, const gint offset, const guint8 *str, size_t size)
2203 {
2204         const guint8 *ptr;
2205
2206         ptr = ensure_contiguous_no_exception(tvb, offset, (gint) size, NULL);
2207
2208         if (ptr) {
2209                 int cmp = memcmp(ptr, str, size);
2210
2211                 /*
2212                  * Return 0 if equal, -1 otherwise.
2213                  */
2214                 return (cmp == 0 ? 0 : -1);
2215         } else {
2216                 /*
2217                  * Not enough characters in the tvbuff to match the
2218                  * string.
2219                  */
2220                 return -1;
2221         }
2222 }
2223
2224 /* Convert a string from Unicode to ASCII.      At the moment we fake it by
2225  * replacing all non-ASCII characters with a '.' )-:  The caller must
2226  * free the result returned.  The len parameter is the number of guint16's
2227  * to convert from Unicode. */
2228 /* XXX - this function has been superceded by tvb_get_unicode_string() */
2229 char *
2230 tvb_fake_unicode(tvbuff_t *tvb, int offset, const int len, const gboolean little_endian)
2231 {
2232         char *buffer;
2233         int i;
2234         guint16 character;
2235
2236         /* Make sure we have enough data before allocating the buffer,
2237            so we don't blow up if the length is huge. */
2238         tvb_ensure_bytes_exist(tvb, offset, 2*len);
2239
2240         /* We know we won't throw an exception, so we don't have to worry
2241            about leaking this buffer. */
2242         buffer = g_malloc(len + 1);
2243
2244         for (i = 0; i < len; i++) {
2245                 character = little_endian ? tvb_get_letohs(tvb, offset)
2246                                           : tvb_get_ntohs(tvb, offset);
2247                 buffer[i] = character < 256 ? character : '.';
2248                 offset += 2;
2249         }
2250
2251         buffer[len] = 0;
2252
2253         return buffer;
2254 }
2255
2256 /* Convert a string from Unicode to ASCII.      At the moment we fake it by
2257  * replacing all non-ASCII characters with a '.' )-:   The len parameter is
2258  * the number of guint16's to convert from Unicode.
2259  *
2260  * This function allocates memory from a buffer with packet lifetime.
2261  * You do not have to free this buffer, it will be automatically freed
2262  * when wireshark starts decoding the next packet.
2263  */
2264 char *
2265 tvb_get_ephemeral_faked_unicode(tvbuff_t *tvb, int offset, const int len, const gboolean little_endian)
2266 {
2267         char *buffer;
2268         int i;
2269         guint16 character;
2270
2271         /* Make sure we have enough data before allocating the buffer,
2272            so we don't blow up if the length is huge. */
2273         tvb_ensure_bytes_exist(tvb, offset, 2*len);
2274
2275         /* We know we won't throw an exception, so we don't have to worry
2276            about leaking this buffer. */
2277         buffer = ep_alloc(len + 1);
2278
2279         for (i = 0; i < len; i++) {
2280                 character = little_endian ? tvb_get_letohs(tvb, offset)
2281                                           : tvb_get_ntohs(tvb, offset);
2282                 buffer[i] = character < 256 ? character : '.';
2283                 offset += 2;
2284         }
2285
2286         buffer[len] = 0;
2287
2288         return buffer;
2289 }
2290
2291 /*
2292  * Format the data in the tvb from offset for length ...
2293  */
2294
2295 gchar *
2296 tvb_format_text(tvbuff_t *tvb, const gint offset, const gint size)
2297 {
2298   const guint8 *ptr;
2299   gint len = size;
2300
2301   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2302     len = tvb_length_remaining(tvb, offset);
2303     ptr = ensure_contiguous(tvb, offset, len);
2304   }
2305
2306   return format_text(ptr, len);
2307 }
2308
2309 /*
2310  * Format the data in the tvb from offset for length ...
2311  */
2312
2313 gchar *
2314 tvb_format_text_wsp(tvbuff_t *tvb, const gint offset, const gint size)
2315 {
2316   const guint8 *ptr;
2317   gint len = size;
2318
2319   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2320
2321         len = tvb_length_remaining(tvb, offset);
2322         ptr = ensure_contiguous(tvb, offset, len);
2323
2324   }
2325
2326   return format_text_wsp(ptr, len);
2327
2328 }
2329
2330 /*
2331  * Like "tvb_format_text()", but for null-padded strings; don't show
2332  * the null padding characters as "\000".
2333  */
2334 gchar *
2335 tvb_format_stringzpad(tvbuff_t *tvb, const gint offset, const gint size)
2336 {
2337   const guint8 *ptr, *p;
2338   gint len = size;
2339   gint stringlen;
2340
2341   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2342
2343         len = tvb_length_remaining(tvb, offset);
2344         ptr = ensure_contiguous(tvb, offset, len);
2345
2346   }
2347
2348   for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2349         ;
2350   return format_text(ptr, stringlen);
2351
2352 }
2353
2354 /*
2355  * Like "tvb_format_text_wsp()", but for null-padded strings; don't show
2356  * the null padding characters as "\000".
2357  */
2358 gchar *
2359 tvb_format_stringzpad_wsp(tvbuff_t *tvb, const gint offset, const gint size)
2360 {
2361   const guint8 *ptr, *p;
2362   gint len = size;
2363   gint stringlen;
2364
2365   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
2366
2367         len = tvb_length_remaining(tvb, offset);
2368         ptr = ensure_contiguous(tvb, offset, len);
2369
2370   }
2371
2372   for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2373         ;
2374   return format_text_wsp(ptr, stringlen);
2375
2376 }
2377
2378 /*
2379  * Given a tvbuff, an offset, and a length, allocate a buffer big enough
2380  * to hold a non-null-terminated string of that length at that offset,
2381  * plus a trailing '\0', copy the string into it, and return a pointer
2382  * to the string.
2383  *
2384  * Throws an exception if the tvbuff ends before the string does.
2385  */
2386 guint8 *
2387 tvb_get_string(tvbuff_t *tvb, const gint offset, const gint length)
2388 {
2389         const guint8 *ptr;
2390         guint8 *strbuf = NULL;
2391
2392         tvb_ensure_bytes_exist(tvb, offset, length);
2393
2394         ptr = ensure_contiguous(tvb, offset, length);
2395         strbuf = g_malloc(length + 1);
2396         if (length != 0) {
2397                 memcpy(strbuf, ptr, length);
2398         }
2399         strbuf[length] = '\0';
2400         return strbuf;
2401 }
2402
2403 /*
2404  * Unicode (UTF-16) version of tvb_get_string()
2405  *
2406  * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
2407  *
2408  * Specify length in bytes
2409  *
2410  * Returns an UTF-8 string that must be freed by the caller
2411  */
2412 gchar *
2413 tvb_get_unicode_string(tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2414 {
2415         gchar *tmpbuf = NULL;
2416         gunichar2 uchar;
2417         gint i; /* Byte counter for tvbuff */
2418         gint tmpbuf_len;
2419         GString *strbuf = NULL;
2420
2421         strbuf = g_string_new(NULL);
2422
2423         for(i = 0; i < length; i += 2) {
2424
2425                 if(encoding == ENC_BIG_ENDIAN)
2426                         uchar = tvb_get_ntohs(tvb, offset + i);
2427                 else
2428                         uchar = tvb_get_letohs(tvb, offset + i);
2429
2430                 /* Calculate how much space is needed to store UTF-16 character
2431                  * in UTF-8 */
2432                 tmpbuf_len = g_unichar_to_utf8(uchar, NULL);
2433
2434                 tmpbuf = g_malloc(tmpbuf_len + 1); /* + 1 to make room for null
2435                                                     * terminator */
2436
2437                 g_unichar_to_utf8(uchar, tmpbuf);
2438
2439                 /* NULL terminate the tmpbuf so g_string_append knows where
2440                  * to stop */
2441                 tmpbuf[tmpbuf_len] = '\0';
2442
2443                 g_string_append(strbuf, tmpbuf);
2444
2445                 g_free(tmpbuf);
2446         }
2447
2448         return g_string_free(strbuf, FALSE);
2449 }
2450
2451 /*
2452  * Given a tvbuff, an offset, a length, and an encoding, allocate a
2453  * buffer big enough to hold a non-null-terminated string of that length
2454  * at that offset, plus a trailing '\0', copy the string into it, and
2455  * return a pointer to the string; if the encoding is EBCDIC, map
2456  * the string from EBCDIC to ASCII.
2457  *
2458  * Throws an exception if the tvbuff ends before the string does.
2459  *
2460  * This function allocates memory from a buffer with packet lifetime.
2461  * You do not have to free this buffer, it will be automatically freed
2462  * when wireshark starts decoding the next packet.
2463  * Do not use this function if you want the allocated memory to be persistent
2464  * after the current packet has been dissected.
2465  */
2466 guint8 *
2467 tvb_get_ephemeral_string_enc(tvbuff_t *tvb, const gint offset,
2468     const gint length, const gint encoding)
2469 {
2470         const guint8 *ptr;
2471         guint8 *strbuf = NULL;
2472
2473         tvb_ensure_bytes_exist(tvb, offset, length);
2474
2475         ptr = ensure_contiguous(tvb, offset, length);
2476         strbuf = ep_alloc(length + 1);
2477         if (length != 0) {
2478                 memcpy(strbuf, ptr, length);
2479         }
2480         if ((encoding & ENC_CHARENCODING_MASK) == ENC_EBCDIC)
2481                 EBCDIC_to_ASCII(strbuf, length);
2482         strbuf[length] = '\0';
2483         return strbuf;
2484 }
2485
2486 guint8 *
2487 tvb_get_ephemeral_string(tvbuff_t *tvb, const gint offset,
2488     const gint length)
2489 {
2490         return tvb_get_ephemeral_string_enc(tvb, offset, length, ENC_UTF_8|ENC_NA);
2491 }
2492
2493 /*
2494  * Unicode (UTF-16) version of tvb_get_ephemeral_string()
2495  *
2496  * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
2497  *
2498  * Specify length in bytes
2499  *
2500  * Returns an ep_ allocated UTF-8 string
2501  */
2502 gchar *
2503 tvb_get_ephemeral_unicode_string(tvbuff_t *tvb, const gint offset, gint length, const guint encoding)
2504 {
2505         gchar *tmpbuf = NULL;
2506         gunichar2 uchar;
2507         gint i; /* Byte counter for tvbuff */
2508         gint tmpbuf_len;
2509         emem_strbuf_t *strbuf = NULL;
2510
2511         strbuf = ep_strbuf_new(NULL);
2512
2513         for(i = 0; i < length; i += 2) {
2514
2515                 if(encoding == ENC_BIG_ENDIAN)
2516                         uchar = tvb_get_ntohs(tvb, offset + i);
2517                 else
2518                         uchar = tvb_get_letohs(tvb, offset + i);
2519
2520                 /* Calculate how much space is needed to store UTF-16 character
2521                  * in UTF-8 */
2522                 tmpbuf_len = g_unichar_to_utf8(uchar, NULL);
2523
2524                 tmpbuf = g_malloc(tmpbuf_len + 1); /* + 1 to make room for null
2525                                                     * terminator */
2526
2527                 g_unichar_to_utf8(uchar, tmpbuf);
2528
2529                 /* NULL terminate the tmpbuf so ep_strbuf_append knows where
2530                  * to stop */
2531                 tmpbuf[tmpbuf_len] = '\0';
2532
2533                 ep_strbuf_append(strbuf, tmpbuf);
2534
2535                 g_free(tmpbuf);
2536         }
2537
2538         return strbuf->str;
2539 }
2540
2541 /*
2542  * Given a tvbuff, an offset, and a length, allocate a buffer big enough
2543  * to hold a non-null-terminated string of that length at that offset,
2544  * plus a trailing '\0', copy the string into it, and return a pointer
2545  * to the string.
2546  *
2547  * Throws an exception if the tvbuff ends before the string does.
2548  *
2549  * This function allocates memory from a buffer with capture session lifetime.
2550  * You do not have to free this buffer, it will be automatically freed
2551  * when wireshark starts or opens a new capture.
2552  */
2553 guint8 *
2554 tvb_get_seasonal_string(tvbuff_t *tvb, const gint offset, const gint length)
2555 {
2556         const guint8 *ptr;
2557         guint8 *strbuf = NULL;
2558
2559         tvb_ensure_bytes_exist(tvb, offset, length);
2560
2561         ptr = ensure_contiguous(tvb, offset, length);
2562         strbuf = se_alloc(length + 1);
2563         if (length != 0) {
2564                 memcpy(strbuf, ptr, length);
2565         }
2566         strbuf[length] = '\0';
2567         return strbuf;
2568 }
2569
2570 /*
2571  * Given a tvbuff, an offset, and an encoding, with the offset assumed
2572  * to refer to a null-terminated string, find the length of that string
2573  * (and throw an exception if the tvbuff ends before we find the null),
2574  * allocate a buffer big enough to hold the string, copy the string into
2575  * it, and return a pointer to the string; if the encoding is EBCDIC, map
2576  * the string from EBCDIC to ASCII.  Also return the length of the
2577  * string (including the terminating null) through a pointer.
2578  */
2579 guint8 *
2580 tvb_get_stringz_enc(tvbuff_t *tvb, const gint offset, gint *lengthp, gint encoding)
2581 {
2582         guint size;
2583         guint8 *strptr;
2584
2585         size = tvb_strsize(tvb, offset);
2586         strptr = g_malloc(size);
2587         tvb_memcpy(tvb, strptr, offset, size);
2588         if ((encoding & ENC_CHARENCODING_MASK) == ENC_EBCDIC)
2589                 EBCDIC_to_ASCII(strptr, size);
2590         if (lengthp)
2591                 *lengthp = size;
2592         return strptr;
2593 }
2594
2595 guint8 *
2596 tvb_get_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
2597 {
2598         return tvb_get_stringz_enc(tvb, offset, lengthp, ENC_UTF_8|ENC_NA);
2599 }
2600
2601 /*
2602  * Given a tvbuff and an offset, with the offset assumed to refer to
2603  * a null-terminated string, find the length of that string (and throw
2604  * an exception if the tvbuff ends before we find the null), ensure that
2605  * the TVB is flat, and return a pointer to the string (in the TVB).
2606  * Also return the length of the string (including the terminating null)
2607  * through a pointer.
2608  *
2609  * As long as we aren't using composite TVBs, this saves the cycles used
2610  * (often unnecessariliy) in allocating a buffer and copying the string into
2611  * it.  (If we do start using composite TVBs, we may want to replace this
2612  * function with the _ephemeral versoin.)
2613  */
2614 const guint8 *
2615 tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
2616 {
2617         guint size;
2618         const guint8 *strptr;
2619
2620         size = tvb_strsize(tvb, offset);
2621         strptr = ensure_contiguous(tvb, offset, size);
2622         if (lengthp)
2623                 *lengthp = size;
2624         return strptr;
2625 }
2626
2627 /*
2628  * Given a tvbuff and an offset, with the offset assumed to refer to
2629  * a null-terminated string, find the length of that string (and throw
2630  * an exception if the tvbuff ends before we find the null), allocate
2631  * a buffer big enough to hold the string, copy the string into it,
2632  * and return a pointer to the string.  Also return the length of the
2633  * string (including the terminating null) through a pointer.
2634  *
2635  * This function allocates memory from a buffer with packet lifetime.
2636  * You do not have to free this buffer, it will be automatically freed
2637  * when wireshark starts decoding the next packet.
2638  * Do not use this function if you want the allocated memory to be persistent
2639  * after the current packet has been dissected.
2640  */
2641 guint8 *
2642 tvb_get_ephemeral_stringz_enc(tvbuff_t *tvb, const gint offset, gint *lengthp, gint encoding)
2643 {
2644         guint size;
2645         guint8 *strptr;
2646
2647         size = tvb_strsize(tvb, offset);
2648         strptr = ep_alloc(size);
2649         tvb_memcpy(tvb, strptr, offset, size);
2650         if ((encoding & ENC_CHARENCODING_MASK) == ENC_EBCDIC)
2651                 EBCDIC_to_ASCII(strptr, size);
2652         if (lengthp)
2653                 *lengthp = size;
2654         return strptr;
2655 }
2656
2657 guint8 *
2658 tvb_get_ephemeral_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
2659 {
2660         return tvb_get_ephemeral_stringz_enc(tvb, offset, lengthp, ENC_UTF_8|ENC_NA);
2661 }
2662
2663 /*
2664  * Unicode (UTF-16) version of tvb_get_ephemeral_stringz()
2665  *
2666  * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
2667  *
2668  * Returns an ep_ allocated UTF-8 string and updates lengthp pointer with length of string (in bytes)
2669  */
2670 gchar *
2671 tvb_get_ephemeral_unicode_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding)
2672 {
2673         gchar *tmpbuf = NULL;
2674         gunichar2 uchar;
2675         gint size; /* Number of UTF-16 characters */
2676         gint i; /* Byte counter for tvbuff */
2677         gint tmpbuf_len;
2678         emem_strbuf_t *strbuf = NULL;
2679
2680         strbuf = ep_strbuf_new(NULL);
2681
2682         size = tvb_unicode_strsize(tvb, offset);
2683
2684         for(i = 0; i < size; i += 2) {
2685
2686                 if(encoding == ENC_BIG_ENDIAN)
2687                         uchar = tvb_get_ntohs(tvb, offset + i);
2688                 else
2689                         uchar = tvb_get_letohs(tvb, offset + i);
2690
2691                 /* Calculate how much space is needed to store UTF-16 character
2692                  * in UTF-8 */
2693                 tmpbuf_len = g_unichar_to_utf8(uchar, NULL);
2694
2695                 tmpbuf = g_malloc(tmpbuf_len + 1); /* + 1 to make room for null
2696                                                     * terminator */
2697
2698                 g_unichar_to_utf8(uchar, tmpbuf);
2699
2700                 /* NULL terminate the tmpbuf so ep_strbuf_append knows where
2701                  * to stop */
2702                 tmpbuf[tmpbuf_len] = '\0';
2703
2704                 ep_strbuf_append(strbuf, tmpbuf);
2705
2706                 g_free(tmpbuf);
2707         }
2708
2709         if(lengthp)
2710                 *lengthp = i; /* Number of *bytes* processed */
2711
2712         return strbuf->str;
2713 }
2714
2715 /*
2716  * Given a tvbuff and an offset, with the offset assumed to refer to
2717  * a null-terminated string, find the length of that string (and throw
2718  * an exception if the tvbuff ends before we find the null), allocate
2719  * a buffer big enough to hold the string, copy the string into it,
2720  * and return a pointer to the string.  Also return the length of the
2721  * string (including the terminating null) through a pointer.
2722  *
2723  * This function allocates memory from a buffer with capture session lifetime.
2724  * You do not have to free this buffer, it will be automatically freed
2725  * when wireshark starts or opens a new capture.
2726  */
2727 guint8 *
2728 tvb_get_seasonal_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp)
2729 {
2730         guint size;
2731         guint8 *strptr;
2732
2733         size = tvb_strsize(tvb, offset);
2734         strptr = se_alloc(size);
2735         tvb_memcpy(tvb, strptr, offset, size);
2736         if (lengthp)
2737                 *lengthp = size;
2738         return strptr;
2739 }
2740
2741 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
2742  * no more than bufsize number of bytes, including terminating NUL, to buffer.
2743  * Returns length of string (not including terminating NUL), or -1 if the string was
2744  * truncated in the buffer due to not having reached the terminating NUL.
2745  * In this way, it acts like g_snprintf().
2746  *
2747  * bufsize MUST be greater than 0.
2748  *
2749  * When processing a packet where the remaining number of bytes is less
2750  * than bufsize, an exception is not thrown if the end of the packet
2751  * is reached before the NUL is found. If no NUL is found before reaching
2752  * the end of the short packet, -1 is still returned, and the string
2753  * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
2754  * at the correct spot, terminating the string.
2755  *
2756  * *bytes_copied will contain the number of bytes actually copied,
2757  * including the terminating-NUL.
2758  */
2759 static gint
2760 _tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer,
2761                 gint *bytes_copied)
2762 {
2763         gint    stringlen;
2764         guint   abs_offset, junk_length;
2765         gint    limit, len;
2766         gboolean decreased_max = FALSE;
2767
2768         check_offset_length(tvb->length, tvb->reported_length, offset, 0, &abs_offset, &junk_length);
2769
2770         /* There must at least be room for the terminating NUL. */
2771         DISSECTOR_ASSERT(bufsize != 0);
2772
2773         /* If there's no room for anything else, just return the NUL. */
2774         if (bufsize == 1) {
2775                 buffer[0] = 0;
2776                 *bytes_copied = 1;
2777                 return 0;
2778         }
2779
2780         /* Only read to end of tvbuff, w/o throwing exception. */
2781         len = tvb_length_remaining(tvb, abs_offset);
2782
2783         /* check_offset_length() won't throw an exception if we're
2784          * looking at the byte immediately after the end of the tvbuff. */
2785         if (len == 0) {
2786                 THROW(ReportedBoundsError);
2787         }
2788
2789         /* This should not happen because check_offset_length() would
2790          * have already thrown an exception if 'offset' were out-of-bounds.
2791          */
2792         DISSECTOR_ASSERT(len != -1);
2793
2794         /*
2795          * If we've been passed a negative number, bufsize will
2796          * be huge.
2797          */
2798         DISSECTOR_ASSERT(bufsize <= G_MAXINT);
2799
2800         if ((guint)len < bufsize) {
2801                 limit = len;
2802                 decreased_max = TRUE;
2803         }
2804         else {
2805                 limit = bufsize;
2806         }
2807
2808         stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
2809         /* If NUL wasn't found, copy the data and return -1 */
2810         if (stringlen == -1) {
2811                 tvb_memcpy(tvb, buffer, abs_offset, limit);
2812                 if (decreased_max) {
2813                         buffer[limit] = 0;
2814                         /* Add 1 for the extra NUL that we set at buffer[limit],
2815                          * pretending that it was copied as part of the string. */
2816                         *bytes_copied = limit + 1;
2817                 }
2818                 else {
2819                         *bytes_copied = limit;
2820                 }
2821                 return -1;
2822         }
2823
2824         /* Copy the string to buffer */
2825         tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
2826         *bytes_copied = stringlen + 1;
2827         return stringlen;
2828 }
2829
2830 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
2831  * no more than bufsize number of bytes, including terminating NUL, to buffer.
2832  * Returns length of string (not including terminating NUL), or -1 if the string was
2833  * truncated in the buffer due to not having reached the terminating NUL.
2834  * In this way, it acts like g_snprintf().
2835  *
2836  * When processing a packet where the remaining number of bytes is less
2837  * than bufsize, an exception is not thrown if the end of the packet
2838  * is reached before the NUL is found. If no NUL is found before reaching
2839  * the end of the short packet, -1 is still returned, and the string
2840  * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
2841  * at the correct spot, terminating the string.
2842  */
2843 gint
2844 tvb_get_nstringz(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer)
2845 {
2846         gint bytes_copied;
2847
2848         DISSECTOR_ASSERT(tvb && tvb->initialized);
2849
2850         return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
2851 }
2852
2853 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
2854  * have a terminating NUL. If the string was truncated when copied into buffer,
2855  * a NUL is placed at the end of buffer to terminate it.
2856  */
2857 gint
2858 tvb_get_nstringz0(tvbuff_t *tvb, const gint offset, const guint bufsize, guint8* buffer)
2859 {
2860         gint    len, bytes_copied;
2861
2862         DISSECTOR_ASSERT(tvb && tvb->initialized);
2863
2864         len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
2865
2866         if (len == -1) {
2867                 buffer[bufsize - 1] = 0;
2868                 return bytes_copied - 1;
2869         }
2870         else {
2871                 return len;
2872         }
2873 }
2874
2875 /*
2876  * Given a tvbuff, an offset into the tvbuff, and a length that starts
2877  * at that offset (which may be -1 for "all the way to the end of the
2878  * tvbuff"), find the end of the (putative) line that starts at the
2879  * specified offset in the tvbuff, going no further than the specified
2880  * length.
2881  *
2882  * Return the length of the line (not counting the line terminator at
2883  * the end), or, if we don't find a line terminator:
2884  *
2885  *      if "deseg" is true, return -1;
2886  *
2887  *      if "deseg" is false, return the amount of data remaining in
2888  *      the buffer.
2889  *
2890  * Set "*next_offset" to the offset of the character past the line
2891  * terminator, or past the end of the buffer if we don't find a line
2892  * terminator.  (It's not set if we return -1.)
2893  */
2894 gint
2895 tvb_find_line_end(tvbuff_t *tvb, const gint offset, int len, gint *next_offset,
2896         const gboolean desegment)
2897 {
2898         gint eob_offset;
2899         gint eol_offset;
2900         int linelen;
2901         guchar found_needle = 0;
2902
2903         if (len == -1)
2904                 len = tvb_length_remaining(tvb, offset);
2905         /*
2906          * XXX - what if "len" is still -1, meaning "offset is past the
2907          * end of the tvbuff"?
2908          */
2909         eob_offset = offset + len;
2910
2911         /*
2912          * Look either for a CR or an LF.
2913          */
2914         eol_offset = tvb_pbrk_guint8(tvb, offset, len, (const guint8 *)"\r\n", &found_needle);
2915         if (eol_offset == -1) {
2916                 /*
2917                  * No CR or LF - line is presumably continued in next packet.
2918                  */
2919                 if (desegment) {
2920                         /*
2921                          * Tell our caller we saw no EOL, so they can
2922                          * try to desegment and get the entire line
2923                          * into one tvbuff.
2924                          */
2925                         return -1;
2926                 } else {
2927                         /*
2928                          * Pretend the line runs to the end of the tvbuff.
2929                          */
2930                         linelen = eob_offset - offset;
2931                         if (next_offset)
2932                                 *next_offset = eob_offset;
2933                 }
2934         } else {
2935                 /*
2936                  * Find the number of bytes between the starting offset
2937                  * and the CR or LF.
2938                  */
2939                 linelen = eol_offset - offset;
2940
2941                 /*
2942                  * Is it a CR?
2943                  */
2944                 if (found_needle == '\r') {
2945                         /*
2946                          * Yes - is it followed by an LF?
2947                          */
2948                         if (eol_offset + 1 >= eob_offset) {
2949                                 /*
2950                                  * Dunno - the next byte isn't in this
2951                                  * tvbuff.
2952                                  */
2953                                 if (desegment) {
2954                                         /*
2955                                          * We'll return -1, although that
2956                                          * runs the risk that if the line
2957                                          * really *is* terminated with a CR,
2958                                          * we won't properly dissect this
2959                                          * tvbuff.
2960                                          *
2961                                          * It's probably more likely that
2962                                          * the line ends with CR-LF than
2963                                          * that it ends with CR by itself.
2964                                          */
2965                                         return -1;
2966                                 }
2967                         } else {
2968                                 /*
2969                                  * Well, we can at least look at the next
2970                                  * byte.
2971                                  */
2972                                 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
2973                                         /*
2974                                          * It's an LF; skip over the CR.
2975                                          */
2976                                         eol_offset++;
2977                                 }
2978                         }
2979                 }
2980
2981                 /*
2982                  * Return the offset of the character after the last
2983                  * character in the line, skipping over the last character
2984                  * in the line terminator.
2985                  */
2986                 if (next_offset)
2987                         *next_offset = eol_offset + 1;
2988         }
2989         return linelen;
2990 }
2991
2992 /*
2993  * Given a tvbuff, an offset into the tvbuff, and a length that starts
2994  * at that offset (which may be -1 for "all the way to the end of the
2995  * tvbuff"), find the end of the (putative) line that starts at the
2996  * specified offset in the tvbuff, going no further than the specified
2997  * length.
2998  *
2999  * However, treat quoted strings inside the buffer specially - don't
3000  * treat newlines in quoted strings as line terminators.
3001  *
3002  * Return the length of the line (not counting the line terminator at
3003  * the end), or the amount of data remaining in the buffer if we don't
3004  * find a line terminator.
3005  *
3006  * Set "*next_offset" to the offset of the character past the line
3007  * terminator, or past the end of the buffer if we don't find a line
3008  * terminator.
3009  */
3010 gint
3011 tvb_find_line_end_unquoted(tvbuff_t *tvb, const gint offset, int len,
3012         gint *next_offset)
3013 {
3014         gint cur_offset, char_offset;
3015         gboolean is_quoted;
3016         guchar c = 0;
3017         gint eob_offset;
3018         int linelen;
3019
3020         if (len == -1)
3021                 len = tvb_length_remaining(tvb, offset);
3022         /*
3023          * XXX - what if "len" is still -1, meaning "offset is past the
3024          * end of the tvbuff"?
3025          */
3026         eob_offset = offset + len;
3027
3028         cur_offset = offset;
3029         is_quoted = FALSE;
3030         for (;;) {
3031                         /*
3032                  * Is this part of the string quoted?
3033                  */
3034                 if (is_quoted) {
3035                         /*
3036                          * Yes - look only for the terminating quote.
3037                          */
3038                         char_offset = tvb_find_guint8(tvb, cur_offset, len,
3039                                 '"');
3040                 } else {
3041                         /*
3042                          * Look either for a CR, an LF, or a '"'.
3043                          */
3044                         char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
3045                                 (const guint8 *)"\r\n\"", &c);
3046                 }
3047                 if (char_offset == -1) {
3048                         /*
3049                          * Not found - line is presumably continued in
3050                          * next packet.
3051                          * We pretend the line runs to the end of the tvbuff.
3052                          */
3053                         linelen = eob_offset - offset;
3054                         if (next_offset)
3055                                 *next_offset = eob_offset;
3056                         break;
3057                 }
3058
3059                 if (is_quoted) {
3060                         /*
3061                          * We're processing a quoted string.
3062                          * We only looked for ", so we know it's a ";
3063                          * as we're processing a quoted string, it's a
3064                          * closing quote.
3065                          */
3066                         is_quoted = FALSE;
3067                 } else {
3068                         /*
3069                          * OK, what is it?
3070                          */
3071                         if (c == '"') {
3072                                 /*
3073                                  * Un-quoted "; it begins a quoted
3074                                  * string.
3075                                  */
3076                                 is_quoted = TRUE;
3077                         } else {
3078                                 /*
3079                                  * It's a CR or LF; we've found a line
3080                                  * terminator.
3081                                  *
3082                                  * Find the number of bytes between the
3083                                  * starting offset and the CR or LF.
3084                                  */
3085                                 linelen = char_offset - offset;
3086
3087                                 /*
3088                                  * Is it a CR?
3089                                  */
3090                                 if (c == '\r') {
3091                                         /*
3092                                          * Yes; is it followed by an LF?
3093                                          */
3094                                         if (char_offset + 1 < eob_offset &&
3095                                                 tvb_get_guint8(tvb, char_offset + 1)
3096                                                   == '\n') {
3097                                                 /*
3098                                                  * Yes; skip over the CR.
3099                                                  */
3100                                                 char_offset++;
3101                                         }
3102                                 }
3103
3104                                 /*
3105                                  * Return the offset of the character after
3106                                  * the last character in the line, skipping
3107                                  * over the last character in the line
3108                                  * terminator, and quit.
3109                                  */
3110                                 if (next_offset)
3111                                         *next_offset = char_offset + 1;
3112                                 break;
3113                         }
3114                 }
3115
3116                 /*
3117                  * Step past the character we found.
3118                  */
3119                 cur_offset = char_offset + 1;
3120                 if (cur_offset >= eob_offset) {
3121                         /*
3122                          * The character we found was the last character
3123                          * in the tvbuff - line is presumably continued in
3124                          * next packet.
3125                          * We pretend the line runs to the end of the tvbuff.
3126                          */
3127                         linelen = eob_offset - offset;
3128                         if (next_offset)
3129                                 *next_offset = eob_offset;
3130                         break;
3131                 }
3132         }
3133         return linelen;
3134 }
3135
3136 /*
3137  * Copied from the mgcp dissector. (This function should be moved to /epan )
3138  * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
3139  *                                character following offset or offset + maxlength -1 whichever
3140  *                                is smaller.
3141  *
3142  * Parameters:
3143  * tvb - The tvbuff in which we are skipping whitespace.
3144  * offset - The offset in tvb from which we begin trying to skip whitespace.
3145  * maxlength - The maximum distance from offset that we may try to skip
3146  * whitespace.
3147  *
3148  * Returns: The position in tvb of the first non-whitespace
3149  *                      character following offset or offset + maxlength -1 whichever
3150  *                      is smaller.
3151  */
3152 gint tvb_skip_wsp(tvbuff_t* tvb, const gint offset, const gint maxlength)
3153 {
3154         gint counter = offset;
3155         gint end, tvb_len;
3156         guint8 tempchar;
3157
3158         /* Get the length remaining */
3159         tvb_len = tvb_length(tvb);
3160         end = offset + maxlength;
3161         if (end >= tvb_len)
3162         {
3163                 end = tvb_len;
3164         }
3165
3166         /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
3167         for (counter = offset;
3168                  counter < end &&
3169                   ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
3170                   tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
3171                  counter++);
3172
3173         return (counter);
3174 }
3175
3176 gint tvb_skip_wsp_return(tvbuff_t* tvb, const gint offset){
3177         gint counter = offset;
3178         gint end;
3179         guint8 tempchar;
3180         end = 0;
3181
3182         for(counter = offset; counter > end &&
3183                 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
3184                 tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
3185         counter++;
3186         return (counter);
3187 }
3188
3189
3190 /*
3191  * Format a bunch of data from a tvbuff as bytes, returning a pointer
3192  * to the string with the formatted data, with "punct" as a byte
3193  * separator.
3194  */
3195 gchar *
3196 tvb_bytes_to_str_punct(tvbuff_t *tvb, const gint offset, const gint len, const gchar punct)
3197 {
3198         return bytes_to_str_punct(ensure_contiguous(tvb, offset, len), len, punct);
3199 }
3200
3201
3202 /*
3203  * Given a tvbuff, an offset into the tvbuff, and a length that starts
3204  * at that offset (which may be -1 for "all the way to the end of the
3205  * tvbuff"), fetch BCD encoded digits from a tvbuff starting from either
3206  * the low or high half byte, formating the digits according to an input digit set,
3207  * if NUll a default digit set of 0-9 returning "?" for overdecadic digits will be used.
3208  * A pointer to the EP allocated string will be returned.
3209  * Note a tvbuff content of 0xf is considered a 'filler' and will end the conversion.
3210  */
3211 static dgt_set_t Dgt1_9_bcd = {
3212     {
3213   /*  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e */
3214      '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?'
3215     }
3216 };
3217 const gchar *
3218 tvb_bcd_dig_to_ep_str(tvbuff_t *tvb, const gint offset, const gint len, dgt_set_t *dgt, gboolean skip_first)
3219 {
3220         int length;
3221         guint8 octet;
3222         int i=0;
3223         char *digit_str;
3224         gint t_offset = offset;
3225
3226         if (!dgt)
3227                 dgt = &Dgt1_9_bcd;
3228
3229         if( len == -1){
3230                 length = tvb_length(tvb);
3231                 if (length < offset){
3232                         return "";
3233                 }
3234         }else{
3235                 length = offset + len;
3236         }
3237         digit_str = ep_alloc((length - offset)*2+1);
3238
3239         while ( t_offset < length ){
3240
3241                 octet = tvb_get_guint8(tvb,t_offset);
3242                 if (!skip_first){
3243                         digit_str[i] = dgt->out[octet & 0x0f];
3244                         i++;
3245                 }
3246                 skip_first = FALSE;
3247
3248                 /*
3249                  * unpack second value in byte
3250                  */
3251                 octet = octet >> 4;
3252
3253                 if (octet == 0x0f)      /* odd number bytes - hit filler */
3254                         break;
3255
3256                 digit_str[i] = dgt->out[octet & 0x0f];
3257                 i++;
3258                 t_offset++;
3259
3260         }
3261         digit_str[i]= '\0';
3262         return digit_str;
3263
3264 }
3265
3266 /*
3267  * Format a bunch of data from a tvbuff as bytes, returning a pointer
3268  * to the string with the formatted data.
3269  */
3270 gchar *
3271 tvb_bytes_to_str(tvbuff_t *tvb, const gint offset, const gint len)
3272 {
3273         return bytes_to_str(ensure_contiguous(tvb, offset, len), len);
3274 }
3275
3276 /* Find a needle tvbuff within a haystack tvbuff. */
3277 gint
3278 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const gint haystack_offset)
3279 {
3280         guint           haystack_abs_offset, haystack_abs_length;
3281         const guint8    *haystack_data;
3282         const guint8    *needle_data;
3283         const guint     needle_len = needle_tvb->length;
3284         const guint8    *location;
3285
3286         DISSECTOR_ASSERT(haystack_tvb && haystack_tvb->initialized);
3287
3288         if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
3289                 return -1;
3290         }
3291
3292         /* Get pointers to the tvbuffs' data. */
3293         haystack_data = ensure_contiguous(haystack_tvb, 0, -1);
3294         needle_data = ensure_contiguous(needle_tvb, 0, -1);
3295
3296         check_offset_length(haystack_tvb->length, haystack_tvb->reported_length, haystack_offset, -1,
3297                         &haystack_abs_offset, &haystack_abs_length);
3298
3299         location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
3300                         needle_data, needle_len);
3301
3302         if (location) {
3303                 return (gint) (location - haystack_data);
3304         }
3305
3306         return -1;
3307 }
3308
3309 #ifdef HAVE_LIBZ
3310 /*
3311  * Uncompresses a zlib compressed packet inside a message of tvb at offset with
3312  * length comprlen.  Returns an uncompressed tvbuffer if uncompression
3313  * succeeded or NULL if uncompression failed.
3314  */
3315 #define TVB_Z_MIN_BUFSIZ 32768
3316 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
3317 /* #define TVB_Z_DEBUG 1 */
3318 #undef TVB_Z_DEBUG
3319
3320 tvbuff_t *
3321 tvb_uncompress(tvbuff_t *tvb, const int offset, int comprlen)
3322 {
3323         gint err = Z_OK;
3324         guint bytes_out = 0;
3325         guint8 *compr = NULL;
3326         guint8 *uncompr = NULL;
3327         tvbuff_t *uncompr_tvb = NULL;
3328         z_streamp strm = NULL;
3329         Bytef *strmbuf = NULL;
3330         guint inits_done = 0;
3331         gint wbits = MAX_WBITS;
3332         guint8 *next = NULL;
3333         guint bufsiz = TVB_Z_MIN_BUFSIZ;
3334 #ifdef TVB_Z_DEBUG
3335         guint inflate_passes = 0;
3336         guint bytes_in = tvb_length_remaining(tvb, offset);
3337 #endif
3338
3339         if (tvb == NULL) {
3340                 return NULL;
3341         }
3342
3343         compr = tvb_memdup(tvb, offset, comprlen);
3344
3345         if (!compr)
3346                 return NULL;
3347
3348         /*
3349          * Assume that the uncompressed data is at least twice as big as
3350          * the compressed size.
3351          */
3352         bufsiz = tvb_length_remaining(tvb, offset) * 2;
3353         bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
3354
3355 #ifdef TVB_Z_DEBUG
3356         printf("bufsiz: %u bytes\n", bufsiz);
3357 #endif
3358
3359         next = compr;
3360
3361         strm = g_new0(z_stream, 1);
3362         strm->next_in = next;
3363         strm->avail_in = comprlen;
3364
3365         strmbuf = g_malloc0(bufsiz);
3366         strm->next_out = strmbuf;
3367         strm->avail_out = bufsiz;
3368
3369         err = inflateInit2(strm, wbits);
3370         inits_done = 1;
3371         if (err != Z_OK) {
3372                 inflateEnd(strm);
3373                 g_free(strm);
3374                 g_free(compr);
3375                 g_free(strmbuf);
3376                 return NULL;
3377         }
3378
3379         while (1) {
3380                 memset(strmbuf, '\0', bufsiz);
3381                 strm->next_out = strmbuf;
3382                 strm->avail_out = bufsiz;
3383
3384                 err = inflate(strm, Z_SYNC_FLUSH);
3385
3386                 if (err == Z_OK || err == Z_STREAM_END) {
3387                         guint bytes_pass = bufsiz - strm->avail_out;
3388
3389 #ifdef TVB_Z_DEBUG
3390                         ++inflate_passes;
3391 #endif
3392
3393                         if (uncompr == NULL) {
3394                                 uncompr = g_memdup(strmbuf, bytes_pass);
3395                         } else {
3396                                 guint8 *new_data = g_malloc0(bytes_out + bytes_pass);
3397
3398                                 g_memmove(new_data, uncompr, bytes_out);
3399                                 g_memmove((new_data + bytes_out), strmbuf,
3400                                         bytes_pass);
3401
3402                                 g_free(uncompr);
3403                                 uncompr = new_data;
3404                         }
3405
3406                         bytes_out += bytes_pass;
3407
3408                         if ( err == Z_STREAM_END) {
3409                                 inflateEnd(strm);
3410                                 g_free(strm);
3411                                 g_free(strmbuf);
3412                                 break;
3413                         }
3414                 } else if (err == Z_BUF_ERROR) {
3415                         /*
3416                          * It's possible that not enough frames were captured
3417                          * to decompress this fully, so return what we've done
3418                          * so far, if any.
3419                          */
3420                         inflateEnd(strm);
3421                         g_free(strm);
3422                         g_free(strmbuf);
3423
3424                         if (uncompr != NULL) {
3425                                 break;
3426                         } else {
3427                                 g_free(compr);
3428                                 return NULL;
3429                         }
3430
3431                 } else if (err == Z_DATA_ERROR && inits_done == 1
3432                         && uncompr == NULL && (*compr  == 0x1f) &&
3433                         (*(compr + 1) == 0x8b)) {
3434                         /*
3435                          * inflate() is supposed to handle both gzip and deflate
3436                          * streams automatically, but in reality it doesn't
3437                          * seem to handle either (at least not within the
3438                          * context of an HTTP response.)  We have to try
3439                          * several tweaks, depending on the type of data and
3440                          * version of the library installed.
3441                          */
3442
3443                         /*
3444                          * Gzip file format.  Skip past the header, since the
3445                          * fix to make it work (setting windowBits to 31)
3446                          * doesn't work with all versions of the library.
3447                          */
3448                         Bytef *c = compr + 2;
3449                         Bytef flags = 0;
3450
3451                         if (*c == Z_DEFLATED) {
3452                                 c++;
3453                         } else {
3454                                 inflateEnd(strm);
3455                                 g_free(strm);
3456                                 g_free(compr);
3457                                 g_free(strmbuf);
3458                                 return NULL;
3459                         }
3460
3461                         flags = *c;
3462
3463                         /* Skip past the MTIME, XFL, and OS fields. */
3464                         c += 7;
3465
3466                         if (flags & (1 << 2)) {
3467                                 /* An Extra field is present. */
3468                                 gint xsize = (gint)(*c |
3469                                         (*(c + 1) << 8));
3470
3471                                 c += xsize;
3472                         }
3473
3474                         if (flags & (1 << 3)) {
3475                                 /* A null terminated filename */
3476
3477                                 while ((c - compr) < comprlen && *c != '\0') {
3478                                         c++;
3479                                 }
3480
3481                                 c++;
3482                         }
3483
3484                         if (flags & (1 << 4)) {
3485                                 /* A null terminated comment */
3486
3487                                 while ((c - compr) < comprlen && *c != '\0') {
3488                                         c++;
3489                                 }
3490
3491                                 c++;
3492                         }
3493
3494
3495                         inflateReset(strm);
3496                         next = c;
3497                         strm->next_in = next;
3498                         if (c - compr > comprlen) {
3499                                 inflateEnd(strm);
3500                                 g_free(strm);
3501                                 g_free(compr);
3502                                 g_free(strmbuf);
3503                                 return NULL;
3504                         }
3505                         comprlen -= (int) (c - compr);
3506
3507                         inflateEnd(strm);
3508                         err = inflateInit2(strm, wbits);
3509                         inits_done++;
3510                 } else if (err == Z_DATA_ERROR && uncompr == NULL &&
3511                         inits_done <= 3) {
3512
3513                         /*
3514                          * Re-init the stream with a negative
3515                          * MAX_WBITS. This is necessary due to
3516                          * some servers (Apache) not sending
3517                          * the deflate header with the
3518                          * content-encoded response.
3519                          */
3520                         wbits = -MAX_WBITS;
3521
3522                         inflateReset(strm);
3523
3524                         strm->next_in = next;
3525                         strm->avail_in = comprlen;
3526
3527                         inflateEnd(strm);
3528                         memset(strmbuf, '\0', bufsiz);
3529                         strm->next_out = strmbuf;
3530                         strm->avail_out = bufsiz;
3531
3532                         err = inflateInit2(strm, wbits);
3533
3534                         inits_done++;
3535
3536                         if (err != Z_OK) {
3537                                 g_free(strm);
3538                                 g_free(strmbuf);
3539                                 g_free(compr);
3540                                 g_free(uncompr);
3541
3542                                 return NULL;
3543                         }
3544                 } else {
3545                         inflateEnd(strm);
3546                         g_free(strm);
3547                         g_free(strmbuf);
3548
3549                         if (uncompr == NULL) {
3550                                 g_free(compr);
3551                                 return NULL;
3552                         }
3553
3554                         break;
3555                 }
3556         }
3557
3558 #ifdef TVB_Z_DEBUG
3559         printf("inflate() total passes: %u\n", inflate_passes);
3560         printf("bytes  in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
3561 #endif
3562
3563         if (uncompr != NULL) {
3564                 uncompr_tvb =  tvb_new_real_data((guint8*) uncompr, bytes_out,
3565                         bytes_out);
3566                 tvb_set_free_cb(uncompr_tvb, g_free);
3567         }
3568         g_free(compr);
3569         return uncompr_tvb;
3570 }
3571 #else
3572 tvbuff_t *
3573 tvb_uncompress(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
3574 {
3575         return NULL;
3576 }
3577 #endif
3578
3579 tvbuff_t *
3580 tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
3581 {
3582         tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
3583         if (new_tvb)
3584                 tvb_set_child_real_data_tvbuff (parent, new_tvb);
3585         return new_tvb;
3586 }
3587
3588 gint
3589 tvb_raw_offset(tvbuff_t *tvb)
3590 {
3591         return ((tvb->raw_offset==-1)?(tvb->raw_offset = tvb_offset_from_real_beginning(tvb)):tvb->raw_offset);
3592 }
3593
3594 struct tvbuff *
3595 tvb_get_ds_tvb(tvbuff_t *tvb)
3596 {
3597         return(tvb->ds_tvb);
3598 }