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