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