In tvb_get_string(), throw an exception if our length is less than zero.
[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  * 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 guint64
1056 tvb_get_ntoh64(tvbuff_t *tvb, gint offset)
1057 {
1058         const guint8* ptr;
1059
1060         ptr = ensure_contiguous(tvb, offset, sizeof(guint64));
1061         return pntoh64(ptr);
1062 }
1063
1064 /*
1065  * Stuff for IEEE float handling on platforms that don't have IEEE
1066  * format as the native floating-point format.
1067  *
1068  * For now, we treat only the VAX as such a platform.
1069  *
1070  * XXX - other non-IEEE boxes that can run UNIX include some Crays,
1071  * and possibly other machines.
1072  *
1073  * It appears that the official Linux port to System/390 and
1074  * zArchitecture uses IEEE format floating point (not a
1075  * huge surprise).
1076  *
1077  * I don't know whether there are any other machines that
1078  * could run Ethereal and that don't use IEEE format.
1079  * As far as I know, all of the main commercial microprocessor
1080  * families on which OSes that support Ethereal can run
1081  * use IEEE format (x86, 68k, SPARC, MIPS, PA-RISC, Alpha,
1082  * IA-64, and so on).
1083  */
1084
1085 #if defined(vax)
1086
1087 #include <math.h>
1088
1089 /*
1090  * Single-precision.
1091  */
1092 #define IEEE_SP_NUMBER_WIDTH    32      /* bits in number */
1093 #define IEEE_SP_EXP_WIDTH       8       /* bits in exponent */
1094 #define IEEE_SP_MANTISSA_WIDTH  23      /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1095
1096 #define IEEE_SP_SIGN_MASK       0x80000000
1097 #define IEEE_SP_EXPONENT_MASK   0x7F800000
1098 #define IEEE_SP_MANTISSA_MASK   0x007FFFFF
1099 #define IEEE_SP_INFINITY        IEEE_SP_EXPONENT_MASK
1100
1101 #define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1102 #define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1103 #define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1104
1105 static int
1106 ieee_float_is_zero(guint32 w)
1107 {
1108         return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1109 }
1110
1111 static gfloat
1112 get_ieee_float(guint32 w)
1113 {
1114         long sign;
1115         long exponent;
1116         long mantissa;
1117
1118         sign = w & IEEE_SP_SIGN_MASK;
1119         exponent = w & IEEE_SP_EXPONENT_MASK;
1120         mantissa = w & IEEE_SP_MANTISSA_MASK;
1121
1122         if (ieee_float_is_zero(w)) {
1123                 /* number is zero, unnormalized, or not-a-number */
1124                 return 0.0;
1125         }
1126 #if 0
1127         /*
1128          * XXX - how to handle this?
1129          */
1130         if (IEEE_SP_INFINITY == exponent) {
1131                 /*
1132                  * number is positive or negative infinity, or a special value
1133                  */
1134                 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1135         }
1136 #endif
1137
1138         exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1139             IEEE_SP_MANTISSA_WIDTH;
1140         mantissa |= IEEE_SP_IMPLIED_BIT;
1141
1142         if (sign)
1143                 return -mantissa * pow(2, exponent);
1144         else
1145                 return mantissa * pow(2, exponent);
1146 }
1147
1148 /*
1149  * Double-precision.
1150  * We assume that if you don't have IEEE floating-point, you have a
1151  * compiler that understands 64-bit integral quantities.
1152  */
1153 #define IEEE_DP_NUMBER_WIDTH    64      /* bits in number */
1154 #define IEEE_DP_EXP_WIDTH       11      /* bits in exponent */
1155 #define IEEE_DP_MANTISSA_WIDTH  52      /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1156
1157 #define IEEE_DP_SIGN_MASK       0x8000000000000000LL
1158 #define IEEE_DP_EXPONENT_MASK   0x7FF0000000000000LL
1159 #define IEEE_DP_MANTISSA_MASK   0x000FFFFFFFFFFFFFLL
1160 #define IEEE_DP_INFINITY        IEEE_DP_EXPONENT_MASK
1161
1162 #define IEEE_DP_IMPLIED_BIT (1LL << IEEE_DP_MANTISSA_WIDTH)
1163 #define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1164 #define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1165
1166 static int
1167 ieee_double_is_zero(guint64 w)
1168 {
1169         return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1170 }
1171
1172 static gdouble
1173 get_ieee_double(guint64 w)
1174 {
1175         gint64 sign;
1176         gint64 exponent;
1177         gint64 mantissa;
1178
1179         sign = w & IEEE_DP_SIGN_MASK;
1180         exponent = w & IEEE_DP_EXPONENT_MASK;
1181         mantissa = w & IEEE_DP_MANTISSA_MASK;
1182
1183         if (ieee_double_is_zero(w)) {
1184                 /* number is zero, unnormalized, or not-a-number */
1185                 return 0.0;
1186         }
1187 #if 0
1188         /*
1189          * XXX - how to handle this?
1190          */
1191         if (IEEE_DP_INFINITY == exponent) {
1192                 /*
1193                  * number is positive or negative infinity, or a special value
1194                  */
1195                 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1196         }
1197 #endif
1198
1199         exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1200             IEEE_DP_MANTISSA_WIDTH;
1201         mantissa |= IEEE_DP_IMPLIED_BIT;
1202
1203         if (sign)
1204                 return -mantissa * pow(2, exponent);
1205         else
1206                 return mantissa * pow(2, exponent);
1207 }
1208 #endif
1209
1210 /*
1211  * Fetches an IEEE single-precision floating-point number, in
1212  * big-endian form, and returns a "float".
1213  *
1214  * XXX - should this be "double", in case there are IEEE single-
1215  * precision numbers that won't fit in some platform's native
1216  * "float" format?
1217  */
1218 gfloat
1219 tvb_get_ntohieee_float(tvbuff_t *tvb, int offset)
1220 {
1221 #if defined(vax)
1222         return get_ieee_float(tvb_get_ntohl(tvb, offset));
1223 #else
1224         union {
1225                 gfloat f;
1226                 guint32 w;
1227         } ieee_fp_union;
1228
1229         ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1230         return ieee_fp_union.f;
1231 #endif
1232 }
1233
1234 /*
1235  * Fetches an IEEE double-precision floating-point number, in
1236  * big-endian form, and returns a "double".
1237  */
1238 gdouble
1239 tvb_get_ntohieee_double(tvbuff_t *tvb, int offset)
1240 {
1241 #if defined(vax)
1242         union {
1243                 guint32 w[2];
1244                 guint64 dw;
1245         } ieee_fp_union;
1246 #else
1247         union {
1248                 gdouble d;
1249                 guint32 w[2];
1250         } ieee_fp_union;
1251 #endif
1252
1253 #ifdef WORDS_BIGENDIAN
1254         ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1255         ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1256 #else
1257         ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1258         ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1259 #endif
1260 #if defined(vax)
1261         return get_ieee_double(ieee_fp_union.dw);
1262 #else
1263         return ieee_fp_union.d;
1264 #endif
1265 }
1266
1267 guint16
1268 tvb_get_letohs(tvbuff_t *tvb, gint offset)
1269 {
1270         const guint8* ptr;
1271
1272         ptr = ensure_contiguous(tvb, offset, sizeof(guint16));
1273         return pletohs(ptr);
1274 }
1275
1276 guint32
1277 tvb_get_letoh24(tvbuff_t *tvb, gint offset)
1278 {
1279         const guint8* ptr;
1280
1281         ptr = ensure_contiguous(tvb, offset, 3);
1282         return pletoh24(ptr);
1283 }
1284
1285 guint32
1286 tvb_get_letohl(tvbuff_t *tvb, gint offset)
1287 {
1288         const guint8* ptr;
1289
1290         ptr = ensure_contiguous(tvb, offset, sizeof(guint32));
1291         return pletohl(ptr);
1292 }
1293
1294 guint64
1295 tvb_get_letoh64(tvbuff_t *tvb, gint offset)
1296 {
1297         const guint8* ptr;
1298
1299         ptr = ensure_contiguous(tvb, offset, sizeof(guint64));
1300         return pletoh64(ptr);
1301 }
1302
1303 /*
1304  * Fetches an IEEE single-precision floating-point number, in
1305  * little-endian form, and returns a "float".
1306  *
1307  * XXX - should this be "double", in case there are IEEE single-
1308  * precision numbers that won't fit in some platform's native
1309  * "float" format?
1310  */
1311 gfloat
1312 tvb_get_letohieee_float(tvbuff_t *tvb, int offset)
1313 {
1314 #if defined(vax)
1315         return get_ieee_float(tvb_get_letohl(tvb, offset));
1316 #else
1317         union {
1318                 gfloat f;
1319                 guint32 w;
1320         } ieee_fp_union;
1321
1322         ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1323         return ieee_fp_union.f;
1324 #endif
1325 }
1326
1327 /*
1328  * Fetches an IEEE double-precision floating-point number, in
1329  * little-endian form, and returns a "double".
1330  */
1331 gdouble
1332 tvb_get_letohieee_double(tvbuff_t *tvb, int offset)
1333 {
1334 #if defined(vax)
1335         union {
1336                 guint32 w[2];
1337                 guint64 dw;
1338         } ieee_fp_union;
1339 #else
1340         union {
1341                 gdouble d;
1342                 guint32 w[2];
1343         } ieee_fp_union;
1344 #endif
1345
1346 #ifdef WORDS_BIGENDIAN
1347         ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1348         ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1349 #else
1350         ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1351         ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1352 #endif
1353 #if defined(vax)
1354         return get_ieee_double(ieee_fp_union.dw);
1355 #else
1356         return ieee_fp_union.d;
1357 #endif
1358 }
1359
1360 /* Find first occurence of needle in tvbuff, starting at offset. Searches
1361  * at most maxlength number of bytes; if maxlength is -1, searches to
1362  * end of tvbuff.
1363  * Returns the offset of the found needle, or -1 if not found.
1364  * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1365  * in that case, -1 will be returned if the boundary is reached before
1366  * finding needle. */
1367 gint
1368 tvb_find_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 needle)
1369 {
1370         const guint8    *result;
1371         guint           abs_offset, junk_length;
1372         guint           tvbufflen;
1373         guint           limit;
1374
1375         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1376
1377         /* Only search to end of tvbuff, w/o throwing exception. */
1378         tvbufflen = tvb_length_remaining(tvb, abs_offset);
1379         if (maxlength == -1) {
1380                 /* No maximum length specified; search to end of tvbuff. */
1381                 limit = tvbufflen;
1382         }
1383         else if (tvbufflen < (guint) maxlength) {
1384                 /* Maximum length goes past end of tvbuff; search to end
1385                    of tvbuff. */
1386                 limit = tvbufflen;
1387         }
1388         else {
1389                 /* Maximum length doesn't go past end of tvbuff; search
1390                    to that value. */
1391                 limit = maxlength;
1392         }
1393
1394         /* If we have real data, perform our search now. */
1395         if (tvb->real_data) {
1396                 result = guint8_find(tvb->real_data + abs_offset, limit, needle);
1397                 if (result == NULL) {
1398                         return -1;
1399                 }
1400                 else {
1401                         return result - tvb->real_data;
1402                 }
1403         }
1404
1405         switch(tvb->type) {
1406                 case TVBUFF_REAL_DATA:
1407                         g_assert_not_reached();
1408
1409                 case TVBUFF_SUBSET:
1410                         return tvb_find_guint8(tvb->tvbuffs.subset.tvb,
1411                                         abs_offset - tvb->tvbuffs.subset.offset,
1412                                         limit, needle);
1413
1414                 case TVBUFF_COMPOSITE:
1415                         g_assert_not_reached();
1416                         /* XXX - return composite_find_guint8(tvb, offset, limit, needle); */
1417         }
1418
1419         g_assert_not_reached();
1420         return -1;
1421 }
1422
1423 /* Find first occurence of any of the needles in tvbuff, starting at offset.
1424  * Searches at most maxlength number of bytes; if maxlength is -1, searches
1425  * to end of tvbuff.
1426  * Returns the offset of the found needle, or -1 if not found.
1427  * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
1428  * in that case, -1 will be returned if the boundary is reached before
1429  * finding needle. */
1430 gint
1431 tvb_pbrk_guint8(tvbuff_t *tvb, gint offset, gint maxlength, guint8 *needles)
1432 {
1433         const guint8    *result;
1434         guint           abs_offset, junk_length;
1435         guint           tvbufflen;
1436         guint           limit;
1437
1438         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1439
1440         /* Only search to end of tvbuff, w/o throwing exception. */
1441         tvbufflen = tvb_length_remaining(tvb, abs_offset);
1442         if (maxlength == -1) {
1443                 /* No maximum length specified; search to end of tvbuff. */
1444                 limit = tvbufflen;
1445         }
1446         else if (tvbufflen < (guint) maxlength) {
1447                 /* Maximum length goes past end of tvbuff; search to end
1448                    of tvbuff. */
1449                 limit = tvbufflen;
1450         }
1451         else {
1452                 /* Maximum length doesn't go past end of tvbuff; search
1453                    to that value. */
1454                 limit = maxlength;
1455         }
1456
1457         /* If we have real data, perform our search now. */
1458         if (tvb->real_data) {
1459                 result = guint8_pbrk(tvb->real_data + abs_offset, limit, needles);
1460                 if (result == NULL) {
1461                         return -1;
1462                 }
1463                 else {
1464                         return result - tvb->real_data;
1465                 }
1466         }
1467
1468         switch(tvb->type) {
1469                 case TVBUFF_REAL_DATA:
1470                         g_assert_not_reached();
1471
1472                 case TVBUFF_SUBSET:
1473                         return tvb_pbrk_guint8(tvb->tvbuffs.subset.tvb,
1474                                         abs_offset - tvb->tvbuffs.subset.offset,
1475                                         limit, needles);
1476
1477                 case TVBUFF_COMPOSITE:
1478                         g_assert_not_reached();
1479                         /* XXX - return composite_pbrk_guint8(tvb, offset, limit, needle); */
1480         }
1481
1482         g_assert_not_reached();
1483         return -1;
1484 }
1485
1486 /* Find size of stringz (NUL-terminated string) by looking for terminating
1487  * NUL.  The size of the string includes the terminating NUL.
1488  *
1489  * If the NUL isn't found, it throws the appropriate exception.
1490  */
1491 guint
1492 tvb_strsize(tvbuff_t *tvb, gint offset)
1493 {
1494         guint   abs_offset, junk_length;
1495         gint    nul_offset;
1496
1497         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1498         nul_offset = tvb_find_guint8(tvb, abs_offset, -1, 0);
1499         if (nul_offset == -1) {
1500                 /*
1501                  * OK, we hit the end of the tvbuff, so we should throw
1502                  * an exception.
1503                  *
1504                  * Did we hit the end of the captured data, or the end
1505                  * of the actual data?  If there's less captured data
1506                  * than actual data, we presumably hit the end of the
1507                  * captured data, otherwise we hit the end of the actual
1508                  * data.
1509                  */
1510                 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
1511                         THROW(BoundsError);
1512                 } else {
1513                         THROW(ReportedBoundsError);
1514                 }
1515         }
1516         return (nul_offset - abs_offset) + 1;
1517 }
1518
1519 /* Find length of string by looking for end of string ('\0'), up to
1520  * 'maxlength' characters'; if 'maxlength' is -1, searches to end
1521  * of tvbuff.
1522  * Returns -1 if 'maxlength' reached before finding EOS. */
1523 gint
1524 tvb_strnlen(tvbuff_t *tvb, gint offset, guint maxlength)
1525 {
1526         gint    result_offset;
1527         guint   abs_offset, junk_length;
1528
1529         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1530
1531         result_offset = tvb_find_guint8(tvb, abs_offset, maxlength, 0);
1532
1533         if (result_offset == -1) {
1534                 return -1;
1535         }
1536         else {
1537                 return result_offset - abs_offset;
1538         }
1539 }
1540
1541 /*
1542  * Implement strneql etc
1543  */
1544
1545 /*
1546  * Call strncmp after checking if enough chars left, returning 0 if
1547  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1548  */
1549 gint
1550 tvb_strneql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
1551 {
1552         const guint8 *ptr;
1553
1554         ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1555
1556         if (ptr) {
1557                 int cmp = strncmp((const char *)ptr, str, size);
1558
1559                 /*
1560                  * Return 0 if equal, -1 otherwise.
1561                  */
1562                 return (cmp == 0 ? 0 : -1);
1563         } else {
1564                 /*
1565                  * Not enough characters in the tvbuff to match the
1566                  * string.
1567                  */
1568                 return -1;
1569         }
1570 }
1571
1572 /*
1573  * Call strncasecmp after checking if enough chars left, returning 0 if
1574  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1575  */
1576 gint
1577 tvb_strncaseeql(tvbuff_t *tvb, gint offset, const gchar *str, gint size)
1578 {
1579         const guint8 *ptr;
1580
1581         ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1582
1583         if (ptr) {
1584                 int cmp = strncasecmp((const char *)ptr, str, size);
1585
1586                 /*
1587                  * Return 0 if equal, -1 otherwise.
1588                  */
1589                 return (cmp == 0 ? 0 : -1);
1590         } else {
1591                 /*
1592                  * Not enough characters in the tvbuff to match the
1593                  * string.
1594                  */
1595                 return -1;
1596         }
1597 }
1598
1599 /*
1600  * Call memcmp after checking if enough chars left, returning 0 if
1601  * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
1602  */
1603 gint
1604 tvb_memeql(tvbuff_t *tvb, gint offset, const guint8 *str, gint size)
1605 {
1606         const guint8 *ptr;
1607
1608         ptr = ensure_contiguous_no_exception(tvb, offset, size, NULL);
1609
1610         if (ptr) {
1611                 int cmp = memcmp(ptr, str, size);
1612
1613                 /*
1614                  * Return 0 if equal, -1 otherwise.
1615                  */
1616                 return (cmp == 0 ? 0 : -1);
1617         } else {
1618                 /*
1619                  * Not enough characters in the tvbuff to match the
1620                  * string.
1621                  */
1622                 return -1;
1623         }
1624 }
1625
1626 /* Convert a string from Unicode to ASCII.  At the moment we fake it by
1627  * replacing all non-ASCII characters with a '.' )-:  The caller must
1628  * free the result returned.  The len parameter is the number of guint16's
1629  * to convert from Unicode. */
1630 char *
1631 tvb_fake_unicode(tvbuff_t *tvb, int offset, int len, gboolean little_endian)
1632 {
1633         char *buffer;
1634         int i;
1635         guint16 character;
1636
1637         /* Make sure we have enough data before allocating the buffer,
1638            so we don't blow up if the length is huge. */
1639         tvb_ensure_bytes_exist(tvb, offset, 2*len);
1640
1641         /* We know we won't throw an exception, so we don't have to worry
1642            about leaking this buffer. */
1643         buffer = g_malloc(len + 1);
1644
1645         for (i = 0; i < len; i++) {
1646                 character = little_endian ? tvb_get_letohs(tvb, offset)
1647                                           : tvb_get_ntohs(tvb, offset);
1648                 buffer[i] = character < 256 ? character : '.';
1649                 offset += 2;
1650         }
1651
1652         buffer[len] = 0;
1653
1654         return buffer;
1655 }
1656
1657 /*
1658  * Format the data in the tvb from offset for length ...
1659  */
1660
1661 gchar *
1662 tvb_format_text(tvbuff_t *tvb, gint offset, gint size)
1663 {
1664   const guint8 *ptr;
1665   gint len = size;
1666
1667   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1668
1669     len = tvb_length_remaining(tvb, offset);
1670     ptr = ensure_contiguous(tvb, offset, len);
1671
1672   }
1673
1674   return format_text(ptr, len);
1675
1676 }
1677
1678 /*
1679  * Like "tvb_format_text()", but for null-padded strings; don't show
1680  * the null padding characters as "\000".
1681  */
1682 gchar *
1683 tvb_format_stringzpad(tvbuff_t *tvb, gint offset, gint size)
1684 {
1685   const guint8 *ptr, *p;
1686   gint len = size;
1687   gint stringlen;
1688
1689   if ((ptr = ensure_contiguous(tvb, offset, size)) == NULL) {
1690
1691     len = tvb_length_remaining(tvb, offset);
1692     ptr = ensure_contiguous(tvb, offset, len);
1693
1694   }
1695
1696   for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
1697     ;
1698   return format_text(ptr, stringlen);
1699
1700 }
1701
1702 /*
1703  * Given a tvbuff, an offset, and a length, allocate a buffer big enough
1704  * to hold a non-null-terminated string of that length at that offset,
1705  * plus a trailing '\0', copy the string into it, and return a pointer
1706  * to the string.
1707  *
1708  * Throws an exception if the tvbuff ends before the string does.
1709  */
1710 guint8 *
1711 tvb_get_string(tvbuff_t *tvb, gint offset, gint length)
1712 {
1713         const guint8 *ptr;
1714         guint8 *strbuf = NULL;
1715
1716         if (length < 0)
1717                 THROW(DissectorError);
1718
1719         ptr = ensure_contiguous(tvb, offset, length);
1720         strbuf = g_malloc(length + 1);
1721         if (length != 0) {
1722                 memcpy(strbuf, ptr, length);
1723         }
1724         strbuf[length] = '\0';
1725         return strbuf;
1726 }
1727
1728 /*
1729  * Given a tvbuff and an offset, with the offset assumed to refer to
1730  * a null-terminated string, find the length of that string (and throw
1731  * an exception if the tvbuff ends before we find the null), allocate
1732  * a buffer big enough to hold the string, copy the string into it,
1733  * and return a pointer to the string.  Also return the length of the
1734  * string (including the terminating null) through a pointer.
1735  */
1736 guint8 *
1737 tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp)
1738 {
1739         guint size;
1740         guint8 *strptr;
1741
1742         size = tvb_strsize(tvb, offset);
1743         strptr = g_malloc(size);
1744         tvb_memcpy(tvb, strptr, offset, size);
1745         *lengthp = size;
1746         return strptr;
1747 }
1748
1749 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1750  * no more than bufsize number of bytes, including terminating NUL, to buffer.
1751  * Returns length of string (not including terminating NUL), or -1 if the string was
1752  * truncated in the buffer due to not having reached the terminating NUL.
1753  * In this way, it acts like snprintf().
1754  *
1755  * bufsize MUST be greater than 0.
1756  *
1757  * When processing a packet where the remaining number of bytes is less
1758  * than bufsize, an exception is not thrown if the end of the packet
1759  * is reached before the NUL is found. If no NUL is found before reaching
1760  * the end of the short packet, -1 is still returned, and the string
1761  * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1762  * at the correct spot, terminating the string.
1763  *
1764  * *bytes_copied will contain the number of bytes actually copied,
1765  * including the terminating-NUL.
1766  */
1767 static gint
1768 _tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer,
1769                 gint *bytes_copied)
1770 {
1771         gint    stringlen;
1772         guint   abs_offset, junk_length;
1773         gint    limit, len;
1774         gboolean decreased_max = FALSE;
1775
1776         check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
1777
1778         /* There must at least be room for the terminating NUL. */
1779         g_assert(bufsize != 0);
1780
1781         /* If there's no room for anything else, just return the NUL. */
1782         if (bufsize == 1) {
1783                 buffer[0] = 0;
1784                 *bytes_copied = 1;
1785                 return 0;
1786         }
1787
1788         /* Only read to end of tvbuff, w/o throwing exception. */
1789         len = tvb_length_remaining(tvb, abs_offset);
1790
1791         /* check_offset_length() won't throw an exception if we're
1792          * looking at the byte immediately after the end of the tvbuff. */
1793         if (len == 0) {
1794                 THROW(ReportedBoundsError);
1795         }
1796
1797         /* This should not happen because check_offset_length() would
1798          * have already thrown an exception if 'offset' were out-of-bounds.
1799          */
1800         g_assert(len != -1);
1801
1802         /*
1803          * If we've been passed a negative number, bufsize will
1804          * be huge.
1805          */
1806         g_assert(bufsize <= G_MAXINT);
1807
1808         if ((guint)len < bufsize) {
1809                 limit = len;
1810                 decreased_max = TRUE;
1811         }
1812         else {
1813                 limit = bufsize;
1814         }
1815
1816         stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
1817         /* If NUL wasn't found, copy the data and return -1 */
1818         if (stringlen == -1) {
1819                 tvb_memcpy(tvb, buffer, abs_offset, limit);
1820                 if (decreased_max) {
1821                         buffer[limit] = 0;
1822                         /* Add 1 for the extra NUL that we set at buffer[limit],
1823                          * pretending that it was copied as part of the string. */
1824                         *bytes_copied = limit + 1;
1825                 }
1826                 else {
1827                         *bytes_copied = limit;
1828                 }
1829                 return -1;
1830         }
1831
1832         /* Copy the string to buffer */
1833         tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
1834         *bytes_copied = stringlen + 1;
1835         return stringlen;
1836 }
1837
1838 /* Looks for a stringz (NUL-terminated string) in tvbuff and copies
1839  * no more than bufsize number of bytes, including terminating NUL, to buffer.
1840  * Returns length of string (not including terminating NUL), or -1 if the string was
1841  * truncated in the buffer due to not having reached the terminating NUL.
1842  * In this way, it acts like snprintf().
1843  *
1844  * When processing a packet where the remaining number of bytes is less
1845  * than bufsize, an exception is not thrown if the end of the packet
1846  * is reached before the NUL is found. If no NUL is found before reaching
1847  * the end of the short packet, -1 is still returned, and the string
1848  * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
1849  * at the correct spot, terminating the string.
1850  */
1851 gint
1852 tvb_get_nstringz(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1853 {
1854         gint bytes_copied;
1855
1856         return _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1857 }
1858
1859 /* Like tvb_get_nstringz(), but never returns -1. The string is guaranteed to
1860  * have a terminating NUL. If the string was truncated when copied into buffer,
1861  * a NUL is placed at the end of buffer to terminate it.
1862  */
1863 gint
1864 tvb_get_nstringz0(tvbuff_t *tvb, gint offset, guint bufsize, guint8* buffer)
1865 {
1866         gint    len, bytes_copied;
1867
1868         len = _tvb_get_nstringz(tvb, offset, bufsize, buffer, &bytes_copied);
1869
1870         if (len == -1) {
1871                 buffer[bufsize - 1] = 0;
1872                 return bytes_copied - 1;
1873         }
1874         else {
1875                 return len;
1876         }
1877 }
1878
1879 /*
1880  * Given a tvbuff, an offset into the tvbuff, and a length that starts
1881  * at that offset (which may be -1 for "all the way to the end of the
1882  * tvbuff"), find the end of the (putative) line that starts at the
1883  * specified offset in the tvbuff, going no further than the specified
1884  * length.
1885  *
1886  * Return the length of the line (not counting the line terminator at
1887  * the end), or, if we don't find a line terminator:
1888  *
1889  *      if "deseg" is true, return -1;
1890  *
1891  *      if "deseg" is false, return the amount of data remaining in
1892  *      the buffer.
1893  *
1894  * Set "*next_offset" to the offset of the character past the line
1895  * terminator, or past the end of the buffer if we don't find a line
1896  * terminator.  (It's not set if we return -1.)
1897  */
1898 gint
1899 tvb_find_line_end(tvbuff_t *tvb, gint offset, int len, gint *next_offset,
1900     gboolean desegment)
1901 {
1902         gint eob_offset;
1903         gint eol_offset;
1904         int linelen;
1905
1906         if (len == -1)
1907                 len = tvb_length_remaining(tvb, offset);
1908         /*
1909          * XXX - what if "len" is still -1, meaning "offset is past the
1910          * end of the tvbuff"?
1911          */
1912         eob_offset = offset + len;
1913
1914         /*
1915          * Look either for a CR or an LF.
1916          */
1917         eol_offset = tvb_pbrk_guint8(tvb, offset, len, (guint8 *)"\r\n");
1918         if (eol_offset == -1) {
1919                 /*
1920                  * No CR or LF - line is presumably continued in next packet.
1921                  */
1922                 if (desegment) {
1923                         /*
1924                          * Tell our caller we saw no EOL, so they can
1925                          * try to desegment and get the entire line
1926                          * into one tvbuff.
1927                          */
1928                         return -1;
1929                 } else {
1930                         /*
1931                          * Pretend the line runs to the end of the tvbuff.
1932                          */
1933                         linelen = eob_offset - offset;
1934                         *next_offset = eob_offset;
1935                 }
1936         } else {
1937                 /*
1938                  * Find the number of bytes between the starting offset
1939                  * and the CR or LF.
1940                  */
1941                 linelen = eol_offset - offset;
1942
1943                 /*
1944                  * Is it a CR?
1945                  */
1946                 if (tvb_get_guint8(tvb, eol_offset) == '\r') {
1947                         /*
1948                          * Yes - is it followed by an LF?
1949                          */
1950                         if (eol_offset + 1 >= eob_offset) {
1951                                 /*
1952                                  * Dunno - the next byte isn't in this
1953                                  * tvbuff.
1954                                  */
1955                                 if (desegment) {
1956                                         /*
1957                                          * We'll return -1, although that
1958                                          * runs the risk that if the line
1959                                          * really *is* terminated with a CR,
1960                                          * we won't properly dissect this
1961                                          * tvbuff.
1962                                          *
1963                                          * It's probably more likely that
1964                                          * the line ends with CR-LF than
1965                                          * that it ends with CR by itself.
1966                                          */
1967                                         return -1;
1968                                 }
1969                         } else {
1970                                 /*
1971                                  * Well, we can at least look at the next
1972                                  * byte.
1973                                  */
1974                                 if (tvb_get_guint8(tvb, eol_offset + 1) == '\n') {
1975                                         /*
1976                                          * It's an LF; skip over the CR.
1977                                          */
1978                                         eol_offset++;
1979                                 }
1980                         }
1981                 }
1982
1983                 /*
1984                  * Return the offset of the character after the last
1985                  * character in the line, skipping over the last character
1986                  * in the line terminator.
1987                  */
1988                 *next_offset = eol_offset + 1;
1989         }
1990         return linelen;
1991 }
1992
1993 /*
1994  * Given a tvbuff, an offset into the tvbuff, and a length that starts
1995  * at that offset (which may be -1 for "all the way to the end of the
1996  * tvbuff"), find the end of the (putative) line that starts at the
1997  * specified offset in the tvbuff, going no further than the specified
1998  * length.
1999  *
2000  * However, treat quoted strings inside the buffer specially - don't
2001  * treat newlines in quoted strings as line terminators.
2002  *
2003  * Return the length of the line (not counting the line terminator at
2004  * the end), or the amount of data remaining in the buffer if we don't
2005  * find a line terminator.
2006  *
2007  * Set "*next_offset" to the offset of the character past the line
2008  * terminator, or past the end of the buffer if we don't find a line
2009  * terminator.
2010  */
2011 gint
2012 tvb_find_line_end_unquoted(tvbuff_t *tvb, gint offset, int len,
2013     gint *next_offset)
2014 {
2015         gint cur_offset, char_offset;
2016         gboolean is_quoted;
2017         guchar c;
2018         gint eob_offset;
2019         int linelen;
2020
2021         if (len == -1)
2022                 len = tvb_length_remaining(tvb, offset);
2023         /*
2024          * XXX - what if "len" is still -1, meaning "offset is past the
2025          * end of the tvbuff"?
2026          */
2027         eob_offset = offset + len;
2028
2029         cur_offset = offset;
2030         is_quoted = FALSE;
2031         for (;;) {
2032                 /*
2033                  * Is this part of the string quoted?
2034                  */
2035                 if (is_quoted) {
2036                         /*
2037                          * Yes - look only for the terminating quote.
2038                          */
2039                         char_offset = tvb_find_guint8(tvb, cur_offset, len,
2040                             '"');
2041                 } else {
2042                         /*
2043                          * Look either for a CR, an LF, or a '"'.
2044                          */
2045                         char_offset = tvb_pbrk_guint8(tvb, cur_offset, len,
2046                             (guint8 *)"\r\n\"");
2047                 }
2048                 if (char_offset == -1) {
2049                         /*
2050                          * Not found - line is presumably continued in
2051                          * next packet.
2052                          * We pretend the line runs to the end of the tvbuff.
2053                          */
2054                         linelen = eob_offset - offset;
2055                         *next_offset = eob_offset;
2056                         break;
2057                 }
2058
2059                 if (is_quoted) {
2060                         /*
2061                          * We're processing a quoted string.
2062                          * We only looked for ", so we know it's a ";
2063                          * as we're processing a quoted string, it's a
2064                          * closing quote.
2065                          */
2066                         is_quoted = FALSE;
2067                 } else {
2068                         /*
2069                          * OK, what is it?
2070                          */
2071                         c = tvb_get_guint8(tvb, char_offset);
2072                         if (c == '"') {
2073                                 /*
2074                                  * Un-quoted "; it begins a quoted
2075                                  * string.
2076                                  */
2077                                 is_quoted = TRUE;
2078                         } else {
2079                                 /*
2080                                  * It's a CR or LF; we've found a line
2081                                  * terminator.
2082                                  *
2083                                  * Find the number of bytes between the
2084                                  * starting offset and the CR or LF.
2085                                  */
2086                                 linelen = char_offset - offset;
2087
2088                                 /*
2089                                  * Is it a CR?
2090                                  */
2091                                 if (c == '\r') {
2092                                         /*
2093                                          * Yes; is it followed by an LF?
2094                                          */
2095                                         if (char_offset + 1 < eob_offset &&
2096                                             tvb_get_guint8(tvb, char_offset + 1)
2097                                               == '\n') {
2098                                                 /*
2099                                                  * Yes; skip over the CR.
2100                                                  */
2101                                                 char_offset++;
2102                                         }
2103                                 }
2104
2105                                 /*
2106                                  * Return the offset of the character after
2107                                  * the last character in the line, skipping
2108                                  * over the last character in the line
2109                                  * terminator, and quit.
2110                                  */
2111                                 *next_offset = char_offset + 1;
2112                                 break;
2113                         }
2114                 }
2115
2116                 /*
2117                  * Step past the character we found.
2118                  */
2119                 cur_offset = char_offset + 1;
2120                 if (cur_offset >= eob_offset) {
2121                         /*
2122                          * The character we found was the last character
2123                          * in the tvbuff - line is presumably continued in
2124                          * next packet.
2125                          * We pretend the line runs to the end of the tvbuff.
2126                          */
2127                         linelen = eob_offset - offset;
2128                         *next_offset = eob_offset;
2129                         break;
2130                 }
2131         }
2132         return linelen;
2133 }
2134
2135 /*
2136  * Format a bunch of data from a tvbuff as bytes, returning a pointer
2137  * to the string with the formatted data, with "punct" as a byte
2138  * separator.
2139  */
2140 gchar *
2141 tvb_bytes_to_str_punct(tvbuff_t *tvb, gint offset, gint len, gchar punct)
2142 {
2143         return bytes_to_str_punct(tvb_get_ptr(tvb, offset, len), len, punct);
2144 }
2145
2146 /*
2147  * Format a bunch of data from a tvbuff as bytes, returning a pointer
2148  * to the string with the formatted data.
2149  */
2150 gchar *
2151 tvb_bytes_to_str(tvbuff_t *tvb, gint offset, gint len)
2152 {
2153         return bytes_to_str(tvb_get_ptr(tvb, offset, len), len);
2154 }
2155
2156 /* Find a needle tvbuff within a haystack tvbuff. */
2157 gint
2158 tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, gint haystack_offset)
2159 {
2160         guint           haystack_abs_offset, haystack_abs_length;
2161         const guint8    *haystack_data;
2162         const guint8    *needle_data;
2163         const guint     needle_len = needle_tvb->length;
2164         const guint8    *location;
2165
2166         if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
2167                 return -1;
2168         }
2169
2170         /* Get pointers to the tvbuffs' data. */
2171         haystack_data = tvb_get_ptr(haystack_tvb, 0, -1);
2172         needle_data = tvb_get_ptr(needle_tvb, 0, -1);
2173
2174         check_offset_length(haystack_tvb, haystack_offset, -1,
2175                         &haystack_abs_offset, &haystack_abs_length);
2176
2177         location = epan_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
2178                         needle_data, needle_len);
2179
2180         if (location) {
2181                 return location - haystack_data;
2182         }
2183         else {
2184                 return -1;
2185         }
2186
2187         return -1;
2188 }
2189
2190 #ifdef HAVE_LIBZ
2191 /*
2192  * Uncompresses a zlib compressed packet inside a message of tvb at offset with
2193  * length comprlen.  Returns an uncompressed tvbuffer if uncompression
2194  * succeeded or NULL if uncompression failed.
2195  */
2196 #define TVB_Z_MIN_BUFSIZ 32768
2197 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
2198 /* #define TVB_Z_DEBUG 1 */
2199 #undef TVB_Z_DEBUG
2200
2201 tvbuff_t *
2202 tvb_uncompress(tvbuff_t *tvb, int offset, int comprlen)
2203 {
2204         
2205
2206         gint err = Z_OK;
2207         guint bytes_out = 0;
2208         guint8 *compr = NULL;
2209         guint8 *uncompr = NULL;
2210         tvbuff_t *uncompr_tvb = NULL;
2211         z_streamp strm = NULL;
2212         Bytef *strmbuf = NULL;
2213         guint inits_done = 0;
2214         gint wbits = MAX_WBITS;
2215         guint8 *next = NULL;
2216         guint bufsiz = TVB_Z_MIN_BUFSIZ;
2217 #ifdef TVB_Z_DEBUG
2218         guint inflate_passes = 0;
2219         guint bytes_in = tvb_length_remaining(tvb, offset);
2220 #endif
2221
2222         if (tvb == NULL) {
2223                 return NULL;
2224         }
2225
2226         strm = g_malloc0(sizeof(z_stream));
2227
2228         if (strm == NULL) {
2229                 return NULL;
2230         }
2231
2232         compr = tvb_memdup(tvb, offset, comprlen);
2233
2234         if (!compr) {
2235                 g_free(strm);
2236                 return NULL;
2237         }
2238
2239         /* 
2240          * Assume that the uncompressed data is at least twice as big as
2241          * the compressed size.
2242          */
2243         bufsiz = tvb_length_remaining(tvb, offset) * 2;
2244
2245         if (bufsiz < TVB_Z_MIN_BUFSIZ) {
2246                 bufsiz = TVB_Z_MIN_BUFSIZ;
2247         } else if (bufsiz > TVB_Z_MAX_BUFSIZ) {
2248                 bufsiz = TVB_Z_MIN_BUFSIZ;
2249         }
2250
2251 #ifdef TVB_Z_DEBUG
2252         printf("bufsiz: %u bytes\n", bufsiz);
2253 #endif
2254
2255         next = compr;
2256
2257         strm->next_in = next;
2258         strm->avail_in = comprlen;
2259
2260
2261         strmbuf = g_malloc0(bufsiz);
2262
2263         if(strmbuf == NULL) {
2264                 g_free(compr);
2265                 g_free(strm);
2266                 return NULL;
2267         }
2268
2269         strm->next_out = strmbuf;
2270         strm->avail_out = bufsiz;
2271
2272         err = inflateInit2(strm, wbits);
2273         inits_done = 1;
2274         if (err != Z_OK) {
2275                 g_free(strm);
2276                 g_free(compr);
2277                 g_free(strmbuf);
2278                 return NULL;
2279         }
2280
2281         while (1) {
2282                 memset(strmbuf, '\0', bufsiz);
2283                 strm->next_out = strmbuf;
2284                 strm->avail_out = bufsiz;
2285
2286                 err = inflate(strm, Z_SYNC_FLUSH);
2287
2288                 if (err == Z_OK || err == Z_STREAM_END) {
2289                         guint bytes_pass = bufsiz - strm->avail_out;
2290
2291 #ifdef TVB_Z_DEBUG
2292                         ++inflate_passes;
2293 #endif
2294
2295                         if (uncompr == NULL) {
2296                                 uncompr = g_memdup(strmbuf, bytes_pass);
2297                         } else {
2298                                 guint8 *new_data = g_malloc0(bytes_out +
2299                                     bytes_pass);
2300
2301                                 if (new_data == NULL) {
2302                                         g_free(strm);
2303                                         g_free(strmbuf);
2304                                         g_free(compr);
2305
2306                                         if (uncompr != NULL) {
2307                                                 g_free(uncompr);
2308                                         }
2309                                         
2310                                         return NULL;
2311                                 }
2312                                 
2313                                 g_memmove(new_data, uncompr, bytes_out);
2314                                 g_memmove((new_data + bytes_out), strmbuf,
2315                                     bytes_pass);
2316
2317                                 g_free(uncompr);
2318                                 uncompr = new_data;
2319                         }
2320
2321                         bytes_out += bytes_pass;
2322
2323                         if ( err == Z_STREAM_END) {
2324                                 inflateEnd(strm);
2325                                 g_free(strm);
2326                                 g_free(strmbuf);
2327                                 break;
2328                         }
2329                 } else if (err == Z_BUF_ERROR) {
2330                         /*
2331                          * It's possible that not enough frames were captured
2332                          * to decompress this fully, so return what we've done
2333                          * so far, if any.
2334                          */
2335
2336                         g_free(strm);
2337                         g_free(strmbuf);
2338
2339                         if (uncompr != NULL) {
2340                                 break;
2341                         } else {
2342                                 g_free(compr);
2343                                 return NULL;
2344                         }
2345                         
2346                 } else if (err == Z_DATA_ERROR && inits_done == 1
2347                     && uncompr == NULL && (*compr  == 0x1f) &&
2348                     (*(compr + 1) == 0x8b)) {
2349                         /*
2350                          * inflate() is supposed to handle both gzip and deflate
2351                          * streams automatically, but in reality it doesn't
2352                          * seem to handle either (at least not within the
2353                          * context of an HTTP response.)  We have to try
2354                          * several tweaks, depending on the type of data and
2355                          * version of the library installed.
2356                          */
2357
2358                         /*
2359                          * Gzip file format.  Skip past the header, since the
2360                          * fix to make it work (setting windowBits to 31)
2361                          * doesn't work with all versions of the library.
2362                          */
2363                         Bytef *c = compr + 2;
2364                         Bytef flags = 0;
2365
2366                         if (*c == Z_DEFLATED) {
2367                                 c++;
2368                         } else {
2369                                 g_free(strm);
2370                                 g_free(compr);
2371                                 g_free(strmbuf);
2372                                 return NULL;
2373                         }
2374
2375                         flags = *c;
2376
2377                         /* Skip past the MTIME, XFL, and OS fields. */
2378                         c += 7;
2379
2380                         if (flags & (1 << 2)) {
2381                                 /* An Extra field is present. */
2382                                 gint xsize = (gint)(*c |
2383                                     (*(c + 1) << 8));
2384
2385                                 c += xsize;
2386                         }
2387
2388                         if (flags & (1 << 3)) {
2389                                 /* A null terminated filename */
2390
2391                                 while (*c != '\0') {
2392                                         c++;
2393                                 }
2394
2395                                 c++;
2396                         }
2397
2398                         if (flags & (1 << 4)) {
2399                                 /* A null terminated comment */
2400                                 
2401                                 while (*c != '\0') {
2402                                         c++;
2403                                 }
2404
2405                                 c++;
2406                         }
2407
2408
2409                         inflateReset(strm);
2410                         next = c;
2411                         strm->next_in = next;
2412                         comprlen -= (c - compr);
2413                         
2414                         err = inflateInit2(strm, wbits);
2415                         inits_done++;
2416                 } else if (err == Z_DATA_ERROR && uncompr == NULL &&
2417                     inits_done <= 3) {
2418                         
2419                         /* 
2420                          * Re-init the stream with a negative
2421                          * MAX_WBITS. This is necessary due to
2422                          * some servers (Apache) not sending
2423                          * the deflate header with the
2424                          * content-encoded response.
2425                          */
2426                         wbits = -MAX_WBITS;
2427
2428                         inflateReset(strm);
2429
2430                         strm->next_in = next;
2431                         strm->avail_in = comprlen;
2432
2433                         memset(strmbuf, '\0', bufsiz);
2434                         strm->next_out = strmbuf;
2435                         strm->avail_out = bufsiz;
2436
2437                         err = inflateInit2(strm, wbits);
2438                                 
2439                         inits_done++;
2440                         
2441                         if (err != Z_OK) {
2442                                 g_free(strm);
2443                                 g_free(strmbuf);
2444                                 g_free(compr);
2445                                 g_free(uncompr);
2446
2447                                 return NULL;
2448                         }
2449                 } else {
2450                         g_free(strm);
2451                         g_free(strmbuf);
2452                         g_free(compr);
2453
2454                         if (uncompr == NULL) {
2455                                 return NULL;
2456                         }
2457
2458                         break;
2459                 }
2460         }
2461
2462 #ifdef TVB_Z_DEBUG
2463         printf("inflate() total passes: %u\n", inflate_passes);
2464         printf("bytes  in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
2465 #endif
2466         
2467         if (uncompr != NULL) {
2468                 uncompr_tvb =  tvb_new_real_data((guint8*) uncompr, bytes_out,
2469                     bytes_out);
2470                 tvb_set_free_cb(uncompr_tvb, g_free);
2471         }
2472         g_free(compr);
2473         return uncompr_tvb;
2474 }
2475 #else
2476 tvbuff_t *
2477 tvb_uncompress(tvbuff_t *tvb _U_, int offset _U_, int comprlen _U_)
2478 {
2479         return NULL;
2480 }
2481 #endif
2482