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