Bug Summary

File:epan/tvbuff.c
Warning:line 514, column 13
Potential leak of memory pointed to by 'data'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tvbuff.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /builds/wireshark/wireshark/build/epan -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /usr/include/lua5.4 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D epan_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-12-07-100356-3573-1 -x c /builds/wireshark/wireshark/epan/tvbuff.c
1/* tvbuff.c
2 *
3 * Testy, Virtual(-izable) Buffer of uint8_t*'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 * SPDX-License-Identifier: GPL-2.0-or-later
22 */
23
24#include "config.h"
25
26#include <string.h>
27#include <stdio.h>
28#include <errno(*__errno_location ()).h>
29
30#include <glib.h>
31
32#include "wsutil/pint.h"
33#include "wsutil/sign_ext.h"
34#include "wsutil/strtoi.h"
35#include "wsutil/unicode-utils.h"
36#include "wsutil/nstime.h"
37#include "wsutil/time_util.h"
38#include <wsutil/ws_assert.h>
39#include "tvbuff.h"
40#include "tvbuff-int.h"
41#include "strutil.h"
42#include "to_str.h"
43#include "charsets.h"
44#include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
45#include "exceptions.h"
46
47#include <time.h>
48
49static uint64_t
50_tvb_get_bits64(tvbuff_t *tvb, unsigned bit_offset, const int total_no_of_bits);
51
52static uint64_t
53_tvb_get_bits64_le(tvbuff_t *tvb, unsigned bit_offset, const int total_no_of_bits);
54
55static inline int
56_tvb_captured_length_remaining(const tvbuff_t *tvb, const int offset);
57
58static inline const uint8_t*
59ensure_contiguous(tvbuff_t *tvb, const int offset, const int length);
60
61static inline uint8_t *
62tvb_get_raw_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int length);
63
64tvbuff_t *
65tvb_new(const struct tvb_ops *ops)
66{
67 tvbuff_t *tvb;
68 size_t size = ops->tvb_size;
69
70 ws_assert(size >= sizeof(*tvb))do { if ((1) && !(size >= sizeof(*tvb))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/tvbuff.c", 70, __func__, "assertion failed: %s"
, "size >= sizeof(*tvb)"); } while (0)
;
71
72 tvb = (tvbuff_t *) g_slice_alloc(size);
73
74 tvb->next = NULL((void*)0);
75 tvb->ops = ops;
76 tvb->initialized = false0;
77 tvb->flags = 0;
78 tvb->length = 0;
79 tvb->reported_length = 0;
80 tvb->contained_length = 0;
81 tvb->real_data = NULL((void*)0);
82 tvb->raw_offset = -1;
83 tvb->ds_tvb = NULL((void*)0);
84
85 return tvb;
86}
87
88static void
89tvb_free_internal(tvbuff_t *tvb)
90{
91 size_t size;
92
93 DISSECTOR_ASSERT(tvb)((void) ((tvb) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/tvbuff.c", 93, "tvb"))))
;
94
95 if (tvb->ops->tvb_free)
96 tvb->ops->tvb_free(tvb);
97
98 size = tvb->ops->tvb_size;
99
100 g_slice_free1(size, tvb);
101}
102
103/* XXX: just call tvb_free_chain();
104 * Not removed so that existing dissectors using tvb_free() need not be changed.
105 * I'd argue that existing calls to tvb_free() should have actually been
106 * calls to tvb_free_chain() although the calls were OK as long as no
107 * subsets, etc had been created on the tvb. */
108void
109tvb_free(tvbuff_t *tvb)
110{
111 tvb_free_chain(tvb);
112}
113
114void
115tvb_free_chain(tvbuff_t *tvb)
116{
117 tvbuff_t *next_tvb;
118 DISSECTOR_ASSERT(tvb)((void) ((tvb) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/tvbuff.c", 118, "tvb"))))
;
119 while (tvb) {
120 next_tvb = tvb->next;
121 tvb_free_internal(tvb);
122 tvb = next_tvb;
123 }
124}
125
126tvbuff_t *
127tvb_new_chain(tvbuff_t *parent, tvbuff_t *backing)
128{
129 tvbuff_t *tvb = tvb_new_proxy(backing);
130
131 tvb_add_to_chain(parent, tvb);
132 return tvb;
133}
134
135void
136tvb_add_to_chain(tvbuff_t *parent, tvbuff_t *child)
137{
138 tvbuff_t *tmp;
139
140 DISSECTOR_ASSERT(parent)((void) ((parent) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/tvbuff.c", 140, "parent"))))
;
141 DISSECTOR_ASSERT(child)((void) ((child) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/tvbuff.c", 141, "child"))))
;
142
143 while (child) {
144 tmp = child;
145 child = child->next;
146
147 tmp->next = parent->next;
148 parent->next = tmp;
149 }
150}
151
152/*
153 * Check whether that offset goes more than one byte past the
154 * end of the buffer.
155 *
156 * If not, return 0; otherwise, return exception
157 */
158static inline int
159validate_offset(const tvbuff_t *tvb, const unsigned abs_offset)
160{
161 if (G_LIKELY(abs_offset <= tvb->length)(abs_offset <= tvb->length)) {
162 /* It's OK. */
163 return 0;
164 }
165
166 /*
167 * It's not OK, but why? Which boundaries is it
168 * past?
169 */
170 if (abs_offset <= tvb->contained_length) {
171 /*
172 * It's past the captured length, but not past
173 * the reported end of any parent tvbuffs from
174 * which this is constructed, or the reported
175 * end of this tvbuff, so it's out of bounds
176 * solely because we're past the end of the
177 * captured data.
178 */
179 return BoundsError1;
180 }
181
182 /*
183 * There's some actual packet boundary, not just the
184 * artificial boundary imposed by packet slicing, that
185 * we're past.
186 */
187
188 if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
189 /*
190 * This tvbuff is the first fragment of a larger
191 * packet that hasn't been reassembled, so we
192 * assume that's the source of the problem - if
193 * we'd reassembled the packet, we wouldn't have
194 * gone past the end.
195 *
196 * That might not be true, but for at least
197 * some forms of reassembly, such as IP
198 * reassembly, you don't know how big the
199 * reassembled packet is unless you reassemble
200 * it, so, in those cases, we can't determine
201 * whether we would have gone past the end
202 * had we reassembled the packet.
203 */
204 return FragmentBoundsError4;
205 }
206
207 /* OK, we're not an unreassembled fragment (that we know of). */
208 if (abs_offset <= tvb->reported_length) {
209 /*
210 * We're within the bounds of what this tvbuff
211 * purportedly contains, based on some length
212 * value, but we're not within the bounds of
213 * something from which this tvbuff was
214 * extracted, so that length value ran past
215 * the end of some parent tvbuff.
216 */
217 return ContainedBoundsError2;
218 }
219
220 /*
221 * OK, it looks as if we ran past the claimed length
222 * of data.
223 */
224 return ReportedBoundsError3;
225}
226
227static inline int
228compute_offset(const tvbuff_t *tvb, const int offset, unsigned *offset_ptr)
229{
230 if (offset >= 0) {
231 /* Positive offset - relative to the beginning of the packet. */
232 if (G_LIKELY((unsigned) offset <= tvb->length)((unsigned) offset <= tvb->length)) {
233 *offset_ptr = offset;
234 } else if ((unsigned) offset <= tvb->contained_length) {
235 return BoundsError1;
236 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
237 return FragmentBoundsError4;
238 } else if ((unsigned) offset <= tvb->reported_length) {
239 return ContainedBoundsError2;
240 } else {
241 return ReportedBoundsError3;
242 }
243 }
244 else {
245 /* Negative offset - relative to the end of the packet. */
246 /* Prevent UB on 2's complement platforms. All tested compilers
247 * (gcc, clang, MSVC) compile this to a single instruction on
248 * x86, ARM, RISC-V, S390x, SPARC, etc. at -O1 and higher
249 * according to godbolt.org. */
250 unsigned abs_offset = ((unsigned)-(offset + 1)) + 1;
251 if (G_LIKELY(abs_offset <= tvb->length)(abs_offset <= tvb->length)) {
252 *offset_ptr = tvb->length - abs_offset;
253 } else if (abs_offset <= tvb->contained_length) {
254 return BoundsError1;
255 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
256 return FragmentBoundsError4;
257 } else if (abs_offset <= tvb->reported_length) {
258 return ContainedBoundsError2;
259 } else {
260 return ReportedBoundsError3;
261 }
262 }
263
264 return 0;
265}
266
267static inline int
268compute_offset_and_remaining(const tvbuff_t *tvb, const int offset, unsigned *offset_ptr, unsigned *rem_len)
269{
270 int exception;
271
272 exception = compute_offset(tvb, offset, offset_ptr);
273 if (!exception)
274 *rem_len = tvb->length - *offset_ptr;
275
276 return exception;
277}
278
279/* Computes the absolute offset and length based on a possibly-negative offset
280 * and a length that is possible -1 (which means "to the end of the data").
281 * Returns integer indicating whether the offset is in bounds (0) or
282 * not (exception number). The integer ptrs are modified with the new offset,
283 * captured (available) length, and contained length (amount that's present
284 * in the parent tvbuff based on its reported length).
285 * No exception is thrown; on success, we return 0, otherwise we return an
286 * exception for the caller to throw if appropriate.
287 *
288 * XXX - we return success (0), if the offset is positive and right
289 * after the end of the tvbuff (i.e., equal to the length). We do this
290 * so that a dissector constructing a subset tvbuff for the next protocol
291 * will get a zero-length tvbuff, not an exception, if there's no data
292 * left for the next protocol - we want the next protocol to be the one
293 * that gets an exception, so the error is reported as an error in that
294 * protocol rather than the containing protocol. */
295static inline int
296check_offset_length_no_exception(const tvbuff_t *tvb,
297 const int offset, int const length_val,
298 unsigned *offset_ptr, unsigned *length_ptr)
299{
300 unsigned end_offset;
301 int exception;
302
303 DISSECTOR_ASSERT(offset_ptr)((void) ((offset_ptr) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 303, "offset_ptr"
))))
;
304 DISSECTOR_ASSERT(length_ptr)((void) ((length_ptr) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 304, "length_ptr"
))))
;
305
306 /* Compute the offset */
307 exception = compute_offset(tvb, offset, offset_ptr);
308 if (exception)
309 return exception;
310
311 if (length_val < -1) {
312 /* XXX - ReportedBoundsError? */
313 return BoundsError1;
314 }
315
316 /* Compute the length */
317 if (length_val == -1)
318 *length_ptr = tvb->length - *offset_ptr;
319 else
320 *length_ptr = length_val;
321
322 /*
323 * Compute the offset of the first byte past the length.
324 */
325 end_offset = *offset_ptr + *length_ptr;
326
327 /*
328 * Check for an overflow
329 */
330 if (end_offset < *offset_ptr)
331 return BoundsError1;
332
333 return validate_offset(tvb, end_offset);
334}
335
336/* Checks (+/-) offset and length and throws an exception if
337 * either is out of bounds. Sets integer ptrs to the new offset
338 * and length. */
339static inline void
340check_offset_length(const tvbuff_t *tvb,
341 const int offset, int const length_val,
342 unsigned *offset_ptr, unsigned *length_ptr)
343{
344 int exception;
345
346 exception = check_offset_length_no_exception(tvb, offset, length_val, offset_ptr, length_ptr);
347 if (exception)
348 THROW(exception)except_throw(1, (exception), ((void*)0));
349}
350
351void
352tvb_check_offset_length(const tvbuff_t *tvb,
353 const int offset, int const length_val,
354 unsigned *offset_ptr, unsigned *length_ptr)
355{
356 check_offset_length(tvb, offset, length_val, offset_ptr, length_ptr);
357}
358
359static const unsigned char left_aligned_bitmask[] = {
360 0xff,
361 0x80,
362 0xc0,
363 0xe0,
364 0xf0,
365 0xf8,
366 0xfc,
367 0xfe
368};
369
370tvbuff_t *
371tvb_new_octet_aligned(tvbuff_t *tvb, uint32_t bit_offset, int32_t no_of_bits)
372{
373 tvbuff_t *sub_tvb = NULL((void*)0);
374 uint32_t byte_offset;
375 int32_t datalen, i;
376 uint8_t left, right, remaining_bits, *buf;
377 const uint8_t *data;
378
379 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 379, "tvb && tvb->initialized"
))))
;
380
381 byte_offset = bit_offset >> 3;
382 left = bit_offset % 8; /* for left-shifting */
383 right = 8 - left; /* for right-shifting */
384
385 if (no_of_bits == -1) {
386 datalen = _tvb_captured_length_remaining(tvb, byte_offset);
387 remaining_bits = 0;
388 } else {
389 datalen = no_of_bits >> 3;
390 remaining_bits = no_of_bits % 8;
391 if (remaining_bits) {
392 datalen++;
393 }
394 }
395
396 /* already aligned -> shortcut */
397 if ((left == 0) && (remaining_bits == 0)) {
398 return tvb_new_subset_length_caplen(tvb, byte_offset, datalen, datalen);
399 }
400
401 DISSECTOR_ASSERT(datalen>0)((void) ((datalen>0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 401, "datalen>0"
))))
;
402
403 /* if at least one trailing byte is available, we must use the content
404 * of that byte for the last shift (i.e. tvb_get_ptr() must use datalen + 1
405 * if non extra byte is available, the last shifted byte requires
406 * special treatment
407 */
408 if (_tvb_captured_length_remaining(tvb, byte_offset) > datalen) {
409 data = ensure_contiguous(tvb, byte_offset, datalen + 1); /* tvb_get_ptr */
410
411 /* Do this allocation AFTER tvb_get_ptr() (which could throw an exception) */
412 buf = (uint8_t *)g_malloc(datalen);
413
414 /* shift tvb data bit_offset bits to the left */
415 for (i = 0; i < datalen; i++)
416 buf[i] = (data[i] << left) | (data[i+1] >> right);
417 } else {
418 data = ensure_contiguous(tvb, byte_offset, datalen); /* tvb_get_ptr() */
419
420 /* Do this allocation AFTER tvb_get_ptr() (which could throw an exception) */
421 buf = (uint8_t *)g_malloc(datalen);
422
423 /* shift tvb data bit_offset bits to the left */
424 for (i = 0; i < (datalen-1); i++)
425 buf[i] = (data[i] << left) | (data[i+1] >> right);
426 buf[datalen-1] = data[datalen-1] << left; /* set last octet */
427 }
428 buf[datalen-1] &= left_aligned_bitmask[remaining_bits];
429
430 sub_tvb = tvb_new_child_real_data(tvb, buf, datalen, datalen);
431 tvb_set_free_cb(sub_tvb, g_free);
432
433 return sub_tvb;
434}
435
436tvbuff_t *
437tvb_new_octet_right_aligned(tvbuff_t *tvb, uint32_t bit_offset, int32_t no_of_bits)
438{
439 tvbuff_t *sub_tvb = NULL((void*)0);
440 uint32_t byte_offset;
441 int src_len, dst_len, i;
442 uint8_t left, right, remaining_bits, *buf;
443 const uint8_t *data;
444
445 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 445, "tvb && tvb->initialized"
))))
;
446
447 byte_offset = bit_offset / 8;
448 /* right shift to put bits in place and discard least significant bits */
449 right = bit_offset % 8;
450 /* left shift to get most significant bits from next octet */
451 left = 8 - right;
452
453 if (no_of_bits == -1) {
454 dst_len = _tvb_captured_length_remaining(tvb, byte_offset);
455 remaining_bits = 0;
456 } else {
457 dst_len = no_of_bits / 8;
458 remaining_bits = no_of_bits % 8;
459 if (remaining_bits) {
460 dst_len++;
461 }
462 }
463
464 /* already aligned -> shortcut */
465 if ((right == 0) && (remaining_bits == 0)) {
466 return tvb_new_subset_length_caplen(tvb, byte_offset, dst_len, dst_len);
467 }
468
469 DISSECTOR_ASSERT(dst_len>0)((void) ((dst_len>0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 469, "dst_len>0"
))))
;
470
471 if (_tvb_captured_length_remaining(tvb, byte_offset) > dst_len) {
472 /* last octet will get data from trailing octet */
473 src_len = dst_len + 1;
474 } else {
475 /* last octet will be zero padded */
476 src_len = dst_len;
477 }
478
479 data = ensure_contiguous(tvb, byte_offset, src_len); /* tvb_get_ptr */
480
481 /* Do this allocation AFTER tvb_get_ptr() (which could throw an exception) */
482 buf = (uint8_t *)g_malloc(dst_len);
483
484 for (i = 0; i < (dst_len - 1); i++)
485 buf[i] = (data[i] >> right) | (data[i+1] << left);
486
487 /* Special handling for last octet */
488 buf[i] = (data[i] >> right);
489 /* Shift most significant bits from trailing octet if available */
490 if (src_len > dst_len)
491 buf[i] |= (data[i+1] << left);
492 /* Preserve only remaining bits in last octet if not multiple of 8 */
493 if (remaining_bits)
494 buf[i] &= ((1 << remaining_bits) - 1);
495
496 sub_tvb = tvb_new_child_real_data(tvb, buf, dst_len, dst_len);
497 tvb_set_free_cb(sub_tvb, g_free);
498
499 return sub_tvb;
500}
501
502static tvbuff_t *
503tvb_generic_clone_offset_len(tvbuff_t *tvb, unsigned offset, unsigned len)
504{
505 tvbuff_t *cloned_tvb;
506 uint8_t *data;
507
508 DISSECTOR_ASSERT(tvb_bytes_exist(tvb, offset, len))((void) ((tvb_bytes_exist(tvb, offset, len)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 508, "tvb_bytes_exist(tvb, offset, len)"
))))
;
5
'?' condition is true
509
510 data = (uint8_t *) g_malloc(len);
6
Memory is allocated
511
512 tvb_memcpy(tvb, data, offset, len);
7
Calling 'tvb_memcpy'
14
Returning from 'tvb_memcpy'
513
514 cloned_tvb = tvb_new_real_data(data, len, len);
15
Potential leak of memory pointed to by 'data'
515 tvb_set_free_cb(cloned_tvb, g_free);
516
517 return cloned_tvb;
518}
519
520tvbuff_t *
521tvb_clone_offset_len(tvbuff_t *tvb, unsigned offset, unsigned len)
522{
523 if (tvb->ops->tvb_clone) {
2
Assuming field 'tvb_clone' is null
3
Taking false branch
524 tvbuff_t *cloned_tvb;
525
526 cloned_tvb = tvb->ops->tvb_clone(tvb, offset, len);
527 if (cloned_tvb)
528 return cloned_tvb;
529 }
530
531 return tvb_generic_clone_offset_len(tvb, offset, len);
4
Calling 'tvb_generic_clone_offset_len'
532}
533
534tvbuff_t *
535tvb_clone(tvbuff_t *tvb)
536{
537 return tvb_clone_offset_len(tvb, 0, tvb->length);
1
Calling 'tvb_clone_offset_len'
538}
539
540unsigned
541tvb_captured_length(const tvbuff_t *tvb)
542{
543 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 543, "tvb && tvb->initialized"
))))
;
544
545 return tvb->length;
546}
547
548/* For tvbuff internal use */
549static inline int
550_tvb_captured_length_remaining(const tvbuff_t *tvb, const int offset)
551{
552 unsigned abs_offset = 0, rem_length;
553 int exception;
554
555 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &rem_length);
556 if (exception)
557 return 0;
558
559 return rem_length;
560}
561
562int
563tvb_captured_length_remaining(const tvbuff_t *tvb, const int offset)
564{
565 unsigned abs_offset = 0, rem_length;
566 int exception;
567
568 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 568, "tvb && tvb->initialized"
))))
;
569
570 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &rem_length);
571 if (exception)
572 return 0;
573
574 return rem_length;
575}
576
577unsigned
578tvb_ensure_captured_length_remaining(const tvbuff_t *tvb, const unsigned offset)
579{
580 unsigned rem_length = 0;
581 int exception;
582
583 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 583, "tvb && tvb->initialized"
))))
;
584
585 exception = validate_offset(tvb, offset);
586 if (exception)
587 THROW(exception)except_throw(1, (exception), ((void*)0));
588
589 rem_length = tvb->length - offset;
590
591 if (rem_length == 0) {
592 /*
593 * This routine ensures there's at least one byte available.
594 * There aren't any bytes available, so throw the appropriate
595 * exception.
596 */
597 if (offset < tvb->contained_length) {
598 THROW(BoundsError)except_throw(1, (1), ((void*)0));
599 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
600 THROW(FragmentBoundsError)except_throw(1, (4), ((void*)0));
601 } else if (offset < tvb->reported_length) {
602 THROW(ContainedBoundsError)except_throw(1, (2), ((void*)0));
603 } else {
604 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
605 }
606 }
607 return rem_length;
608}
609
610/* Validates that 'length' bytes are available starting from
611 * offset (pos/neg). Does not throw an exception. */
612bool_Bool
613tvb_bytes_exist(const tvbuff_t *tvb, const int offset, const int length)
614{
615 unsigned abs_offset = 0, abs_length;
616 int exception;
617
618 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 618, "tvb && tvb->initialized"
))))
;
619
620 /*
621 * Negative lengths are not possible and indicate a bug (e.g. arithmetic
622 * error or an overly large value from packet data).
623 */
624 if (length < 0)
625 return false0;
626
627 exception = check_offset_length_no_exception(tvb, offset, length, &abs_offset, &abs_length);
628 if (exception)
629 return false0;
630
631 return true1;
632}
633
634/* Validates that 'length' bytes, where 'length' is a 64-bit unsigned
635 * integer, are available starting from offset (pos/neg). Throws an
636 * exception if they aren't. */
637void
638tvb_ensure_bytes_exist64(const tvbuff_t *tvb, const int offset, const uint64_t length)
639{
640 /*
641 * Make sure the value fits in a signed integer; if not, assume
642 * that means that it's too big.
643 */
644 if (length > INT_MAX2147483647) {
645 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
646 }
647
648 /* OK, now cast it and try it with tvb_ensure_bytes_exist(). */
649 tvb_ensure_bytes_exist(tvb, offset, (int)length);
650}
651
652/* Validates that 'length' bytes are available starting from
653 * offset (pos/neg). Throws an exception if they aren't. */
654void
655tvb_ensure_bytes_exist(const tvbuff_t *tvb, const int offset, const int length)
656{
657 unsigned real_offset, end_offset;
658
659 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 659, "tvb && tvb->initialized"
))))
;
660
661 /*
662 * -1 doesn't mean "until end of buffer", as that's pointless
663 * for this routine. We must treat it as a Really Large Positive
664 * Number, so that we throw an exception; we throw
665 * ReportedBoundsError, as if it were past even the end of a
666 * reassembled packet, and past the end of even the data we
667 * didn't capture.
668 *
669 * We do the same with other negative lengths.
670 */
671 if (length < 0) {
672 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
673 }
674
675 /* XXX: Below this point could be replaced with a call to
676 * check_offset_length with no functional change, however this is a
677 * *very* hot path and check_offset_length is not well-optimized for
678 * this case (mostly because that function handles length -1 meaning
679 * "until the end of the buffer?"), so we eat some code duplication
680 * for a lot of speedup.
681 *
682 * XXX - Could it be replaced with a call just to compute_offset?
683 */
684
685 if (offset >= 0) {
686 /* Positive offset - relative to the beginning of the packet. */
687 if (G_LIKELY((unsigned) offset <= tvb->length)((unsigned) offset <= tvb->length)) {
688 real_offset = offset;
689 } else if ((unsigned) offset <= tvb->contained_length) {
690 THROW(BoundsError)except_throw(1, (1), ((void*)0));
691 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
692 THROW(FragmentBoundsError)except_throw(1, (4), ((void*)0));
693 } else if ((unsigned) offset <= tvb->reported_length) {
694 THROW(ContainedBoundsError)except_throw(1, (2), ((void*)0));
695 } else {
696 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
697 }
698 }
699 else {
700 /* Negative offset - relative to the end of the packet. */
701 /* Prevent UB on 2's complement platforms. */
702 unsigned abs_offset = ((unsigned)-(offset + 1)) + 1;
703 if (G_LIKELY(abs_offset <= tvb->length)(abs_offset <= tvb->length)) {
704 real_offset = tvb->length - abs_offset;
705 } else if (abs_offset <= tvb->contained_length) {
706 THROW(BoundsError)except_throw(1, (1), ((void*)0));
707 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
708 THROW(FragmentBoundsError)except_throw(1, (4), ((void*)0));
709 } else if (abs_offset <= tvb->reported_length) {
710 THROW(ContainedBoundsError)except_throw(1, (2), ((void*)0));
711 } else {
712 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
713 }
714 }
715
716 /*
717 * Compute the offset of the first byte past the length.
718 */
719 end_offset = real_offset + length;
720
721 /*
722 * Check for an overflow
723 */
724 if (end_offset < real_offset)
725 THROW(BoundsError)except_throw(1, (1), ((void*)0));
726
727 if (G_LIKELY(end_offset <= tvb->length)(end_offset <= tvb->length))
728 return;
729 else if (end_offset <= tvb->contained_length)
730 THROW(BoundsError)except_throw(1, (1), ((void*)0));
731 else if (tvb->flags & TVBUFF_FRAGMENT0x00000001)
732 THROW(FragmentBoundsError)except_throw(1, (4), ((void*)0));
733 else if (end_offset <= tvb->reported_length)
734 THROW(ContainedBoundsError)except_throw(1, (2), ((void*)0));
735 else
736 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
737}
738
739bool_Bool
740tvb_offset_exists(const tvbuff_t *tvb, const int offset)
741{
742 unsigned abs_offset = 0;
743 int exception;
744
745 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 745, "tvb && tvb->initialized"
))))
;
746
747 exception = compute_offset(tvb, offset, &abs_offset);
748 if (exception)
749 return false0;
750
751 /* compute_offset only throws an exception on >, not >= because of the
752 * comment above check_offset_length_no_exception, but here we want the
753 * opposite behaviour so we check ourselves... */
754 return abs_offset < tvb->length;
755}
756
757unsigned
758tvb_reported_length(const tvbuff_t *tvb)
759{
760 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 760, "tvb && tvb->initialized"
))))
;
761
762 return tvb->reported_length;
763}
764
765int
766tvb_reported_length_remaining(const tvbuff_t *tvb, const int offset)
767{
768 unsigned abs_offset = 0;
769 int exception;
770
771 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 771, "tvb && tvb->initialized"
))))
;
772
773 exception = compute_offset(tvb, offset, &abs_offset);
774 if (exception)
775 return 0;
776
777 if (tvb->reported_length >= abs_offset)
778 return tvb->reported_length - abs_offset;
779 else
780 return 0;
781}
782
783unsigned
784tvb_ensure_reported_length_remaining(const tvbuff_t *tvb, const unsigned offset)
785{
786 int exception;
787
788 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 788, "tvb && tvb->initialized"
))))
;
789
790 exception = validate_offset(tvb, offset);
791 if (exception)
792 THROW(exception)except_throw(1, (exception), ((void*)0));
793
794 if (tvb->reported_length >= offset)
795 return tvb->reported_length - offset;
796 else
797 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
798}
799
800/* Set the reported length of a tvbuff to a given value; used for protocols
801 * whose headers contain an explicit length and where the calling
802 * dissector's payload may include padding as well as the packet for
803 * this protocol.
804 * Also adjusts the available and contained length. */
805void
806tvb_set_reported_length(tvbuff_t *tvb, const unsigned reported_length)
807{
808 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 808, "tvb && tvb->initialized"
))))
;
809
810 if (reported_length > tvb->reported_length)
811 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
812
813 tvb->reported_length = reported_length;
814 if (reported_length < tvb->length)
815 tvb->length = reported_length;
816 if (reported_length < tvb->contained_length)
817 tvb->contained_length = reported_length;
818}
819
820/* Repair a tvbuff where the captured length is greater than the
821 * reported length; such a tvbuff makes no sense, as it's impossible
822 * to capture more data than is in the packet.
823 */
824void
825tvb_fix_reported_length(tvbuff_t *tvb)
826{
827 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 827, "tvb && tvb->initialized"
))))
;
828 DISSECTOR_ASSERT(tvb->reported_length < tvb->length)((void) ((tvb->reported_length < tvb->length) ? (void
)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/tvbuff.c", 828, "tvb->reported_length < tvb->length"
))))
;
829
830 tvb->reported_length = tvb->length;
831 if (tvb->contained_length < tvb->length)
832 tvb->contained_length = tvb->length;
833}
834
835unsigned
836tvb_offset_from_real_beginning_counter(const tvbuff_t *tvb, const unsigned counter)
837{
838 if (tvb->ops->tvb_offset)
839 return tvb->ops->tvb_offset(tvb, counter);
840
841 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/tvbuff.c", 841))
;
842 return 0;
843}
844
845unsigned
846tvb_offset_from_real_beginning(const tvbuff_t *tvb)
847{
848 return tvb_offset_from_real_beginning_counter(tvb, 0);
849}
850
851static inline const uint8_t*
852ensure_contiguous_no_exception(tvbuff_t *tvb, const int offset, const int length, int *pexception)
853{
854 unsigned abs_offset = 0, abs_length = 0;
855 int exception;
856
857 exception = check_offset_length_no_exception(tvb, offset, length, &abs_offset, &abs_length);
858 if (exception) {
859 if (pexception)
860 *pexception = exception;
861 return NULL((void*)0);
862 }
863
864 /*
865 * Special case: if the caller (e.g. tvb_get_ptr) requested no data,
866 * then it is acceptable to have an empty tvb (!tvb->real_data).
867 */
868 if (length == 0) {
869 return NULL((void*)0);
870 }
871
872 /*
873 * We know that all the data is present in the tvbuff, so
874 * no exceptions should be thrown.
875 */
876 if (tvb->real_data)
877 return tvb->real_data + abs_offset;
878
879 if (tvb->ops->tvb_get_ptr)
880 return tvb->ops->tvb_get_ptr(tvb, abs_offset, abs_length);
881
882 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/tvbuff.c", 882))
;
883 return NULL((void*)0);
884}
885
886static inline const uint8_t*
887ensure_contiguous(tvbuff_t *tvb, const int offset, const int length)
888{
889 int exception = 0;
890 const uint8_t *p;
891
892 p = ensure_contiguous_no_exception(tvb, offset, length, &exception);
893 if (p == NULL((void*)0) && length != 0) {
894 DISSECTOR_ASSERT(exception > 0)((void) ((exception > 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 894, "exception > 0"
))))
;
895 THROW(exception)except_throw(1, (exception), ((void*)0));
896 }
897 return p;
898}
899
900static inline const uint8_t*
901fast_ensure_contiguous(tvbuff_t *tvb, const int offset, const unsigned length)
902{
903 unsigned end_offset;
904 unsigned u_offset;
905
906 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 906, "tvb && tvb->initialized"
))))
;
907 /* We don't check for overflow in this fast path so we only handle simple types */
908 DISSECTOR_ASSERT(length <= 8)((void) ((length <= 8) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 908, "length <= 8"
))))
;
909
910 if (offset < 0 || !tvb->real_data) {
911 return ensure_contiguous(tvb, offset, length);
912 }
913
914 u_offset = offset;
915 end_offset = u_offset + length;
916
917 if (G_LIKELY(end_offset <= tvb->length)(end_offset <= tvb->length)) {
918 return tvb->real_data + u_offset;
919 } else if (end_offset <= tvb->contained_length) {
920 THROW(BoundsError)except_throw(1, (1), ((void*)0));
921 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
922 THROW(FragmentBoundsError)except_throw(1, (4), ((void*)0));
923 } else if (end_offset <= tvb->reported_length) {
924 THROW(ContainedBoundsError)except_throw(1, (2), ((void*)0));
925 } else {
926 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
927 }
928 /* not reached */
929 return NULL((void*)0);
930}
931
932
933
934/************** ACCESSORS **************/
935
936void *
937tvb_memcpy(tvbuff_t *tvb, void *target, const int offset, size_t length)
938{
939 unsigned abs_offset = 0, abs_length = 0;
940
941 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 941, "tvb && tvb->initialized"
))))
;
8
'?' condition is true
942
943 /*
944 * XXX - we should eliminate the "length = -1 means 'to the end
945 * of the tvbuff'" convention, and use other means to achieve
946 * that; this would let us eliminate a bunch of checks for
947 * negative lengths in cases where the protocol has a 32-bit
948 * length field.
949 *
950 * Allowing -1 but throwing an assertion on other negative
951 * lengths is a bit more work with the length being a size_t;
952 * instead, we check for a length <= 2^31-1.
953 */
954 DISSECTOR_ASSERT(length <= 0x7FFFFFFF)((void) ((length <= 0x7FFFFFFF) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 954, "length <= 0x7FFFFFFF"
))))
;
9
Assuming 'length' is <= 2147483647
10
'?' condition is true
955 check_offset_length(tvb, offset, (int) length, &abs_offset, &abs_length);
956
957 if (target && tvb->real_data) {
11
Assuming 'target' is non-null
12
Assuming field 'real_data' is non-null
13
Taking true branch
958 return memcpy(target, tvb->real_data + abs_offset, abs_length);
959 }
960
961 if (target && tvb->ops->tvb_memcpy)
962 return tvb->ops->tvb_memcpy(tvb, target, abs_offset, abs_length);
963
964 /*
965 * If the length is 0, there's nothing to do.
966 * (tvb->real_data could be null if it's allocated with
967 * a size of length.)
968 */
969 if (length != 0) {
970 /*
971 * XXX, fallback to slower method
972 */
973 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/tvbuff.c", 973))
;
974 }
975 return NULL((void*)0);
976}
977
978
979/*
980 * XXX - this doesn't treat a length of -1 as an error.
981 * If it did, this could replace some code that calls
982 * "tvb_ensure_bytes_exist()" and then allocates a buffer and copies
983 * data to it.
984 *
985 * "composite_get_ptr()" depends on -1 not being
986 * an error; does anything else depend on this routine treating -1 as
987 * meaning "to the end of the buffer"?
988 *
989 * If scope is NULL, memory is allocated with g_malloc() and user must
990 * explicitly free it with g_free().
991 * If scope is not NULL, memory is allocated with the corresponding pool
992 * lifetime.
993 */
994void *
995tvb_memdup(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, size_t length)
996{
997 unsigned abs_offset = 0, abs_length = 0;
998 void *duped;
999
1000 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 1000, "tvb && tvb->initialized"
))))
;
1001
1002 check_offset_length(tvb, offset, (int) length, &abs_offset, &abs_length);
1003
1004 if (abs_length == 0)
1005 return NULL((void*)0);
1006
1007 duped = wmem_alloc(scope, abs_length);
1008 return tvb_memcpy(tvb, duped, abs_offset, abs_length);
1009}
1010
1011
1012
1013const uint8_t*
1014tvb_get_ptr(tvbuff_t *tvb, const int offset, const int length)
1015{
1016 return ensure_contiguous(tvb, offset, length);
1017}
1018
1019/* ---------------- */
1020uint8_t
1021tvb_get_uint8(tvbuff_t *tvb, const int offset)
1022{
1023 const uint8_t *ptr;
1024
1025 ptr = fast_ensure_contiguous(tvb, offset, 1);
1026 return *ptr;
1027}
1028
1029int8_t
1030tvb_get_int8(tvbuff_t *tvb, const int offset)
1031{
1032 const uint8_t *ptr;
1033
1034 ptr = fast_ensure_contiguous(tvb, offset, 1);
1035 return *ptr;
1036}
1037
1038uint16_t
1039tvb_get_ntohs(tvbuff_t *tvb, const int offset)
1040{
1041 const uint8_t *ptr;
1042
1043 ptr = fast_ensure_contiguous(tvb, offset, 2);
1044 return pntohu16(ptr);
1045}
1046
1047int16_t
1048tvb_get_ntohis(tvbuff_t *tvb, const int offset)
1049{
1050 const uint8_t *ptr;
1051
1052 ptr = fast_ensure_contiguous(tvb, offset, 2);
1053 return pntohu16(ptr);
1054}
1055
1056uint32_t
1057tvb_get_ntoh24(tvbuff_t *tvb, const int offset)
1058{
1059 const uint8_t *ptr;
1060
1061 ptr = fast_ensure_contiguous(tvb, offset, 3);
1062 return pntohu24(ptr);
1063}
1064
1065int32_t
1066tvb_get_ntohi24(tvbuff_t *tvb, const int offset)
1067{
1068 uint32_t ret;
1069
1070 ret = ws_sign_ext32(tvb_get_ntoh24(tvb, offset), 24);
1071
1072 return (int32_t)ret;
1073}
1074
1075uint32_t
1076tvb_get_ntohl(tvbuff_t *tvb, const int offset)
1077{
1078 const uint8_t *ptr;
1079
1080 ptr = fast_ensure_contiguous(tvb, offset, 4);
1081 return pntohu32(ptr);
1082}
1083
1084int32_t
1085tvb_get_ntohil(tvbuff_t *tvb, const int offset)
1086{
1087 const uint8_t *ptr;
1088
1089 ptr = fast_ensure_contiguous(tvb, offset, 4);
1090 return pntohu32(ptr);
1091}
1092
1093uint64_t
1094tvb_get_ntoh40(tvbuff_t *tvb, const int offset)
1095{
1096 const uint8_t *ptr;
1097
1098 ptr = fast_ensure_contiguous(tvb, offset, 5);
1099 return pntohu40(ptr);
1100}
1101
1102int64_t
1103tvb_get_ntohi40(tvbuff_t *tvb, const int offset)
1104{
1105 uint64_t ret;
1106
1107 ret = ws_sign_ext64(tvb_get_ntoh40(tvb, offset), 40);
1108
1109 return (int64_t)ret;
1110}
1111
1112uint64_t
1113tvb_get_ntoh48(tvbuff_t *tvb, const int offset)
1114{
1115 const uint8_t *ptr;
1116
1117 ptr = fast_ensure_contiguous(tvb, offset, 6);
1118 return pntohu48(ptr);
1119}
1120
1121int64_t
1122tvb_get_ntohi48(tvbuff_t *tvb, const int offset)
1123{
1124 uint64_t ret;
1125
1126 ret = ws_sign_ext64(tvb_get_ntoh48(tvb, offset), 48);
1127
1128 return (int64_t)ret;
1129}
1130
1131uint64_t
1132tvb_get_ntoh56(tvbuff_t *tvb, const int offset)
1133{
1134 const uint8_t *ptr;
1135
1136 ptr = fast_ensure_contiguous(tvb, offset, 7);
1137 return pntohu56(ptr);
1138}
1139
1140int64_t
1141tvb_get_ntohi56(tvbuff_t *tvb, const int offset)
1142{
1143 uint64_t ret;
1144
1145 ret = ws_sign_ext64(tvb_get_ntoh56(tvb, offset), 56);
1146
1147 return (int64_t)ret;
1148}
1149
1150uint64_t
1151tvb_get_ntoh64(tvbuff_t *tvb, const int offset)
1152{
1153 const uint8_t *ptr;
1154
1155 ptr = fast_ensure_contiguous(tvb, offset, 8);
1156 return pntohu64(ptr);
1157}
1158
1159int64_t
1160tvb_get_ntohi64(tvbuff_t *tvb, const int offset)
1161{
1162 const uint8_t *ptr;
1163
1164 ptr = fast_ensure_contiguous(tvb, offset, 8);
1165 return pntohu64(ptr);
1166}
1167
1168uint16_t
1169tvb_get_uint16(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1170 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1171 return tvb_get_letohs(tvb, offset);
1172 } else {
1173 return tvb_get_ntohs(tvb, offset);
1174 }
1175}
1176
1177int16_t
1178tvb_get_int16(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1179 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1180 return tvb_get_letohis(tvb, offset);
1181 } else {
1182 return tvb_get_ntohis(tvb, offset);
1183 }
1184}
1185
1186uint32_t
1187tvb_get_uint24(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1188 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1189 return tvb_get_letoh24(tvb, offset);
1190 } else {
1191 return tvb_get_ntoh24(tvb, offset);
1192 }
1193}
1194
1195int32_t
1196tvb_get_int24(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1197 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1198 return tvb_get_letohi24(tvb, offset);
1199 } else {
1200 return tvb_get_ntohi24(tvb, offset);
1201 }
1202}
1203
1204uint32_t
1205tvb_get_uint32(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1206 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1207 return tvb_get_letohl(tvb, offset);
1208 } else {
1209 return tvb_get_ntohl(tvb, offset);
1210 }
1211}
1212
1213int32_t
1214tvb_get_int32(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1215 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1216 return tvb_get_letohil(tvb, offset);
1217 } else {
1218 return tvb_get_ntohil(tvb, offset);
1219 }
1220}
1221
1222uint64_t
1223tvb_get_uint40(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1224 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1225 return tvb_get_letoh40(tvb, offset);
1226 } else {
1227 return tvb_get_ntoh40(tvb, offset);
1228 }
1229}
1230
1231int64_t
1232tvb_get_int40(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1233 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1234 return tvb_get_letohi40(tvb, offset);
1235 } else {
1236 return tvb_get_ntohi40(tvb, offset);
1237 }
1238}
1239
1240uint64_t
1241tvb_get_uint48(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1242 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1243 return tvb_get_letoh48(tvb, offset);
1244 } else {
1245 return tvb_get_ntoh48(tvb, offset);
1246 }
1247}
1248
1249int64_t
1250tvb_get_int48(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1251 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1252 return tvb_get_letohi48(tvb, offset);
1253 } else {
1254 return tvb_get_ntohi48(tvb, offset);
1255 }
1256}
1257
1258uint64_t
1259tvb_get_uint56(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1260 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1261 return tvb_get_letoh56(tvb, offset);
1262 } else {
1263 return tvb_get_ntoh56(tvb, offset);
1264 }
1265}
1266
1267int64_t
1268tvb_get_int56(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1269 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1270 return tvb_get_letohi56(tvb, offset);
1271 } else {
1272 return tvb_get_ntohi56(tvb, offset);
1273 }
1274}
1275
1276uint64_t
1277tvb_get_uint64(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1278 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1279 return tvb_get_letoh64(tvb, offset);
1280 } else {
1281 return tvb_get_ntoh64(tvb, offset);
1282 }
1283}
1284
1285uint64_t
1286tvb_get_uint64_with_length(tvbuff_t *tvb, const int offset, unsigned length, const unsigned encoding)
1287{
1288 uint64_t value;
1289
1290 switch (length) {
1291
1292 case 1:
1293 value = tvb_get_uint8(tvb, offset);
1294 break;
1295
1296 case 2:
1297 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letohs(tvb, offset)
1298 : tvb_get_ntohs(tvb, offset);
1299 break;
1300
1301 case 3:
1302 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letoh24(tvb, offset)
1303 : tvb_get_ntoh24(tvb, offset);
1304 break;
1305
1306 case 4:
1307 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letohl(tvb, offset)
1308 : tvb_get_ntohl(tvb, offset);
1309 break;
1310
1311 case 5:
1312 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letoh40(tvb, offset)
1313 : tvb_get_ntoh40(tvb, offset);
1314 break;
1315
1316 case 6:
1317 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letoh48(tvb, offset)
1318 : tvb_get_ntoh48(tvb, offset);
1319 break;
1320
1321 case 7:
1322 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letoh56(tvb, offset)
1323 : tvb_get_ntoh56(tvb, offset);
1324 break;
1325
1326 case 8:
1327 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letoh64(tvb, offset)
1328 : tvb_get_ntoh64(tvb, offset);
1329 break;
1330
1331 default:
1332 if (length < 1) {
1333 value = 0;
1334 } else {
1335 value = (encoding & ENC_LITTLE_ENDIAN0x80000000) ? tvb_get_letoh64(tvb, offset)
1336 : tvb_get_ntoh64(tvb, offset);
1337 }
1338 break;
1339 }
1340 return value;
1341}
1342
1343int64_t
1344tvb_get_int64(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1345 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1346 return tvb_get_letohi64(tvb, offset);
1347 } else {
1348 return tvb_get_ntohi64(tvb, offset);
1349 }
1350}
1351
1352float
1353tvb_get_ieee_float(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1354 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1355 return tvb_get_letohieee_float(tvb, offset);
1356 } else {
1357 return tvb_get_ntohieee_float(tvb, offset);
1358 }
1359}
1360
1361double
1362tvb_get_ieee_double(tvbuff_t *tvb, const int offset, const unsigned encoding) {
1363 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
1364 return tvb_get_letohieee_double(tvb, offset);
1365 } else {
1366 return tvb_get_ntohieee_double(tvb, offset);
1367 }
1368}
1369
1370/*
1371 * Stuff for IEEE float handling on platforms that don't have IEEE
1372 * format as the native floating-point format.
1373 *
1374 * For now, we treat only the VAX as such a platform.
1375 *
1376 * XXX - other non-IEEE boxes that can run UN*X include some Crays,
1377 * and possibly other machines. However, I don't know whether there
1378 * are any other machines that could run Wireshark and that don't use
1379 * IEEE format. As far as I know, all of the main current and past
1380 * commercial microprocessor families on which OSes that support
1381 * Wireshark can run use IEEE format (x86, ARM, 68k, SPARC, MIPS,
1382 * PA-RISC, Alpha, IA-64, and so on), and it appears that the official
1383 * Linux port to System/390 and zArchitecture uses IEEE format floating-
1384 * point rather than IBM hex floating-point (not a huge surprise), so
1385 * I'm not sure that leaves any 32-bit or larger UN*X or Windows boxes,
1386 * other than VAXes, that don't use IEEE format. If you're not running
1387 * UN*X or Windows, the floating-point format is probably going to be
1388 * the least of your problems in a port.
1389 */
1390
1391#if defined(vax)
1392
1393#include <math.h>
1394
1395/*
1396 * Single-precision.
1397 */
1398#define IEEE_SP_NUMBER_WIDTH 32 /* bits in number */
1399#define IEEE_SP_EXP_WIDTH 8 /* bits in exponent */
1400#define IEEE_SP_MANTISSA_WIDTH 23 /* IEEE_SP_NUMBER_WIDTH - 1 - IEEE_SP_EXP_WIDTH */
1401
1402#define IEEE_SP_SIGN_MASK 0x80000000
1403#define IEEE_SP_EXPONENT_MASK 0x7F800000
1404#define IEEE_SP_MANTISSA_MASK 0x007FFFFF
1405#define IEEE_SP_INFINITY IEEE_SP_EXPONENT_MASK
1406
1407#define IEEE_SP_IMPLIED_BIT (1 << IEEE_SP_MANTISSA_WIDTH)
1408#define IEEE_SP_INFINITE ((1 << IEEE_SP_EXP_WIDTH) - 1)
1409#define IEEE_SP_BIAS ((1 << (IEEE_SP_EXP_WIDTH - 1)) - 1)
1410
1411static int
1412ieee_float_is_zero(const uint32_t w)
1413{
1414 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1415}
1416
1417static float
1418get_ieee_float(const uint32_t w)
1419{
1420 long sign;
1421 long exponent;
1422 long mantissa;
1423
1424 sign = w & IEEE_SP_SIGN_MASK;
1425 exponent = w & IEEE_SP_EXPONENT_MASK;
1426 mantissa = w & IEEE_SP_MANTISSA_MASK;
1427
1428 if (ieee_float_is_zero(w)) {
1429 /* number is zero, unnormalized, or not-a-number */
1430 return 0.0;
1431 }
1432#if 0
1433 /*
1434 * XXX - how to handle this?
1435 */
1436 if (IEEE_SP_INFINITY == exponent) {
1437 /*
1438 * number is positive or negative infinity, or a special value
1439 */
1440 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1441 }
1442#endif
1443
1444 exponent = ((exponent >> IEEE_SP_MANTISSA_WIDTH) - IEEE_SP_BIAS) -
1445 IEEE_SP_MANTISSA_WIDTH;
1446 mantissa |= IEEE_SP_IMPLIED_BIT;
1447
1448 if (sign)
1449 return -mantissa * pow(2, exponent);
1450 else
1451 return mantissa * pow(2, exponent);
1452}
1453
1454/*
1455 * Double-precision.
1456 * We assume that if you don't have IEEE floating-point, you have a
1457 * compiler that understands 64-bit integral quantities.
1458 */
1459#define IEEE_DP_NUMBER_WIDTH 64 /* bits in number */
1460#define IEEE_DP_EXP_WIDTH 11 /* bits in exponent */
1461#define IEEE_DP_MANTISSA_WIDTH 52 /* IEEE_DP_NUMBER_WIDTH - 1 - IEEE_DP_EXP_WIDTH */
1462
1463#define IEEE_DP_SIGN_MASK INT64_C(0x8000000000000000)0x8000000000000000L
1464#define IEEE_DP_EXPONENT_MASK INT64_C(0x7FF0000000000000)0x7FF0000000000000L
1465#define IEEE_DP_MANTISSA_MASK INT64_C(0x000FFFFFFFFFFFFF)0x000FFFFFFFFFFFFFL
1466#define IEEE_DP_INFINITY IEEE_DP_EXPONENT_MASK
1467
1468#define IEEE_DP_IMPLIED_BIT (INT64_C(1)1L << IEEE_DP_MANTISSA_WIDTH)
1469#define IEEE_DP_INFINITE ((1 << IEEE_DP_EXP_WIDTH) - 1)
1470#define IEEE_DP_BIAS ((1 << (IEEE_DP_EXP_WIDTH - 1)) - 1)
1471
1472static int
1473ieee_double_is_zero(const uint64_t w)
1474{
1475 return ((w & ~IEEE_SP_SIGN_MASK) == 0);
1476}
1477
1478static double
1479get_ieee_double(const uint64_t w)
1480{
1481 int64_t sign;
1482 int64_t exponent;
1483 int64_t mantissa;
1484
1485 sign = w & IEEE_DP_SIGN_MASK;
1486 exponent = w & IEEE_DP_EXPONENT_MASK;
1487 mantissa = w & IEEE_DP_MANTISSA_MASK;
1488
1489 if (ieee_double_is_zero(w)) {
1490 /* number is zero, unnormalized, or not-a-number */
1491 return 0.0;
1492 }
1493#if 0
1494 /*
1495 * XXX - how to handle this?
1496 */
1497 if (IEEE_DP_INFINITY == exponent) {
1498 /*
1499 * number is positive or negative infinity, or a special value
1500 */
1501 return (sign? MINUS_INFINITY: PLUS_INFINITY);
1502 }
1503#endif
1504
1505 exponent = ((exponent >> IEEE_DP_MANTISSA_WIDTH) - IEEE_DP_BIAS) -
1506 IEEE_DP_MANTISSA_WIDTH;
1507 mantissa |= IEEE_DP_IMPLIED_BIT;
1508
1509 if (sign)
1510 return -mantissa * pow(2, exponent);
1511 else
1512 return mantissa * pow(2, exponent);
1513}
1514#endif
1515
1516/*
1517 * Fetches an IEEE single-precision floating-point number, in
1518 * big-endian form, and returns a "float".
1519 *
1520 * XXX - should this be "double", in case there are IEEE single-
1521 * precision numbers that won't fit in some platform's native
1522 * "float" format?
1523 */
1524float
1525tvb_get_ntohieee_float(tvbuff_t *tvb, const int offset)
1526{
1527#if defined(vax)
1528 return get_ieee_float(tvb_get_ntohl(tvb, offset));
1529#else
1530 union {
1531 float f;
1532 uint32_t w;
1533 } ieee_fp_union;
1534
1535 ieee_fp_union.w = tvb_get_ntohl(tvb, offset);
1536 return ieee_fp_union.f;
1537#endif
1538}
1539
1540/*
1541 * Fetches an IEEE double-precision floating-point number, in
1542 * big-endian form, and returns a "double".
1543 */
1544double
1545tvb_get_ntohieee_double(tvbuff_t *tvb, const int offset)
1546{
1547#if defined(vax)
1548 union {
1549 uint32_t w[2];
1550 uint64_t dw;
1551 } ieee_fp_union;
1552#else
1553 union {
1554 double d;
1555 uint32_t w[2];
1556 } ieee_fp_union;
1557#endif
1558
1559#if G_BYTE_ORDER1234 == G_BIG_ENDIAN4321
1560 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset);
1561 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset+4);
1562#else
1563 ieee_fp_union.w[0] = tvb_get_ntohl(tvb, offset+4);
1564 ieee_fp_union.w[1] = tvb_get_ntohl(tvb, offset);
1565#endif
1566#if defined(vax)
1567 return get_ieee_double(ieee_fp_union.dw);
1568#else
1569 return ieee_fp_union.d;
1570#endif
1571}
1572
1573uint16_t
1574tvb_get_letohs(tvbuff_t *tvb, const int offset)
1575{
1576 const uint8_t *ptr;
1577
1578 ptr = fast_ensure_contiguous(tvb, offset, 2);
1579 return pletohu16(ptr);
1580}
1581
1582int16_t
1583tvb_get_letohis(tvbuff_t *tvb, const int offset)
1584{
1585 const uint8_t *ptr;
1586
1587 ptr = fast_ensure_contiguous(tvb, offset, 2);
1588 return pletohu16(ptr);
1589}
1590
1591uint32_t
1592tvb_get_letoh24(tvbuff_t *tvb, const int offset)
1593{
1594 const uint8_t *ptr;
1595
1596 ptr = fast_ensure_contiguous(tvb, offset, 3);
1597 return pletohu24(ptr);
1598}
1599
1600int32_t
1601tvb_get_letohi24(tvbuff_t *tvb, const int offset)
1602{
1603 uint32_t ret;
1604
1605 ret = ws_sign_ext32(tvb_get_letoh24(tvb, offset), 24);
1606
1607 return (int32_t)ret;
1608}
1609
1610uint32_t
1611tvb_get_letohl(tvbuff_t *tvb, const int offset)
1612{
1613 const uint8_t *ptr;
1614
1615 ptr = fast_ensure_contiguous(tvb, offset, 4);
1616 return pletohu32(ptr);
1617}
1618
1619int32_t
1620tvb_get_letohil(tvbuff_t *tvb, const int offset)
1621{
1622 const uint8_t *ptr;
1623
1624 ptr = fast_ensure_contiguous(tvb, offset, 4);
1625 return pletohu32(ptr);
1626}
1627
1628uint64_t
1629tvb_get_letoh40(tvbuff_t *tvb, const int offset)
1630{
1631 const uint8_t *ptr;
1632
1633 ptr = fast_ensure_contiguous(tvb, offset, 5);
1634 return pletohu40(ptr);
1635}
1636
1637int64_t
1638tvb_get_letohi40(tvbuff_t *tvb, const int offset)
1639{
1640 uint64_t ret;
1641
1642 ret = ws_sign_ext64(tvb_get_letoh40(tvb, offset), 40);
1643
1644 return (int64_t)ret;
1645}
1646
1647uint64_t
1648tvb_get_letoh48(tvbuff_t *tvb, const int offset)
1649{
1650 const uint8_t *ptr;
1651
1652 ptr = fast_ensure_contiguous(tvb, offset, 6);
1653 return pletohu48(ptr);
1654}
1655
1656int64_t
1657tvb_get_letohi48(tvbuff_t *tvb, const int offset)
1658{
1659 uint64_t ret;
1660
1661 ret = ws_sign_ext64(tvb_get_letoh48(tvb, offset), 48);
1662
1663 return (int64_t)ret;
1664}
1665
1666uint64_t
1667tvb_get_letoh56(tvbuff_t *tvb, const int offset)
1668{
1669 const uint8_t *ptr;
1670
1671 ptr = fast_ensure_contiguous(tvb, offset, 7);
1672 return pletohu56(ptr);
1673}
1674
1675int64_t
1676tvb_get_letohi56(tvbuff_t *tvb, const int offset)
1677{
1678 uint64_t ret;
1679
1680 ret = ws_sign_ext64(tvb_get_letoh56(tvb, offset), 56);
1681
1682 return (int64_t)ret;
1683}
1684
1685uint64_t
1686tvb_get_letoh64(tvbuff_t *tvb, const int offset)
1687{
1688 const uint8_t *ptr;
1689
1690 ptr = fast_ensure_contiguous(tvb, offset, 8);
1691 return pletohu64(ptr);
1692}
1693
1694int64_t
1695tvb_get_letohi64(tvbuff_t *tvb, const int offset)
1696{
1697 const uint8_t *ptr;
1698
1699 ptr = fast_ensure_contiguous(tvb, offset, 8);
1700 return pletohu64(ptr);
1701}
1702
1703/*
1704 * Fetches an IEEE single-precision floating-point number, in
1705 * little-endian form, and returns a "float".
1706 *
1707 * XXX - should this be "double", in case there are IEEE single-
1708 * precision numbers that won't fit in some platform's native
1709 * "float" format?
1710 */
1711float
1712tvb_get_letohieee_float(tvbuff_t *tvb, const int offset)
1713{
1714#if defined(vax)
1715 return get_ieee_float(tvb_get_letohl(tvb, offset));
1716#else
1717 union {
1718 float f;
1719 uint32_t w;
1720 } ieee_fp_union;
1721
1722 ieee_fp_union.w = tvb_get_letohl(tvb, offset);
1723 return ieee_fp_union.f;
1724#endif
1725}
1726
1727/*
1728 * Fetches an IEEE double-precision floating-point number, in
1729 * little-endian form, and returns a "double".
1730 */
1731double
1732tvb_get_letohieee_double(tvbuff_t *tvb, const int offset)
1733{
1734#if defined(vax)
1735 union {
1736 uint32_t w[2];
1737 uint64_t dw;
1738 } ieee_fp_union;
1739#else
1740 union {
1741 double d;
1742 uint32_t w[2];
1743 } ieee_fp_union;
1744#endif
1745
1746#if G_BYTE_ORDER1234 == G_BIG_ENDIAN4321
1747 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset+4);
1748 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset);
1749#else
1750 ieee_fp_union.w[0] = tvb_get_letohl(tvb, offset);
1751 ieee_fp_union.w[1] = tvb_get_letohl(tvb, offset+4);
1752#endif
1753#if defined(vax)
1754 return get_ieee_double(ieee_fp_union.dw);
1755#else
1756 return ieee_fp_union.d;
1757#endif
1758}
1759
1760/* This function is a slight misnomer. It accepts all encodings that are
1761 * ASCII "enough", which means encodings that are the same as US-ASCII
1762 * for textual representations of dates and hex bytes; i.e., the same
1763 * for the hex digits and Z (in practice, all alphanumerics), and the
1764 * four separators ':' '-' '.' and ' '
1765 * That means that any encoding that keeps the ISO/IEC 646 invariant
1766 * characters the same (including the T.61 8 bit encoding and multibyte
1767 * encodings like EUC-KR and GB18030) are OK, even if they replace characters
1768 * like '$' '#' and '\' with national variants, but not encodings like UTF-16
1769 * that include extra null bytes.
1770 * For our current purposes, the unpacked GSM 7-bit default alphabet (but not
1771 * all National Language Shift Tables) also satisfies this requirement, but
1772 * note that it does *not* keep all ISO/IEC 646 invariant characters the same.
1773 * If this internal function gets used for additional purposes than currently,
1774 * the set of encodings that it accepts could change.
1775 * */
1776static inline void
1777validate_single_byte_ascii_encoding(const unsigned encoding)
1778{
1779 const unsigned enc = encoding & ~ENC_CHARENCODING_MASK0x0000FFFE;
1780
1781 switch (enc) {
1782 case ENC_UTF_160x00000004:
1783 case ENC_UCS_20x00000006:
1784 case ENC_UCS_40x00000008:
1785 case ENC_3GPP_TS_23_038_7BITS_PACKED0x0000002C:
1786 case ENC_ASCII_7BITS0x00000034:
1787 case ENC_EBCDIC0x0000002E:
1788 case ENC_EBCDIC_CP0370x00000038:
1789 case ENC_EBCDIC_CP5000x00000060:
1790 case ENC_BCD_DIGITS_0_90x00000044:
1791 case ENC_KEYPAD_ABC_TBCD0x00000046:
1792 case ENC_KEYPAD_BC_TBCD0x00000048:
1793 case ENC_ETSI_TS_102_221_ANNEX_A0x0000004E:
1794 case ENC_APN_STR0x00000054:
1795 case ENC_DECT_STANDARD_4BITS_TBCD0x00000058:
1796 REPORT_DISSECTOR_BUG("Invalid string encoding type passed to tvb_get_string_XXX")proto_report_dissector_bug("Invalid string encoding type passed to tvb_get_string_XXX"
)
;
1797 break;
1798 default:
1799 break;
1800 }
1801 /* make sure something valid was set */
1802 if (enc == 0)
1803 REPORT_DISSECTOR_BUG("No string encoding type passed to tvb_get_string_XXX")proto_report_dissector_bug("No string encoding type passed to tvb_get_string_XXX"
)
;
1804}
1805
1806GByteArray*
1807tvb_get_string_bytes(tvbuff_t *tvb, const int offset, const int length,
1808 const unsigned encoding, GByteArray *bytes, int *endoff)
1809{
1810 char *ptr;
1811 const char *begin;
1812 const char *end = NULL((void*)0);
1813 GByteArray *retval = NULL((void*)0);
1814
1815 validate_single_byte_ascii_encoding(encoding);
1816
1817 ptr = (char*) tvb_get_raw_string(NULL((void*)0), tvb, offset, length);
1818 begin = ptr;
1819
1820 if (endoff) *endoff = offset;
1821
1822 while (*begin == ' ') begin++;
1823
1824 if (*begin && bytes) {
1825 if (hex_str_to_bytes_encoding(begin, bytes, &end, encoding, false0)) {
1826 if (bytes->len > 0) {
1827 if (endoff) *endoff = offset + (int)(end - ptr);
1828 retval = bytes;
1829 }
1830 }
1831 }
1832
1833 wmem_free(NULL((void*)0), ptr);
1834
1835 return retval;
1836}
1837
1838static bool_Bool
1839parse_month_name(const char *name, int *tm_mon)
1840{
1841 static const char months[][4] = { "Jan", "Feb", "Mar", "Apr", "May",
1842 "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
1843 for (int i = 0; i < 12; i++) {
1844 if (memcmp(months[i], name, 4) == 0) {
1845 *tm_mon = i;
1846 return true1;
1847 }
1848 }
1849 return false0;
1850}
1851
1852/*
1853 * Is the character a WSP character, as per RFC 5234? (space or tab).
1854 */
1855#define IS_WSP(c)((c) == ' ' || (c) == '\t') ((c) == ' ' || (c) == '\t')
1856
1857/* support hex-encoded time values? */
1858nstime_t*
1859tvb_get_string_time(tvbuff_t *tvb, const int offset, const int length,
1860 const unsigned encoding, nstime_t *ns, int *endoff)
1861{
1862 char *begin;
1863 const char *ptr;
1864 const char *end = NULL((void*)0);
1865 int num_chars = 0;
1866 int utc_offset = 0;
1867
1868 validate_single_byte_ascii_encoding(encoding);
1869
1870 DISSECTOR_ASSERT(ns)((void) ((ns) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/tvbuff.c", 1870, "ns"))))
;
1871
1872 begin = (char*) tvb_get_raw_string(NULL((void*)0), tvb, offset, length);
1873 ptr = begin;
1874
1875 while (IS_WSP(*ptr)((*ptr) == ' ' || (*ptr) == '\t'))
1876 ptr++;
1877
1878 if (*ptr) {
1879 if ((encoding & ENC_ISO_8601_DATE_TIME0x00030000) == ENC_ISO_8601_DATE_TIME0x00030000) {
1880 if (!(end = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME))) {
1881
1882
1883 goto fail;
1884 }
1885 } else if ((encoding & ENC_ISO_8601_DATE_TIME_BASIC0x00100000) == ENC_ISO_8601_DATE_TIME_BASIC0x00100000) {
1886 if (!(end = iso8601_to_nstime(ns, ptr, ISO8601_DATETIME_BASIC))) {
1887
1888
1889 goto fail;
1890 }
1891 } else {
1892 struct tm tm;
1893
1894 memset(&tm, 0, sizeof(tm));
1895 tm.tm_isdst = -1;
1896 ns->secs = 0;
1897 ns->nsecs = 0;
1898
1899 /* note: sscanf is known to be inconsistent across platforms with respect
1900 to whether a %n is counted as a return value or not, so we have to use
1901 '>=' a lot */
1902 if (encoding & ENC_ISO_8601_DATE0x00010000) {
1903 /* 2014-04-07 */
1904 if (sscanf(ptr, "%d-%d-%d%n",
1905 &tm.tm_year,
1906 &tm.tm_mon,
1907 &tm.tm_mday,
1908 &num_chars) >= 3)
1909 {
1910 end = ptr + num_chars;
1911 tm.tm_mon--;
1912 if (tm.tm_year > 1900) tm.tm_year -= 1900;
1913 } else {
1914 goto fail;
1915 }
1916 }
1917 else if (encoding & ENC_ISO_8601_TIME0x00020000) {
1918 /* 2014-04-07 */
1919 if (sscanf(ptr, "%d:%d:%d%n",
1920 &tm.tm_hour,
1921 &tm.tm_min,
1922 &tm.tm_sec,
1923 &num_chars) >= 2)
1924 {
1925 /* what should we do about day/month/year? */
1926 /* setting it to "now" for now */
1927 time_t time_now = time(NULL((void*)0));
1928 struct tm *tm_now = gmtime(&time_now);
1929 if (tm_now != NULL((void*)0)) {
1930 tm.tm_year = tm_now->tm_year;
1931 tm.tm_mon = tm_now->tm_mon;
1932 tm.tm_mday = tm_now->tm_mday;
1933 } else {
1934 /* The second before the Epoch */
1935 tm.tm_year = 69;
1936 tm.tm_mon = 12;
1937 tm.tm_mday = 31;
1938 }
1939 end = ptr + num_chars;
1940 } else {
1941 goto fail;
1942 }
1943 }
1944 else if (encoding & ENC_IMF_DATE_TIME0x00040000) {
1945 /*
1946 * Match [dow,] day month year hh:mm[:ss] with
1947 * two-digit years (RFC 822) or four-digit
1948 * years (RFCs 1123, 2822, 5822). Skip
1949 * the day of week since it is locale
1950 * dependent and does not affect the resulting
1951 * date anyway.
1952 */
1953 if (g_ascii_isalpha(ptr[0])((g_ascii_table[(guchar) (ptr[0])] & G_ASCII_ALPHA) != 0) && g_ascii_isalpha(ptr[1])((g_ascii_table[(guchar) (ptr[1])] & G_ASCII_ALPHA) != 0) && g_ascii_isalpha(ptr[2])((g_ascii_table[(guchar) (ptr[2])] & G_ASCII_ALPHA) != 0) && ptr[3] == ',')
1954 ptr += 4; /* Skip day of week. */
1955
1956 /*
1957 * Parse the day-of-month and month
1958 * name.
1959 */
1960 char month_name[4] = { 0 };
1961
1962 if (sscanf(ptr, "%d %3s%n",
1963 &tm.tm_mday,
1964 month_name,
1965 &num_chars) < 2)
1966 {
1967 /* Not matched. */
1968 goto fail;
1969 }
1970 if (!parse_month_name(month_name, &tm.tm_mon)) {
1971 goto fail;
1972 }
1973 ptr += num_chars;
1974 while (IS_WSP(*ptr)((*ptr) == ' ' || (*ptr) == '\t'))
1975 ptr++;
1976
1977 /*
1978 * Scan the year. Treat 2-digit years
1979 * differently from 4-digit years.
1980 */
1981 uint32_t year;
1982 const char *yearendp;
1983
1984 if (!ws_strtou32(ptr, &yearendp, &year)) {
1985 goto fail;
1986 }
1987 if (!IS_WSP(*yearendp)((*yearendp) == ' ' || (*yearendp) == '\t')) {
1988 /* Not followed by WSP. */
1989 goto fail;
1990 }
1991 if (yearendp - ptr < 2) {
1992 /* 1-digit year. Error. */
1993 goto fail;
1994 }
1995 if (yearendp - ptr == 2) {
1996 /*
1997 * 2-digit year.
1998 *
1999 * Match RFC 2822/RFC 5322 behavior;
2000 * add 2000 to years from 0 to
2001 * 49 and 1900 to uears from 50
2002 * to 99.
2003 */
2004 if (year <= 49) {
2005 year += 2000;
2006 } else {
2007 year += 1900;
2008 }
2009 } else if (yearendp - ptr == 3) {
2010 /*
2011 * 3-digit year.
2012 *
2013 * Match RFC 2822/RFC 5322 behavior;
2014 * add 1900 to the year.
2015 */
2016 year += 1900;
2017 }
2018 tm.tm_year = year - 1900;
2019 ptr = yearendp;
2020 while (IS_WSP(*ptr)((*ptr) == ' ' || (*ptr) == '\t'))
2021 ptr++;
2022
2023 /* Parse the time. */
2024 if (sscanf(ptr, "%d:%d%n:%d%n",
2025 &tm.tm_hour,
2026 &tm.tm_min,
2027 &num_chars,
2028 &tm.tm_sec,
2029 &num_chars) < 2)
2030 {
2031 goto fail;
2032 }
2033 ptr += num_chars;
2034 while (IS_WSP(*ptr)((*ptr) == ' ' || (*ptr) == '\t'))
2035 ptr++;
2036
2037 /*
2038 * Parse the time zone.
2039 * Check for obs-zone values first.
2040 */
2041 if (g_ascii_strncasecmp(ptr, "UT", 2) == 0)
2042 {
2043 ptr += 2;
2044 }
2045 else if (g_ascii_strncasecmp(ptr, "GMT", 3) == 0)
2046 {
2047 ptr += 3;
2048 }
2049 else
2050 {
2051 char sign;
2052 int off_hr;
2053 int off_min;
2054
2055 if (sscanf(ptr, "%c%2d%2d%n",
2056 &sign,
2057 &off_hr,
2058 &off_min,
2059 &num_chars) < 3)
2060 {
2061 goto fail;
2062 }
2063
2064 /*
2065 * If sign is '+', there's a positive
2066 * UTC offset.
2067 *
2068 * If sign is '-', there's a negative
2069 * UTC offset.
2070 *
2071 * Otherwise, that's an invalid UTC
2072 * offset string.
2073 */
2074 if (sign == '+')
2075 utc_offset += (off_hr * 3600) + (off_min * 60);
2076 else if (sign == '-')
2077 utc_offset -= (off_hr * 3600) + (off_min * 60);
2078 else {
2079 /* Sign must be + or - */
2080 goto fail;
2081 }
2082 ptr += num_chars;
2083 }
2084 end = ptr;
2085 }
2086 ns->secs = mktime_utc(&tm);
2087 if (ns->secs == (time_t)-1 && errno(*__errno_location ()) != 0) {
2088 goto fail;
2089 }
2090 ns->secs += utc_offset;
2091 }
2092 } else {
2093 /* Empty string */
2094 goto fail;
2095 }
2096
2097 if (endoff)
2098 *endoff = (int)(offset + (end - begin));
2099 wmem_free(NULL((void*)0), begin);
2100 return ns;
2101
2102fail:
2103 wmem_free(NULL((void*)0), begin);
2104 return NULL((void*)0);
2105}
2106
2107/* Fetch an IPv4 address, in network byte order.
2108 * We do *not* convert them to host byte order; we leave them in
2109 * network byte order. */
2110uint32_t
2111tvb_get_ipv4(tvbuff_t *tvb, const int offset)
2112{
2113 const uint8_t *ptr;
2114 uint32_t addr;
2115
2116 ptr = fast_ensure_contiguous(tvb, offset, sizeof(uint32_t));
2117 memcpy(&addr, ptr, sizeof addr);
2118 return addr;
2119}
2120
2121/* Fetch an IPv6 address. */
2122void
2123tvb_get_ipv6(tvbuff_t *tvb, const int offset, ws_in6_addr *addr)
2124{
2125 const uint8_t *ptr;
2126
2127 ptr = ensure_contiguous(tvb, offset, sizeof(*addr));
2128 memcpy(addr, ptr, sizeof *addr);
2129}
2130
2131/*
2132 * These routines return the length of the address in bytes on success
2133 * and -1 if the prefix length is too long.
2134 */
2135int
2136tvb_get_ipv4_addr_with_prefix_len(tvbuff_t *tvb, int offset, ws_in4_addr *addr,
2137 uint32_t prefix_len)
2138{
2139 uint8_t addr_len;
2140
2141 if (prefix_len > 32)
2142 return -1;
2143
2144 addr_len = (prefix_len + 7) / 8;
2145 *addr = 0;
2146 tvb_memcpy(tvb, addr, offset, addr_len);
2147 if (prefix_len % 8)
2148 ((uint8_t*)addr)[addr_len - 1] &= ((0xff00 >> (prefix_len % 8)) & 0xff);
2149 return addr_len;
2150}
2151
2152/*
2153 * These routines return the length of the address in bytes on success
2154 * and -1 if the prefix length is too long.
2155 */
2156int
2157tvb_get_ipv6_addr_with_prefix_len(tvbuff_t *tvb, int offset, ws_in6_addr *addr,
2158 uint32_t prefix_len)
2159{
2160 uint32_t addr_len;
2161
2162 if (prefix_len > 128)
2163 return -1;
2164
2165 addr_len = (prefix_len + 7) / 8;
2166 memset(addr->bytes, 0, 16);
2167 tvb_memcpy(tvb, addr->bytes, offset, addr_len);
2168 if (prefix_len % 8) {
2169 addr->bytes[addr_len - 1] &=
2170 ((0xff00 >> (prefix_len % 8)) & 0xff);
2171 }
2172
2173 return addr_len;
2174}
2175
2176/* Fetch a GUID. */
2177void
2178tvb_get_ntohguid(tvbuff_t *tvb, const int offset, e_guid_t *guid)
2179{
2180 const uint8_t *ptr = ensure_contiguous(tvb, offset, GUID_LEN16);
2181
2182 guid->data1 = pntohu32(ptr + 0);
2183 guid->data2 = pntohu16(ptr + 4);
2184 guid->data3 = pntohu16(ptr + 6);
2185 memcpy(guid->data4, ptr + 8, sizeof guid->data4);
2186}
2187
2188void
2189tvb_get_letohguid(tvbuff_t *tvb, const int offset, e_guid_t *guid)
2190{
2191 const uint8_t *ptr = ensure_contiguous(tvb, offset, GUID_LEN16);
2192
2193 guid->data1 = pletohu32(ptr + 0);
2194 guid->data2 = pletohu16(ptr + 4);
2195 guid->data3 = pletohu16(ptr + 6);
2196 memcpy(guid->data4, ptr + 8, sizeof guid->data4);
2197}
2198
2199void
2200tvb_get_guid(tvbuff_t *tvb, const int offset, e_guid_t *guid, const unsigned encoding)
2201{
2202 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
2203 tvb_get_letohguid(tvb, offset, guid);
2204 } else {
2205 tvb_get_ntohguid(tvb, offset, guid);
2206 }
2207}
2208
2209static const uint8_t bit_mask8[] = {
2210 0x00,
2211 0x01,
2212 0x03,
2213 0x07,
2214 0x0f,
2215 0x1f,
2216 0x3f,
2217 0x7f,
2218 0xff
2219};
2220
2221
2222/* Get a variable amount of bits
2223 *
2224 * Return a byte array with bit limited data.
2225 * When encoding is ENC_BIG_ENDIAN, the data is aligned to the left.
2226 * When encoding is ENC_LITTLE_ENDIAN, the data is aligned to the right.
2227 */
2228uint8_t *
2229tvb_get_bits_array(wmem_allocator_t *scope, tvbuff_t *tvb, const int bit_offset,
2230 size_t no_of_bits, size_t *data_length, const unsigned encoding)
2231{
2232 tvbuff_t *sub_tvb;
2233 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
2234 sub_tvb = tvb_new_octet_right_aligned(tvb, bit_offset, (int32_t) no_of_bits);
2235 } else {
2236 sub_tvb = tvb_new_octet_aligned(tvb, bit_offset, (int32_t) no_of_bits);
2237 }
2238 *data_length = tvb_reported_length(sub_tvb);
2239 return (uint8_t*)tvb_memdup(scope, sub_tvb, 0, *data_length);
2240}
2241
2242/* Get 1 - 8 bits */
2243uint8_t
2244tvb_get_bits8(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits)
2245{
2246 DISSECTOR_ASSERT_HINT(no_of_bits <= 8, "Too many bits requested for 8-bit return type")((void) ((no_of_bits <= 8) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/tvbuff.c", 2246
, "no_of_bits <= 8", "Too many bits requested for 8-bit return type"
))))
;
2247 return (uint8_t)_tvb_get_bits64(tvb, bit_offset, no_of_bits);
2248}
2249
2250/* Get 1 - 16 bits */
2251uint16_t
2252tvb_get_bits16(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2253{
2254 DISSECTOR_ASSERT_HINT(no_of_bits <= 16, "Too many bits requested for 16-bit return type")((void) ((no_of_bits <= 16) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/tvbuff.c", 2254
, "no_of_bits <= 16", "Too many bits requested for 16-bit return type"
))))
;
2255 return (uint16_t)tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
2256}
2257
2258/* Get 1 - 32 bits */
2259uint32_t
2260tvb_get_bits32(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2261{
2262 DISSECTOR_ASSERT_HINT(no_of_bits <= 32, "Too many bits requested for 32-bit return type")((void) ((no_of_bits <= 32) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/tvbuff.c", 2262
, "no_of_bits <= 32", "Too many bits requested for 32-bit return type"
))))
;
2263 return (uint32_t)tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
2264}
2265
2266/* Get 1 - 64 bits */
2267uint64_t
2268tvb_get_bits64(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2269{
2270 DISSECTOR_ASSERT_HINT(no_of_bits <= 64, "Too many bits requested for 64-bit return type")((void) ((no_of_bits <= 64) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\" (%s)", "epan/tvbuff.c", 2270
, "no_of_bits <= 64", "Too many bits requested for 64-bit return type"
))))
;
2271
2272 /* encoding determines bit numbering within octet array */
2273 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
2274 return _tvb_get_bits64_le(tvb, bit_offset, no_of_bits);
2275 } else {
2276 return _tvb_get_bits64(tvb, bit_offset, no_of_bits);
2277 }
2278}
2279
2280/*
2281 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
2282 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
2283 * Offset should be given in bits from the start of the tvb.
2284 * Bits within octet are numbered from MSB (0) to LSB (7). Bit at bit_offset is return value most significant bit.
2285 * The function tolerates requests for more than 64 bits, but will only return the least significant 64 bits.
2286 */
2287static uint64_t
2288_tvb_get_bits64(tvbuff_t *tvb, unsigned bit_offset, const int total_no_of_bits)
2289{
2290 uint64_t value;
2291 unsigned octet_offset = bit_offset >> 3;
2292 uint8_t required_bits_in_first_octet = 8 - (bit_offset % 8);
2293
2294 if(required_bits_in_first_octet > total_no_of_bits)
2295 {
2296 /* the required bits don't extend to the end of the first octet */
2297 uint8_t right_shift = required_bits_in_first_octet - total_no_of_bits;
2298 value = (tvb_get_uint8(tvb, octet_offset) >> right_shift) & bit_mask8[total_no_of_bits % 8];
2299 }
2300 else
2301 {
2302 uint8_t remaining_bit_length = total_no_of_bits;
2303
2304 /* get the bits up to the first octet boundary */
2305 value = 0;
2306 required_bits_in_first_octet %= 8;
2307 if(required_bits_in_first_octet != 0)
2308 {
2309 value = tvb_get_uint8(tvb, octet_offset) & bit_mask8[required_bits_in_first_octet];
2310 remaining_bit_length -= required_bits_in_first_octet;
2311 octet_offset ++;
2312 }
2313 /* take the biggest words, shorts or octets that we can */
2314 while (remaining_bit_length > 7)
2315 {
2316 switch (remaining_bit_length >> 4)
2317 {
2318 case 0:
2319 /* 8 - 15 bits. (note that 0 - 7 would have dropped out of the while() loop) */
2320 value <<= 8;
2321 value += tvb_get_uint8(tvb, octet_offset);
2322 remaining_bit_length -= 8;
2323 octet_offset ++;
2324 break;
2325
2326 case 1:
2327 /* 16 - 31 bits */
2328 value <<= 16;
2329 value += tvb_get_ntohs(tvb, octet_offset);
2330 remaining_bit_length -= 16;
2331 octet_offset += 2;
2332 break;
2333
2334 case 2:
2335 case 3:
2336 /* 32 - 63 bits */
2337 value <<= 32;
2338 value += tvb_get_ntohl(tvb, octet_offset);
2339 remaining_bit_length -= 32;
2340 octet_offset += 4;
2341 break;
2342
2343 default:
2344 /* 64 bits (or more???) */
2345 value = tvb_get_ntoh64(tvb, octet_offset);
2346 remaining_bit_length -= 64;
2347 octet_offset += 8;
2348 break;
2349 }
2350 }
2351 /* get bits from any partial octet at the tail */
2352 if(remaining_bit_length)
2353 {
2354 value <<= remaining_bit_length;
2355 value += (tvb_get_uint8(tvb, octet_offset) >> (8 - remaining_bit_length));
2356 }
2357 }
2358 return value;
2359}
2360
2361/*
2362 * Offset should be given in bits from the start of the tvb.
2363 * Bits within octet are numbered from LSB (0) to MSB (7). Bit at bit_offset is return value least significant bit.
2364 * The function tolerates requests for more than 64 bits, but will only return the least significant 64 bits.
2365 */
2366static uint64_t
2367_tvb_get_bits64_le(tvbuff_t *tvb, unsigned bit_offset, const int total_no_of_bits)
2368{
2369 uint64_t value = 0;
2370 unsigned octet_offset = bit_offset / 8;
2371 int remaining_bits = total_no_of_bits;
2372 int shift = 0;
2373
2374 if (remaining_bits > 64)
2375 {
2376 remaining_bits = 64;
2377 }
2378
2379 if (bit_offset % 8)
2380 {
2381 /* not aligned, extract bits from first octet */
2382 shift = 8 - (bit_offset % 8);
2383 value = tvb_get_uint8(tvb, octet_offset) >> (bit_offset % 8);
2384 if (shift > remaining_bits)
2385 {
2386 /* keep only the requested bits */
2387 value &= (UINT64_C(1)1UL << remaining_bits) - 1;
2388 remaining_bits = 0;
2389 }
2390 else
2391 {
2392 remaining_bits -= shift;
2393 }
2394 octet_offset++;
2395 }
2396
2397 while (remaining_bits > 0)
2398 {
2399 /* take the biggest words, shorts or octets that we can */
2400 if (remaining_bits >= 32)
2401 {
2402 value |= ((uint64_t)tvb_get_letohl(tvb, octet_offset) << shift);
2403 shift += 32;
2404 remaining_bits -= 32;
2405 octet_offset += 4;
2406 }
2407 else if (remaining_bits >= 16)
2408 {
2409 value |= ((uint64_t)tvb_get_letohs(tvb, octet_offset) << shift);
2410 shift += 16;
2411 remaining_bits -= 16;
2412 octet_offset += 2;
2413 }
2414 else if (remaining_bits >= 8)
2415 {
2416 value |= ((uint64_t)tvb_get_uint8(tvb, octet_offset) << shift);
2417 shift += 8;
2418 remaining_bits -= 8;
2419 octet_offset += 1;
2420 }
2421 else
2422 {
2423 unsigned mask = (1 << remaining_bits) - 1;
2424 value |= (((uint64_t)tvb_get_uint8(tvb, octet_offset) & mask) << shift);
2425 shift += remaining_bits;
2426 remaining_bits = 0;
2427 octet_offset += 1;
2428 }
2429 }
2430 return value;
2431}
2432
2433/* Get 1 - 32 bits (should be deprecated as same as tvb_get_bits32??) */
2434uint32_t
2435tvb_get_bits(tvbuff_t *tvb, const unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2436{
2437 return (uint32_t)tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
2438}
2439
2440static int
2441tvb_find_uint8_generic(tvbuff_t *tvb, unsigned abs_offset, unsigned limit, uint8_t needle)
2442{
2443 const uint8_t *ptr;
2444 const uint8_t *result;
2445
2446 ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr() */
2447 if (!ptr)
2448 return -1;
2449
2450 result = (const uint8_t *) memchr(ptr, needle, limit);
2451 if (!result)
2452 return -1;
2453
2454 return (int) ((result - ptr) + abs_offset);
2455}
2456
2457/* Find first occurrence of needle in tvbuff, starting at offset. Searches
2458 * at most maxlength number of bytes; if maxlength is -1, searches to
2459 * end of tvbuff.
2460 * Returns the offset of the found needle, or -1 if not found.
2461 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
2462 * in that case, -1 will be returned if the boundary is reached before
2463 * finding needle. */
2464int
2465tvb_find_uint8(tvbuff_t *tvb, const int offset, const int maxlength, const uint8_t needle)
2466{
2467 const uint8_t *result;
2468 unsigned abs_offset = 0;
2469 unsigned limit = 0;
2470 int exception;
2471
2472 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2472, "tvb && tvb->initialized"
))))
;
2473
2474 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
2475 if (exception)
2476 THROW(exception)except_throw(1, (exception), ((void*)0));
2477
2478 /* Only search to end of tvbuff, w/o throwing exception. */
2479 if (maxlength >= 0 && limit > (unsigned) maxlength) {
2480 /* Maximum length doesn't go past end of tvbuff; search
2481 to that value. */
2482 limit = (unsigned) maxlength;
2483 }
2484
2485 /* If we have real data, perform our search now. */
2486 if (tvb->real_data) {
2487 result = (const uint8_t *)memchr(tvb->real_data + abs_offset, needle, limit);
2488 if (result == NULL((void*)0)) {
2489 return -1;
2490 }
2491 else {
2492 return (int) (result - tvb->real_data);
2493 }
2494 }
2495
2496 if (tvb->ops->tvb_find_uint8)
2497 return tvb->ops->tvb_find_uint8(tvb, abs_offset, limit, needle);
2498
2499 return tvb_find_uint8_generic(tvb, offset, limit, needle);
2500}
2501
2502/* Same as tvb_find_uint8() with 16bit needle. */
2503int
2504tvb_find_uint16(tvbuff_t *tvb, const int offset, const int maxlength,
2505 const uint16_t needle)
2506{
2507 unsigned abs_offset = 0;
2508 unsigned limit = 0;
2509 int exception;
2510
2511 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
2512 if (exception)
2513 THROW(exception)except_throw(1, (exception), ((void*)0));
2514
2515 /* Only search to end of tvbuff, w/o throwing exception. */
2516 if (maxlength >= 0 && limit > (unsigned) maxlength) {
2517 /* Maximum length doesn't go past end of tvbuff; search
2518 to that value. */
2519 limit = (unsigned) maxlength;
2520 }
2521
2522 const uint8_t needle1 = ((needle & 0xFF00) >> 8);
2523 const uint8_t needle2 = ((needle & 0x00FF) >> 0);
2524 unsigned searched_bytes = 0;
2525 unsigned pos = abs_offset;
2526
2527 do {
2528 int offset1 =
2529 tvb_find_uint8(tvb, pos, limit - searched_bytes, needle1);
2530 int offset2 = -1;
2531
2532 if (offset1 == -1) {
2533 return -1;
2534 }
2535
2536 searched_bytes = (unsigned)offset1 - abs_offset + 1;
2537
2538 if (searched_bytes >= limit) {
2539 return -1;
2540 }
2541
2542 offset2 = tvb_find_uint8(tvb, offset1 + 1, 1, needle2);
2543
2544 searched_bytes += 1;
2545
2546 if (offset2 != -1) {
2547 if (searched_bytes > limit) {
2548 return -1;
2549 }
2550 return offset1;
2551 }
2552
2553 pos = offset1 + 1;
2554 } while (searched_bytes < limit);
2555
2556 return -1;
2557}
2558
2559static inline int
2560tvb_ws_mempbrk_uint8_generic(tvbuff_t *tvb, unsigned abs_offset, unsigned limit, const ws_mempbrk_pattern* pattern, unsigned char *found_needle)
2561{
2562 const uint8_t *ptr;
2563 const uint8_t *result;
2564
2565 ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr */
2566 if (!ptr)
2567 return -1;
2568
2569 result = ws_mempbrk_exec(ptr, limit, pattern, found_needle);
2570 if (!result)
2571 return -1;
2572
2573 return (int) ((result - ptr) + abs_offset);
2574}
2575
2576
2577/* Find first occurrence of any of the pattern chars in tvbuff, starting at offset.
2578 * Searches at most maxlength number of bytes; if maxlength is -1, searches
2579 * to end of tvbuff.
2580 * Returns the offset of the found needle, or -1 if not found.
2581 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
2582 * in that case, -1 will be returned if the boundary is reached before
2583 * finding needle. */
2584int
2585tvb_ws_mempbrk_pattern_uint8(tvbuff_t *tvb, const int offset, const int maxlength,
2586 const ws_mempbrk_pattern* pattern, unsigned char *found_needle)
2587{
2588 const uint8_t *result;
2589 unsigned abs_offset = 0;
2590 unsigned limit = 0;
2591 int exception;
2592
2593 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2593, "tvb && tvb->initialized"
))))
;
2594
2595 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
2596 if (exception)
2597 THROW(exception)except_throw(1, (exception), ((void*)0));
2598
2599 /* Only search to end of tvbuff, w/o throwing exception. */
2600 if (limit > (unsigned) maxlength) {
2601 /* Maximum length doesn't go past end of tvbuff; search
2602 to that value. */
2603 limit = maxlength;
2604 }
2605
2606 /* If we have real data, perform our search now. */
2607 if (tvb->real_data) {
2608 result = ws_mempbrk_exec(tvb->real_data + abs_offset, limit, pattern, found_needle);
2609 if (result == NULL((void*)0)) {
2610 return -1;
2611 }
2612 else {
2613 return (int) (result - tvb->real_data);
2614 }
2615 }
2616
2617 if (tvb->ops->tvb_ws_mempbrk_pattern_uint8)
2618 return tvb->ops->tvb_ws_mempbrk_pattern_uint8(tvb, abs_offset, limit, pattern, found_needle);
2619
2620 return tvb_ws_mempbrk_uint8_generic(tvb, abs_offset, limit, pattern, found_needle);
2621}
2622
2623/* Find size of stringz (NUL-terminated string) by looking for terminating
2624 * NUL. The size of the string includes the terminating NUL.
2625 *
2626 * If the NUL isn't found, it throws the appropriate exception.
2627 */
2628unsigned
2629tvb_strsize(tvbuff_t *tvb, const int offset)
2630{
2631 unsigned abs_offset = 0, junk_length;
2632 int nul_offset;
2633
2634 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2634, "tvb && tvb->initialized"
))))
;
2635
2636 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
2637 nul_offset = tvb_find_uint8(tvb, abs_offset, -1, 0);
2638 if (nul_offset == -1) {
2639 /*
2640 * OK, we hit the end of the tvbuff, so we should throw
2641 * an exception.
2642 */
2643 if (tvb->length < tvb->contained_length) {
2644 THROW(BoundsError)except_throw(1, (1), ((void*)0));
2645 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
2646 THROW(FragmentBoundsError)except_throw(1, (4), ((void*)0));
2647 } else if (tvb->length < tvb->reported_length) {
2648 THROW(ContainedBoundsError)except_throw(1, (2), ((void*)0));
2649 } else {
2650 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
2651 }
2652 }
2653 return (nul_offset - abs_offset) + 1;
2654}
2655
2656/* UTF-16/UCS-2 version of tvb_strsize */
2657/* Returns number of bytes including the (two-bytes) null terminator */
2658unsigned
2659tvb_unicode_strsize(tvbuff_t *tvb, const int offset)
2660{
2661 unsigned i = 0;
2662 gunichar2 uchar;
2663
2664 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2664, "tvb && tvb->initialized"
))))
;
2665
2666 do {
2667 /* Endianness doesn't matter when looking for null */
2668 uchar = tvb_get_ntohs(tvb, offset + i);
2669 i += 2;
2670 } while(uchar != 0);
2671
2672 return i;
2673}
2674
2675/* Find length of string by looking for end of string ('\0'), up to
2676 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
2677 * of tvbuff.
2678 * Returns -1 if 'maxlength' reached before finding EOS. */
2679int
2680tvb_strnlen(tvbuff_t *tvb, const int offset, const unsigned maxlength)
2681{
2682 int result_offset;
2683 unsigned abs_offset = 0, junk_length;
2684
2685 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2685, "tvb && tvb->initialized"
))))
;
2686
2687 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
2688
2689 result_offset = tvb_find_uint8(tvb, abs_offset, maxlength, 0);
2690
2691 if (result_offset == -1) {
2692 return -1;
2693 }
2694 else {
2695 return result_offset - abs_offset;
2696 }
2697}
2698
2699/*
2700 * Implement strneql etc
2701 */
2702
2703/*
2704 * Call strncmp after checking if enough chars left, returning 0 if
2705 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2706 */
2707int
2708tvb_strneql(tvbuff_t *tvb, const int offset, const char *str, const size_t size)
2709{
2710 const uint8_t *ptr;
2711
2712 ptr = ensure_contiguous_no_exception(tvb, offset, (int)size, NULL((void*)0));
2713
2714 if (ptr) {
2715 int cmp = strncmp((const char *)ptr, str, size);
2716
2717 /*
2718 * Return 0 if equal, -1 otherwise.
2719 */
2720 return (cmp == 0 ? 0 : -1);
2721 } else {
2722 /*
2723 * Not enough characters in the tvbuff to match the
2724 * string.
2725 */
2726 return -1;
2727 }
2728}
2729
2730/*
2731 * Call g_ascii_strncasecmp after checking if enough chars left, returning
2732 * 0 if it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2733 */
2734int
2735tvb_strncaseeql(tvbuff_t *tvb, const int offset, const char *str, const size_t size)
2736{
2737 const uint8_t *ptr;
2738
2739 ptr = ensure_contiguous_no_exception(tvb, offset, (int)size, NULL((void*)0));
2740
2741 if (ptr) {
2742 int cmp = g_ascii_strncasecmp((const char *)ptr, str, size);
2743
2744 /*
2745 * Return 0 if equal, -1 otherwise.
2746 */
2747 return (cmp == 0 ? 0 : -1);
2748 } else {
2749 /*
2750 * Not enough characters in the tvbuff to match the
2751 * string.
2752 */
2753 return -1;
2754 }
2755}
2756
2757/*
2758 * Check that the tvbuff contains at least size bytes, starting at
2759 * offset, and that those bytes are equal to str. Return 0 for success
2760 * and -1 for error. This function does not throw an exception.
2761 */
2762int
2763tvb_memeql(tvbuff_t *tvb, const int offset, const uint8_t *str, size_t size)
2764{
2765 const uint8_t *ptr;
2766
2767 ptr = ensure_contiguous_no_exception(tvb, offset, (int) size, NULL((void*)0));
2768
2769 if (ptr) {
2770 int cmp = memcmp(ptr, str, size);
2771
2772 /*
2773 * Return 0 if equal, -1 otherwise.
2774 */
2775 return (cmp == 0 ? 0 : -1);
2776 } else {
2777 /*
2778 * Not enough characters in the tvbuff to match the
2779 * string.
2780 */
2781 return -1;
2782 }
2783}
2784
2785/**
2786 * Format the data in the tvb from offset for size.
2787 */
2788char *
2789tvb_format_text(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int size)
2790{
2791 const uint8_t *ptr;
2792 int len;
2793
2794 len = (size > 0) ? size : 0;
2795
2796 ptr = ensure_contiguous(tvb, offset, size);
2797 return format_text(scope, (const char*)ptr, len);
2798}
2799
2800/*
2801 * Format the data in the tvb from offset for length ...
2802 */
2803char *
2804tvb_format_text_wsp(wmem_allocator_t* allocator, tvbuff_t *tvb, const int offset, const int size)
2805{
2806 const uint8_t *ptr;
2807 int len;
2808
2809 len = (size > 0) ? size : 0;
2810
2811 ptr = ensure_contiguous(tvb, offset, size);
2812 return format_text_wsp(allocator, (const char*)ptr, len);
2813}
2814
2815/**
2816 * Like "tvb_format_text()", but for null-padded strings; don't show
2817 * the null padding characters as "\000".
2818 */
2819char *
2820tvb_format_stringzpad(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int size)
2821{
2822 const uint8_t *ptr, *p;
2823 int len;
2824 int stringlen;
2825
2826 len = (size > 0) ? size : 0;
2827
2828 ptr = ensure_contiguous(tvb, offset, size);
2829 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2830 ;
2831 return format_text(scope, (const char*)ptr, stringlen);
2832}
2833
2834/*
2835 * Like "tvb_format_text_wsp()", but for null-padded strings; don't show
2836 * the null padding characters as "\000".
2837 */
2838char *
2839tvb_format_stringzpad_wsp(wmem_allocator_t* allocator, tvbuff_t *tvb, const int offset, const int size)
2840{
2841 const uint8_t *ptr, *p;
2842 int len;
2843 int stringlen;
2844
2845 len = (size > 0) ? size : 0;
2846
2847 ptr = ensure_contiguous(tvb, offset, size);
2848 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2849 ;
2850 return format_text_wsp(allocator, (const char*)ptr, stringlen);
2851}
2852
2853/*
2854 * All string functions below take a scope as an argument.
2855 *
2856 *
2857 * If scope is NULL, memory is allocated with g_malloc() and user must
2858 * explicitly free it with g_free().
2859 * If scope is not NULL, memory is allocated with the corresponding pool
2860 * lifetime.
2861 *
2862 * All functions throw an exception if the tvbuff ends before the string
2863 * does.
2864 */
2865
2866/*
2867 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2868 * of bytes referred to by the tvbuff, offset, and length as an ASCII string,
2869 * with all bytes with the high-order bit set being invalid, and return a
2870 * pointer to a UTF-8 string, allocated using the wmem scope.
2871 *
2872 * Octets with the highest bit set will be converted to the Unicode
2873 * REPLACEMENT CHARACTER.
2874 */
2875static uint8_t *
2876tvb_get_ascii_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
2877{
2878 const uint8_t *ptr;
2879
2880 ptr = ensure_contiguous(tvb, offset, length);
2881 return get_ascii_string(scope, ptr, length);
2882}
2883
2884/*
2885 * Given a wmem scope, a tvbuff, an offset, a length, and a translation table,
2886 * treat the string of bytes referred to by the tvbuff, offset, and length
2887 * as a string encoded using one octet per character, with octets with the
2888 * high-order bit clear being mapped by the translation table to 2-byte
2889 * Unicode Basic Multilingual Plane characters (including REPLACEMENT
2890 * CHARACTER) and octets with the high-order bit set being mapped to
2891 * REPLACEMENT CHARACTER, and return a pointer to a UTF-8 string,
2892 * allocated using the wmem scope.
2893 *
2894 * Octets with the highest bit set will be converted to the Unicode
2895 * REPLACEMENT CHARACTER.
2896 */
2897static uint8_t *
2898tvb_get_iso_646_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length, const gunichar2 table[0x80])
2899{
2900 const uint8_t *ptr;
2901
2902 ptr = ensure_contiguous(tvb, offset, length);
2903 return get_iso_646_string(scope, ptr, length, table);
2904}
2905
2906/*
2907 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2908 * of bytes referred to by the tvbuff, the offset. and the length as a UTF-8
2909 * string, and return a pointer to a UTF-8 string, allocated using the wmem
2910 * scope, with all ill-formed sequences replaced with the Unicode REPLACEMENT
2911 * CHARACTER according to the recommended "best practices" given in the Unicode
2912 * Standard and specified by W3C/WHATWG.
2913 *
2914 * Note that in conformance with the Unicode Standard, this treats three
2915 * byte sequences corresponding to UTF-16 surrogate halves (paired or unpaired)
2916 * and two byte overlong encodings of 7-bit ASCII characters as invalid and
2917 * substitutes REPLACEMENT CHARACTER for them. Explicit support for nonstandard
2918 * derivative encoding formats (e.g. CESU-8, Java Modified UTF-8, WTF-8) could
2919 * be added later.
2920 */
2921static uint8_t *
2922tvb_get_utf_8_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int length)
2923{
2924 const uint8_t *ptr;
2925
2926 ptr = ensure_contiguous(tvb, offset, length);
2927 return get_utf_8_string(scope, ptr, length);
2928}
2929
2930/*
2931 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2932 * of bytes referred to by the tvbuff, the offset, and the length as a
2933 * raw string, and return a pointer to that string, allocated using the
2934 * wmem scope. This means a null is appended at the end, but no replacement
2935 * checking is done otherwise, unlike tvb_get_utf_8_string().
2936 *
2937 * Also, this one allows a length of -1 to mean get all, but does not
2938 * allow a negative offset.
2939 */
2940static inline uint8_t *
2941tvb_get_raw_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int length)
2942{
2943 uint8_t *strbuf;
2944 int abs_length = length;
2945
2946 DISSECTOR_ASSERT(offset >= 0)((void) ((offset >= 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2946, "offset >= 0"
))))
;
2947 DISSECTOR_ASSERT(abs_length >= -1)((void) ((abs_length >= -1) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2947, "abs_length >= -1"
))))
;
2948
2949 if (abs_length < 0)
2950 abs_length = tvb->length - offset;
2951
2952 tvb_ensure_bytes_exist(tvb, offset, abs_length);
2953 strbuf = (uint8_t *)wmem_alloc(scope, abs_length + 1);
2954 tvb_memcpy(tvb, strbuf, offset, abs_length);
2955 strbuf[abs_length] = '\0';
2956 return strbuf;
2957}
2958
2959/*
2960 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2961 * of bytes referred to by the tvbuff, the offset, and the length as an
2962 * ISO 8859/1 string, and return a pointer to a UTF-8 string, allocated
2963 * using the wmem scope.
2964 */
2965static uint8_t *
2966tvb_get_string_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
2967{
2968 const uint8_t *ptr;
2969
2970 ptr = ensure_contiguous(tvb, offset, length);
2971 return get_8859_1_string(scope, ptr, length);
2972}
2973
2974/*
2975 * Given a wmem scope, a tvbuff, an offset, a length, and a translation
2976 * table, treat the string of bytes referred to by the tvbuff, the offset,
2977 * and the length as a string encoded using one octet per character, with
2978 * octets with the high-order bit clear being ASCII and octets with the
2979 * high-order bit set being mapped by the translation table to 2-byte
2980 * Unicode Basic Multilingual Plane characters (including REPLACEMENT
2981 * CHARACTER), and return a pointer to a UTF-8 string, allocated with the
2982 * wmem scope.
2983 */
2984static uint8_t *
2985tvb_get_string_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length, const gunichar2 table[0x80])
2986{
2987 const uint8_t *ptr;
2988
2989 ptr = ensure_contiguous(tvb, offset, length);
2990 return get_unichar2_string(scope, ptr, length, table);
2991}
2992
2993/*
2994 * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
2995 * giving the byte order, treat the string of bytes referred to by the
2996 * tvbuff, the offset, and the length as a UCS-2 encoded string in
2997 * the byte order in question, containing characters from the Basic
2998 * Multilingual Plane (plane 0) of Unicode, and return a pointer to a
2999 * UTF-8 string, allocated with the wmem scope.
3000 *
3001 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
3002 *
3003 * Specify length in bytes.
3004 *
3005 * XXX - should map lead and trail surrogate values to REPLACEMENT
3006 * CHARACTERs (0xFFFD)?
3007 * XXX - if there are an odd number of bytes, should put a
3008 * REPLACEMENT CHARACTER at the end.
3009 */
3010static uint8_t *
3011tvb_get_ucs_2_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length, const unsigned encoding)
3012{
3013 const uint8_t *ptr;
3014
3015 ptr = ensure_contiguous(tvb, offset, length);
3016 return get_ucs_2_string(scope, ptr, length, encoding);
3017}
3018
3019/*
3020 * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
3021 * giving the byte order, treat the string of bytes referred to by the
3022 * tvbuff, the offset, and the length as a UTF-16 encoded string in
3023 * the byte order in question, and return a pointer to a UTF-8 string,
3024 * allocated with the wmem scope.
3025 *
3026 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
3027 *
3028 * Specify length in bytes.
3029 *
3030 * XXX - should map surrogate errors to REPLACEMENT CHARACTERs (0xFFFD).
3031 * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
3032 * XXX - if there are an odd number of bytes, should put a
3033 * REPLACEMENT CHARACTER at the end.
3034 */
3035static uint8_t *
3036tvb_get_utf_16_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length, const unsigned encoding)
3037{
3038 const uint8_t *ptr;
3039
3040 ptr = ensure_contiguous(tvb, offset, length);
3041 return get_utf_16_string(scope, ptr, length, encoding);
3042}
3043
3044/*
3045 * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
3046 * giving the byte order, treat the string of bytes referred to by the
3047 * tvbuff, the offset, and the length as a UCS-4 encoded string in
3048 * the byte order in question, and return a pointer to a UTF-8 string,
3049 * allocated with the wmem scope.
3050 *
3051 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
3052 *
3053 * Specify length in bytes
3054 *
3055 * XXX - should map lead and trail surrogate values to a "substitute"
3056 * UTF-8 character?
3057 * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
3058 * XXX - if the number of bytes isn't a multiple of 4, should put a
3059 * REPLACEMENT CHARACTER at the end.
3060 */
3061static char *
3062tvb_get_ucs_4_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length, const unsigned encoding)
3063{
3064 const uint8_t *ptr;
3065
3066 ptr = ensure_contiguous(tvb, offset, length);
3067 return (char*)get_ucs_4_string(scope, ptr, length, encoding);
3068}
3069
3070char *
3071tvb_get_ts_23_038_7bits_string_packed(wmem_allocator_t *scope, tvbuff_t *tvb,
3072 const int bit_offset, int no_of_chars)
3073{
3074 int in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
3075 int length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
3076 const uint8_t *ptr;
3077
3078 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3078, "tvb && tvb->initialized"
))))
;
3079
3080 ptr = ensure_contiguous(tvb, in_offset, length);
3081 return (char*)get_ts_23_038_7bits_string_packed(scope, ptr, bit_offset, no_of_chars);
3082}
3083
3084char *
3085tvb_get_ts_23_038_7bits_string_unpacked(wmem_allocator_t *scope, tvbuff_t *tvb,
3086 const int offset, int length)
3087{
3088 const uint8_t *ptr;
3089
3090 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3090, "tvb && tvb->initialized"
))))
;
3091
3092 ptr = ensure_contiguous(tvb, offset, length);
3093 return (char*)get_ts_23_038_7bits_string_unpacked(scope, ptr, length);
3094}
3095
3096char *
3097tvb_get_etsi_ts_102_221_annex_a_string(wmem_allocator_t *scope, tvbuff_t *tvb,
3098 const int offset, int length)
3099{
3100 const uint8_t *ptr;
3101
3102 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3102, "tvb && tvb->initialized"
))))
;
3103
3104 ptr = ensure_contiguous(tvb, offset, length);
3105 return (char*)get_etsi_ts_102_221_annex_a_string(scope, ptr, length);
3106}
3107
3108char *
3109tvb_get_ascii_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb,
3110 const int bit_offset, int no_of_chars)
3111{
3112 int in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
3113 int length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
3114 const uint8_t *ptr;
3115
3116 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3116, "tvb && tvb->initialized"
))))
;
3117
3118 ptr = ensure_contiguous(tvb, in_offset, length);
3119 return (char*)get_ascii_7bits_string(scope, ptr, bit_offset, no_of_chars);
3120}
3121
3122/*
3123 * Given a wmem scope, a tvbuff, an offset, a length, and a translation
3124 * table, treat the string of bytes referred to by the tvbuff, the offset,
3125 * and the length as a string encoded using one octet per character, with
3126 * octets being mapped by the translation table to 2-byte Unicode Basic
3127 * Multilingual Plane characters (including REPLACEMENT CHARACTER), and
3128 * return a pointer to a UTF-8 string, allocated with the wmem scope.
3129 */
3130static uint8_t *
3131tvb_get_nonascii_unichar2_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length, const gunichar2 table[256])
3132{
3133 const uint8_t *ptr;
3134
3135 ptr = ensure_contiguous(tvb, offset, length);
3136 return get_nonascii_unichar2_string(scope, ptr, length, table);
3137}
3138
3139/*
3140 * Given a wmem scope, a tvbuff, an offset, and a length, treat the bytes
3141 * referred to by the tvbuff, offset, and length as a GB18030 encoded string,
3142 * and return a pointer to a UTF-8 string, allocated with the wmem scope,
3143 * converted having substituted REPLACEMENT CHARACTER according to the
3144 * Unicode Standard 5.22 U+FFFD Substitution for Conversion.
3145 * ( https://www.unicode.org/versions/Unicode13.0.0/ch05.pdf )
3146 *
3147 * As expected, this will also decode GBK and GB2312 strings.
3148 */
3149static uint8_t *
3150tvb_get_gb18030_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3151{
3152 const uint8_t *ptr;
3153
3154 ptr = ensure_contiguous(tvb, offset, length);
3155 return get_gb18030_string(scope, ptr, length);
3156}
3157
3158/*
3159 * Given a wmem scope, a tvbuff, an offset, and a length, treat the bytes
3160 * referred to by the tvbuff, offset, and length as a EUC-KR encoded string,
3161 * and return a pointer to a UTF-8 string, allocated with the wmem scope,
3162 * converted having substituted REPLACEMENT CHARACTER according to the
3163 * Unicode Standard 5.22 U+FFFD Substitution for Conversion.
3164 * ( https://www.unicode.org/versions/Unicode13.0.0/ch05.pdf )
3165 */
3166static uint8_t *
3167tvb_get_euc_kr_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3168{
3169 const uint8_t *ptr;
3170
3171 ptr = ensure_contiguous(tvb, offset, length);
3172 return get_euc_kr_string(scope, ptr, length);
3173}
3174
3175static uint8_t *
3176tvb_get_t61_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3177{
3178 const uint8_t *ptr;
3179
3180 ptr = ensure_contiguous(tvb, offset, length);
3181 return get_t61_string(scope, ptr, length);
3182}
3183
3184/*
3185 * Encoding tables for BCD strings.
3186 */
3187static const dgt_set_t Dgt0_9_bcd = {
3188 {
3189 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3190 '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?','?'
3191 }
3192};
3193
3194static const dgt_set_t Dgt_keypad_abc_tbcd = {
3195 {
3196 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3197 '0','1','2','3','4','5','6','7','8','9','*','#','a','b','c','?'
3198 }
3199};
3200
3201static const dgt_set_t Dgt_ansi_tbcd = {
3202 {
3203 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3204 '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#','?'
3205 }
3206};
3207
3208static const dgt_set_t Dgt_dect_standard_4bits_tbcd = {
3209 {
3210 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3211 '0','1','2','3','4','5','6','7','8','9','?',' ','?','?','?','?'
3212 }
3213};
3214
3215static uint8_t *
3216tvb_get_apn_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset,
3217 int length)
3218{
3219 wmem_strbuf_t *str;
3220
3221 /*
3222 * This is a domain name.
3223 *
3224 * 3GPP TS 23.003, section 19.4.2 "Fully Qualified Domain Names
3225 * (FQDNs)", subsection 19.4.2.1 "General", says:
3226 *
3227 * The encoding of any identifier used as part of a Fully
3228 * Qualified Domain Name (FQDN) shall follow the Name Syntax
3229 * defined in IETF RFC 2181 [18], IETF RFC 1035 [19] and
3230 * IETF RFC 1123 [20]. An FQDN consists of one or more
3231 * labels. Each label is coded as a one octet length field
3232 * followed by that number of octets coded as 8 bit ASCII
3233 * characters.
3234 *
3235 * so this does not appear to use full-blown DNS compression -
3236 * the upper 2 bits of the length don't indicate that it's a
3237 * pointer or an extended label (RFC 2673).
3238 */
3239 str = wmem_strbuf_new_sized(scope, length + 1);
3240 if (length > 0) {
3241 const uint8_t *ptr;
3242
3243 ptr = ensure_contiguous(tvb, offset, length);
3244
3245 for (;;) {
3246 unsigned label_len;
3247
3248 /*
3249 * Process this label.
3250 */
3251 label_len = *ptr;
3252 ptr++;
3253 length--;
3254
3255 while (label_len != 0) {
3256 uint8_t ch;
3257
3258 if (length == 0)
3259 goto end;
3260
3261 ch = *ptr;
3262 if (ch < 0x80)
3263 wmem_strbuf_append_c(str, ch);
3264 else
3265 wmem_strbuf_append_unichar_repl(str)wmem_strbuf_append_unichar(str, 0x00FFFD);
3266 ptr++;
3267 label_len--;
3268 length--;
3269 }
3270
3271 if (length == 0)
3272 goto end;
3273
3274 wmem_strbuf_append_c(str, '.');
3275 }
3276 }
3277
3278end:
3279 return (uint8_t *) wmem_strbuf_finalize(str);
3280}
3281
3282static uint8_t *
3283tvb_get_dect_standard_8bits_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3284{
3285 const uint8_t *ptr;
3286
3287 ptr = ensure_contiguous(tvb, offset, length);
3288 return get_dect_standard_8bits_string(scope, ptr, length);
3289}
3290
3291/*
3292 * Given a tvbuff, an offset, a length, and an encoding, allocate a
3293 * buffer big enough to hold a non-null-terminated string of that length
3294 * at that offset, plus a trailing '\0', copy into the buffer the
3295 * string as converted from the appropriate encoding to UTF-8, and
3296 * return a pointer to the string.
3297 */
3298uint8_t *
3299tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset,
3300 const int length, const unsigned encoding)
3301{
3302 uint8_t *strptr;
3303 bool_Bool odd, skip_first;
3304
3305 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3305, "tvb && tvb->initialized"
))))
;
3306
3307 /* make sure length = -1 fails */
3308 if (length < 0) {
3309 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
3310 }
3311
3312 switch (encoding & ENC_CHARENCODING_MASK0x0000FFFE) {
3313
3314 case ENC_ASCII0x00000000:
3315 default:
3316 /*
3317 * For now, we treat bogus values as meaning
3318 * "ASCII" rather than reporting an error,
3319 * for the benefit of old dissectors written
3320 * when the last argument to proto_tree_add_item()
3321 * was a bool for the byte order, not an
3322 * encoding value, and passed non-zero values
3323 * other than true to mean "little-endian".
3324 */
3325 strptr = tvb_get_ascii_string(scope, tvb, offset, length);
3326 break;
3327
3328 case ENC_UTF_80x00000002:
3329 strptr = tvb_get_utf_8_string(scope, tvb, offset, length);
3330 break;
3331
3332 case ENC_UTF_160x00000004:
3333 strptr = tvb_get_utf_16_string(scope, tvb, offset, length,
3334 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3335 break;
3336
3337 case ENC_UCS_20x00000006:
3338 strptr = tvb_get_ucs_2_string(scope, tvb, offset, length,
3339 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3340 break;
3341
3342 case ENC_UCS_40x00000008:
3343 strptr = (uint8_t*)tvb_get_ucs_4_string(scope, tvb, offset, length,
3344 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3345 break;
3346
3347 case ENC_ISO_8859_10x0000000A:
3348 /*
3349 * ISO 8859-1 printable code point values are equal
3350 * to the equivalent Unicode code point value, so
3351 * no translation table is needed.
3352 */
3353 strptr = tvb_get_string_8859_1(scope, tvb, offset, length);
3354 break;
3355
3356 case ENC_ISO_8859_20x0000000C:
3357 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_2);
3358 break;
3359
3360 case ENC_ISO_8859_30x0000000E:
3361 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_3);
3362 break;
3363
3364 case ENC_ISO_8859_40x00000010:
3365 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_4);
3366 break;
3367
3368 case ENC_ISO_8859_50x00000012:
3369 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_5);
3370 break;
3371
3372 case ENC_ISO_8859_60x00000014:
3373 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_6);
3374 break;
3375
3376 case ENC_ISO_8859_70x00000016:
3377 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_7);
3378 break;
3379
3380 case ENC_ISO_8859_80x00000018:
3381 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_8);
3382 break;
3383
3384 case ENC_ISO_8859_90x0000001A:
3385 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_9);
3386 break;
3387
3388 case ENC_ISO_8859_100x0000001C:
3389 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_10);
3390 break;
3391
3392 case ENC_ISO_8859_110x0000001E:
3393 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_11);
3394 break;
3395
3396 case ENC_ISO_8859_130x00000022:
3397 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_13);
3398 break;
3399
3400 case ENC_ISO_8859_140x00000024:
3401 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_14);
3402 break;
3403
3404 case ENC_ISO_8859_150x00000026:
3405 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_15);
3406 break;
3407
3408 case ENC_ISO_8859_160x00000028:
3409 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_16);
3410 break;
3411
3412 case ENC_WINDOWS_12500x0000002A:
3413 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1250);
3414 break;
3415
3416 case ENC_WINDOWS_12510x0000003C:
3417 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1251);
3418 break;
3419
3420 case ENC_WINDOWS_12520x0000003A:
3421 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1252);
3422 break;
3423
3424 case ENC_MAC_ROMAN0x00000030:
3425 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_mac_roman);
3426 break;
3427
3428 case ENC_CP4370x00000032:
3429 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp437);
3430 break;
3431
3432 case ENC_CP8550x0000003E:
3433 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp855);
3434 break;
3435
3436 case ENC_CP8660x00000040:
3437 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp866);
3438 break;
3439
3440 case ENC_ISO_646_BASIC0x00000042:
3441 strptr = tvb_get_iso_646_string(scope, tvb, offset, length, charset_table_iso_646_basic);
3442 break;
3443
3444 case ENC_3GPP_TS_23_038_7BITS_PACKED0x0000002C:
3445 {
3446 int bit_offset = offset << 3;
3447 int no_of_chars = (length << 3) / 7;
3448 strptr = (uint8_t*)tvb_get_ts_23_038_7bits_string_packed(scope, tvb, bit_offset, no_of_chars);
3449 }
3450 break;
3451
3452 case ENC_ASCII_7BITS0x00000034:
3453 {
3454 int bit_offset = offset << 3;
3455 int no_of_chars = (length << 3) / 7;
3456 strptr = (uint8_t*)tvb_get_ascii_7bits_string(scope, tvb, bit_offset, no_of_chars);
3457 }
3458 break;
3459
3460 case ENC_EBCDIC0x0000002E:
3461 /*
3462 * "Common" EBCDIC, covering all characters with the
3463 * same code point in all Roman-alphabet EBCDIC code
3464 * pages.
3465 */
3466 strptr = tvb_get_nonascii_unichar2_string(scope, tvb, offset, length, charset_table_ebcdic);
3467 break;
3468
3469 case ENC_EBCDIC_CP0370x00000038:
3470 /*
3471 * EBCDIC code page 037.
3472 */
3473 strptr = tvb_get_nonascii_unichar2_string(scope, tvb, offset, length, charset_table_ebcdic_cp037);
3474 break;
3475
3476 case ENC_EBCDIC_CP5000x00000060:
3477 /*
3478 * EBCDIC code page 500.
3479 */
3480 strptr = tvb_get_nonascii_unichar2_string(scope, tvb, offset, length, charset_table_ebcdic_cp500);
3481 break;
3482
3483 case ENC_T610x00000036:
3484 strptr = tvb_get_t61_string(scope, tvb, offset, length);
3485 break;
3486
3487 case ENC_BCD_DIGITS_0_90x00000044:
3488 /*
3489 * Packed BCD, with digits 0-9.
3490 */
3491 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3492 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3493 strptr = (uint8_t*)tvb_get_bcd_string(scope, tvb, offset, length, &Dgt0_9_bcd, skip_first, odd, !(encoding & ENC_LITTLE_ENDIAN0x80000000));
3494 break;
3495
3496 case ENC_KEYPAD_ABC_TBCD0x00000046:
3497 /*
3498 * Keypad-with-a/b/c "telephony BCD" - packed BCD, with
3499 * digits 0-9 and symbols *, #, a, b, and c.
3500 */
3501 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3502 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3503 strptr = (uint8_t*)tvb_get_bcd_string(scope, tvb, offset, length, &Dgt_keypad_abc_tbcd, skip_first, odd, !(encoding & ENC_LITTLE_ENDIAN0x80000000));
3504 break;
3505
3506 case ENC_KEYPAD_BC_TBCD0x00000048:
3507 /*
3508 * Keypad-with-B/C "telephony BCD" - packed BCD, with
3509 * digits 0-9 and symbols B, C, *, and #.
3510 */
3511 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3512 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3513 strptr = (uint8_t*)tvb_get_bcd_string(scope, tvb, offset, length, &Dgt_ansi_tbcd, skip_first, odd, !(encoding & ENC_LITTLE_ENDIAN0x80000000));
3514 break;
3515
3516 case ENC_3GPP_TS_23_038_7BITS_UNPACKED0x0000004C:
3517 strptr = (uint8_t*)tvb_get_ts_23_038_7bits_string_unpacked(scope, tvb, offset, length);
3518 break;
3519
3520 case ENC_ETSI_TS_102_221_ANNEX_A0x0000004E:
3521 strptr = (uint8_t*)tvb_get_etsi_ts_102_221_annex_a_string(scope, tvb, offset, length);
3522 break;
3523
3524 case ENC_GB180300x00000050:
3525 strptr = tvb_get_gb18030_string(scope, tvb, offset, length);
3526 break;
3527
3528 case ENC_EUC_KR0x00000052:
3529 strptr = tvb_get_euc_kr_string(scope, tvb, offset, length);
3530 break;
3531
3532 case ENC_APN_STR0x00000054:
3533 strptr = tvb_get_apn_string(scope, tvb, offset, length);
3534 break;
3535
3536 case ENC_DECT_STANDARD_8BITS0x00000056:
3537 strptr = tvb_get_dect_standard_8bits_string(scope, tvb, offset, length);
3538 break;
3539
3540 case ENC_DECT_STANDARD_4BITS_TBCD0x00000058:
3541 /*
3542 * DECT standard 4bits "telephony BCD" - packed BCD, with
3543 * digits 0-9 and symbol SPACE for 0xb.
3544 */
3545 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3546 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3547 strptr = (uint8_t*)tvb_get_bcd_string(scope, tvb, offset, length, &Dgt_dect_standard_4bits_tbcd, skip_first, odd, false0);
3548 break;
3549 }
3550 return strptr;
3551}
3552
3553/*
3554 * This is like tvb_get_string_enc(), except that it handles null-padded
3555 * strings.
3556 *
3557 * Currently, string values are stored as UTF-8 null-terminated strings,
3558 * so nothing needs to be done differently for null-padded strings; we
3559 * could save a little memory by not storing the null padding.
3560 *
3561 * If we ever store string values differently, in a fashion that doesn't
3562 * involve null termination, that might change.
3563 */
3564uint8_t *
3565tvb_get_stringzpad(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset,
3566 const int length, const unsigned encoding)
3567{
3568 return tvb_get_string_enc(scope, tvb, offset, length, encoding);
3569}
3570
3571/*
3572 * These routines are like the above routines, except that they handle
3573 * null-terminated strings. They find the length of that string (and
3574 * throw an exception if the tvbuff ends before we find the null), and
3575 * also return through a pointer the length of the string, in bytes,
3576 * including the terminating null (the terminating null being 2 bytes
3577 * for UCS-2 and UTF-16, 4 bytes for UCS-4, and 1 byte for other
3578 * encodings).
3579 */
3580static uint8_t *
3581tvb_get_ascii_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3582{
3583 unsigned size;
3584 const uint8_t *ptr;
3585
3586 size = tvb_strsize(tvb, offset);
3587 ptr = ensure_contiguous(tvb, offset, size);
3588 /* XXX, conversion between signed/unsigned integer */
3589 if (lengthp)
3590 *lengthp = size;
3591 return get_ascii_string(scope, ptr, size);
3592}
3593
3594static uint8_t *
3595tvb_get_iso_646_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp, const gunichar2 table[0x80])
3596{
3597 unsigned size;
3598 const uint8_t *ptr;
3599
3600 size = tvb_strsize(tvb, offset);
3601 ptr = ensure_contiguous(tvb, offset, size);
3602 /* XXX, conversion between signed/unsigned integer */
3603 if (lengthp)
3604 *lengthp = size;
3605 return get_iso_646_string(scope, ptr, size, table);
3606}
3607
3608static uint8_t *
3609tvb_get_utf_8_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp)
3610{
3611 unsigned size;
3612 const uint8_t *ptr;
3613
3614 size = tvb_strsize(tvb, offset);
3615 ptr = ensure_contiguous(tvb, offset, size);
3616 /* XXX, conversion between signed/unsigned integer */
3617 if (lengthp)
3618 *lengthp = size;
3619 return get_utf_8_string(scope, ptr, size);
3620}
3621
3622static uint8_t *
3623tvb_get_stringz_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3624{
3625 unsigned size;
3626 const uint8_t *ptr;
3627
3628 size = tvb_strsize(tvb, offset);
3629 ptr = ensure_contiguous(tvb, offset, size);
3630 /* XXX, conversion between signed/unsigned integer */
3631 if (lengthp)
3632 *lengthp = size;
3633 return get_8859_1_string(scope, ptr, size);
3634}
3635
3636static uint8_t *
3637tvb_get_stringz_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp, const gunichar2 table[0x80])
3638{
3639 unsigned size;
3640 const uint8_t *ptr;
3641
3642 size = tvb_strsize(tvb, offset);
3643 ptr = ensure_contiguous(tvb, offset, size);
3644 /* XXX, conversion between signed/unsigned integer */
3645 if (lengthp)
3646 *lengthp = size;
3647 return get_unichar2_string(scope, ptr, size, table);
3648}
3649
3650/*
3651 * Given a tvbuff and an offset, with the offset assumed to refer to
3652 * a null-terminated string, find the length of that string (and throw
3653 * an exception if the tvbuff ends before we find the null), ensure that
3654 * the TVB is flat, and return a pointer to the string (in the TVB).
3655 * Also return the length of the string (including the terminating null)
3656 * through a pointer.
3657 *
3658 * As long as we aren't using composite TVBs, this saves the cycles used
3659 * (often unnecessarily) in allocating a buffer and copying the string into
3660 * it. (If we do start using composite TVBs, we may want to replace this
3661 * function with the _ephemeral version.)
3662 */
3663const uint8_t *
3664tvb_get_const_stringz(tvbuff_t *tvb, const int offset, int *lengthp)
3665{
3666 unsigned size;
3667 const uint8_t *strptr;
3668
3669 size = tvb_strsize(tvb, offset);
3670 strptr = ensure_contiguous(tvb, offset, size);
3671 if (lengthp)
3672 *lengthp = size;
3673 return strptr;
3674}
3675
3676static char *
3677tvb_get_ucs_2_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3678{
3679 int size; /* Number of bytes in string */
3680 const uint8_t *ptr;
3681
3682 size = tvb_unicode_strsize(tvb, offset);
3683 ptr = ensure_contiguous(tvb, offset, size);
3684 /* XXX, conversion between signed/unsigned integer */
3685 if (lengthp)
3686 *lengthp = size;
3687 return (char*)get_ucs_2_string(scope, ptr, size, encoding);
3688}
3689
3690static char *
3691tvb_get_utf_16_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3692{
3693 int size;
3694 const uint8_t *ptr;
3695
3696 size = tvb_unicode_strsize(tvb, offset);
3697 ptr = ensure_contiguous(tvb, offset, size);
3698 /* XXX, conversion between signed/unsigned integer */
3699 if (lengthp)
3700 *lengthp = size;
3701 return (char*)get_utf_16_string(scope, ptr, size, encoding);
3702}
3703
3704static char *
3705tvb_get_ucs_4_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3706{
3707 int size;
3708 gunichar uchar;
3709 const uint8_t *ptr;
3710
3711 size = 0;
3712 do {
3713 /* Endianness doesn't matter when looking for null */
3714 uchar = tvb_get_ntohl(tvb, offset + size);
3715 size += 4;
3716 } while(uchar != 0);
3717
3718 ptr = ensure_contiguous(tvb, offset, size);
3719 /* XXX, conversion between signed/unsigned integer */
3720 if (lengthp)
3721 *lengthp = size;
3722 return (char*)get_ucs_4_string(scope, ptr, size, encoding);
3723}
3724
3725static uint8_t *
3726tvb_get_nonascii_unichar2_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp, const gunichar2 table[256])
3727{
3728 unsigned size;
3729 const uint8_t *ptr;
3730
3731 size = tvb_strsize(tvb, offset);
3732 ptr = ensure_contiguous(tvb, offset, size);
3733 /* XXX, conversion between signed/unsigned integer */
3734 if (lengthp)
3735 *lengthp = size;
3736 return get_nonascii_unichar2_string(scope, ptr, size, table);
3737}
3738
3739static uint8_t *
3740tvb_get_t61_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3741{
3742 unsigned size;
3743 const uint8_t *ptr;
3744
3745 size = tvb_strsize(tvb, offset);
3746 ptr = ensure_contiguous(tvb, offset, size);
3747 /* XXX, conversion between signed/unsigned integer */
3748 if (lengthp)
3749 *lengthp = size;
3750 return get_t61_string(scope, ptr, size);
3751}
3752
3753static uint8_t *
3754tvb_get_gb18030_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3755{
3756 unsigned size;
3757 const uint8_t *ptr;
3758
3759 size = tvb_strsize(tvb, offset);
3760 ptr = ensure_contiguous(tvb, offset, size);
3761 /* XXX, conversion between signed/unsigned integer */
3762 if (lengthp)
3763 *lengthp = size;
3764 return get_gb18030_string(scope, ptr, size);
3765}
3766
3767static uint8_t *
3768tvb_get_euc_kr_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3769{
3770 unsigned size;
3771 const uint8_t *ptr;
3772
3773 size = tvb_strsize(tvb, offset);
3774 ptr = ensure_contiguous(tvb, offset, size);
3775 /* XXX, conversion between signed/unsigned integer */
3776 if (lengthp)
3777 *lengthp = size;
3778 return get_euc_kr_string(scope, ptr, size);
3779}
3780
3781static uint8_t *
3782tvb_get_dect_standard_8bits_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3783{
3784 unsigned size;
3785 const uint8_t *ptr;
3786
3787 size = tvb_strsize(tvb, offset);
3788 ptr = ensure_contiguous(tvb, offset, size);
3789 /* XXX, conversion between signed/unsigned integer */
3790 if (lengthp)
3791 *lengthp = size;
3792 return get_dect_standard_8bits_string(scope, ptr, size);
3793}
3794
3795uint8_t *
3796tvb_get_stringz_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3797{
3798 uint8_t *strptr;
3799
3800 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3800, "tvb && tvb->initialized"
))))
;
3801
3802 switch (encoding & ENC_CHARENCODING_MASK0x0000FFFE) {
3803
3804 case ENC_ASCII0x00000000:
3805 default:
3806 /*
3807 * For now, we treat bogus values as meaning
3808 * "ASCII" rather than reporting an error,
3809 * for the benefit of old dissectors written
3810 * when the last argument to proto_tree_add_item()
3811 * was a bool for the byte order, not an
3812 * encoding value, and passed non-zero values
3813 * other than true to mean "little-endian".
3814 */
3815 strptr = tvb_get_ascii_stringz(scope, tvb, offset, lengthp);
3816 break;
3817
3818 case ENC_UTF_80x00000002:
3819 /*
3820 * XXX - should map all invalid UTF-8 sequences
3821 * to a "substitute" UTF-8 character.
3822 * XXX - should map code points > 10FFFF to REPLACEMENT
3823 * CHARACTERs.
3824 */
3825 strptr = tvb_get_utf_8_stringz(scope, tvb, offset, lengthp);
3826 break;
3827
3828 case ENC_UTF_160x00000004:
3829 strptr = (uint8_t*)tvb_get_utf_16_stringz(scope, tvb, offset, lengthp,
3830 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3831 break;
3832
3833 case ENC_UCS_20x00000006:
3834 strptr = (uint8_t*)tvb_get_ucs_2_stringz(scope, tvb, offset, lengthp,
3835 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3836 break;
3837
3838 case ENC_UCS_40x00000008:
3839 strptr = (uint8_t*)tvb_get_ucs_4_stringz(scope, tvb, offset, lengthp,
3840 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3841 break;
3842
3843 case ENC_ISO_8859_10x0000000A:
3844 /*
3845 * ISO 8859-1 printable code point values are equal
3846 * to the equivalent Unicode code point value, so
3847 * no translation table is needed.
3848 */
3849 strptr = tvb_get_stringz_8859_1(scope, tvb, offset, lengthp);
3850 break;
3851
3852 case ENC_ISO_8859_20x0000000C:
3853 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_2);
3854 break;
3855
3856 case ENC_ISO_8859_30x0000000E:
3857 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_3);
3858 break;
3859
3860 case ENC_ISO_8859_40x00000010:
3861 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_4);
3862 break;
3863
3864 case ENC_ISO_8859_50x00000012:
3865 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_5);
3866 break;
3867
3868 case ENC_ISO_8859_60x00000014:
3869 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_6);
3870 break;
3871
3872 case ENC_ISO_8859_70x00000016:
3873 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_7);
3874 break;
3875
3876 case ENC_ISO_8859_80x00000018:
3877 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_8);
3878 break;
3879
3880 case ENC_ISO_8859_90x0000001A:
3881 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_9);
3882 break;
3883
3884 case ENC_ISO_8859_100x0000001C:
3885 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_10);
3886 break;
3887
3888 case ENC_ISO_8859_110x0000001E:
3889 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_11);
3890 break;
3891
3892 case ENC_ISO_8859_130x00000022:
3893 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_13);
3894 break;
3895
3896 case ENC_ISO_8859_140x00000024:
3897 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_14);
3898 break;
3899
3900 case ENC_ISO_8859_150x00000026:
3901 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_15);
3902 break;
3903
3904 case ENC_ISO_8859_160x00000028:
3905 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_16);
3906 break;
3907
3908 case ENC_WINDOWS_12500x0000002A:
3909 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1250);
3910 break;
3911
3912 case ENC_WINDOWS_12510x0000003C:
3913 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1251);
3914 break;
3915
3916 case ENC_WINDOWS_12520x0000003A:
3917 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1252);
3918 break;
3919
3920 case ENC_MAC_ROMAN0x00000030:
3921 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_mac_roman);
3922 break;
3923
3924 case ENC_CP4370x00000032:
3925 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp437);
3926 break;
3927
3928 case ENC_CP8550x0000003E:
3929 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp855);
3930 break;
3931
3932 case ENC_CP8660x00000040:
3933 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp866);
3934 break;
3935
3936 case ENC_ISO_646_BASIC0x00000042:
3937 strptr = tvb_get_iso_646_stringz(scope, tvb, offset, lengthp, charset_table_iso_646_basic);
3938 break;
3939
3940 case ENC_3GPP_TS_23_038_7BITS_PACKED0x0000002C:
3941 case ENC_3GPP_TS_23_038_7BITS_UNPACKED0x0000004C:
3942 case ENC_ETSI_TS_102_221_ANNEX_A0x0000004E:
3943 REPORT_DISSECTOR_BUG("TS 23.038 7bits has no null character and doesn't support null-terminated strings")proto_report_dissector_bug("TS 23.038 7bits has no null character and doesn't support null-terminated strings"
)
;
3944 break;
3945
3946 case ENC_ASCII_7BITS0x00000034:
3947 REPORT_DISSECTOR_BUG("tvb_get_stringz_enc function with ENC_ASCII_7BITS not implemented yet")proto_report_dissector_bug("tvb_get_stringz_enc function with ENC_ASCII_7BITS not implemented yet"
)
;
3948 break;
3949
3950 case ENC_EBCDIC0x0000002E:
3951 /*
3952 * "Common" EBCDIC, covering all characters with the
3953 * same code point in all Roman-alphabet EBCDIC code
3954 * pages.
3955 */
3956 strptr = tvb_get_nonascii_unichar2_stringz(scope, tvb, offset, lengthp, charset_table_ebcdic);
3957 break;
3958
3959 case ENC_EBCDIC_CP0370x00000038:
3960 /*
3961 * EBCDIC code page 037.
3962 */
3963 strptr = tvb_get_nonascii_unichar2_stringz(scope, tvb, offset, lengthp, charset_table_ebcdic_cp037);
3964 break;
3965
3966 case ENC_EBCDIC_CP5000x00000060:
3967 /*
3968 * EBCDIC code page 500.
3969 */
3970 strptr = tvb_get_nonascii_unichar2_stringz(scope, tvb, offset, lengthp, charset_table_ebcdic_cp500);
3971 break;
3972
3973 case ENC_T610x00000036:
3974 strptr = tvb_get_t61_stringz(scope, tvb, offset, lengthp);
3975 break;
3976
3977 case ENC_GB180300x00000050:
3978 strptr = tvb_get_gb18030_stringz(scope, tvb, offset, lengthp);
3979 break;
3980
3981 case ENC_EUC_KR0x00000052:
3982 strptr = tvb_get_euc_kr_stringz(scope, tvb, offset, lengthp);
3983 break;
3984
3985 case ENC_DECT_STANDARD_8BITS0x00000056:
3986 strptr = tvb_get_dect_standard_8bits_stringz(scope, tvb, offset, lengthp);
3987 break;
3988 }
3989
3990 return strptr;
3991}
3992
3993/* Looks for a stringz (NUL-terminated string) in tvbuff and copies
3994 * no more than bufsize number of bytes, including terminating NUL, to buffer.
3995 * Returns length of string (not including terminating NUL), or -1 if the string was
3996 * truncated in the buffer due to not having reached the terminating NUL.
3997 * In this way, it acts like snprintf().
3998 *
3999 * bufsize MUST be greater than 0.
4000 *
4001 * When processing a packet where the remaining number of bytes is less
4002 * than bufsize, an exception is not thrown if the end of the packet
4003 * is reached before the NUL is found. If no NUL is found before reaching
4004 * the end of the short packet, -1 is still returned, and the string
4005 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
4006 * at the correct spot, terminating the string.
4007 *
4008 * *bytes_copied will contain the number of bytes actually copied,
4009 * including the terminating-NUL.
4010 */
4011static int
4012_tvb_get_raw_bytes_as_stringz(tvbuff_t *tvb, const int offset, const unsigned bufsize, uint8_t* buffer, int *bytes_copied)
4013{
4014 int stringlen;
4015 unsigned abs_offset = 0;
4016 int limit;
4017 unsigned len = 0;
4018 bool_Bool decreased_max = false0;
4019
4020 /* Only read to end of tvbuff, w/o throwing exception. */
4021 check_offset_length(tvb, offset, -1, &abs_offset, &len);
4022
4023 /* There must at least be room for the terminating NUL. */
4024 DISSECTOR_ASSERT(bufsize != 0)((void) ((bufsize != 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4024, "bufsize != 0"
))))
;
4025
4026 /* If there's no room for anything else, just return the NUL. */
4027 if (bufsize == 1) {
4028 buffer[0] = 0;
4029 *bytes_copied = 1;
4030 return 0;
4031 }
4032
4033 /* check_offset_length() won't throw an exception if we're
4034 * looking at the byte immediately after the end of the tvbuff. */
4035 if (len == 0) {
4036 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
4037 }
4038
4039 /*
4040 * If we've been passed a negative number, bufsize will
4041 * be huge.
4042 */
4043 DISSECTOR_ASSERT(bufsize <= INT_MAX)((void) ((bufsize <= 2147483647) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4043, "bufsize <= 2147483647"
))))
;
4044
4045 if ((unsigned)len < bufsize) {
4046 limit = len;
4047 decreased_max = true1;
4048 }
4049 else {
4050 limit = bufsize;
4051 }
4052
4053 stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
4054 /* If NUL wasn't found, copy the data and return -1 */
4055 if (stringlen == -1) {
4056 tvb_memcpy(tvb, buffer, abs_offset, limit);
4057 if (decreased_max) {
4058 buffer[limit] = 0;
4059 /* Add 1 for the extra NUL that we set at buffer[limit],
4060 * pretending that it was copied as part of the string. */
4061 *bytes_copied = limit + 1;
4062 }
4063 else {
4064 *bytes_copied = limit;
4065 }
4066 return -1;
4067 }
4068
4069 /* Copy the string to buffer */
4070 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
4071 *bytes_copied = stringlen + 1;
4072 return stringlen;
4073}
4074
4075int
4076tvb_get_raw_bytes_as_stringz(tvbuff_t *tvb, const int offset, const unsigned bufsize, uint8_t* buffer)
4077{
4078 int len, bytes_copied;
4079
4080 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4080, "tvb && tvb->initialized"
))))
;
4081
4082 len = _tvb_get_raw_bytes_as_stringz(tvb, offset, bufsize, buffer, &bytes_copied);
4083
4084 if (len == -1) {
4085 buffer[bufsize - 1] = 0;
4086 return bytes_copied - 1;
4087 }
4088 else {
4089 return len;
4090 }
4091}
4092
4093/*
4094 * Given a tvbuff, an offset into the tvbuff, a buffer, and a buffer size,
4095 * extract as many raw bytes from the tvbuff, starting at the offset,
4096 * as 1) are available in the tvbuff and 2) will fit in the buffer, leaving
4097 * room for a terminating NUL.
4098 */
4099int
4100tvb_get_raw_bytes_as_string(tvbuff_t *tvb, const int offset, char *buffer, size_t bufsize)
4101{
4102 int len = 0;
4103
4104 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4104, "tvb && tvb->initialized"
))))
;
4105
4106 /* There must be room for the string and the terminating NUL. */
4107 DISSECTOR_ASSERT(bufsize > 0)((void) ((bufsize > 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4107, "bufsize > 0"
))))
;
4108
4109 DISSECTOR_ASSERT(bufsize - 1 < INT_MAX)((void) ((bufsize - 1 < 2147483647) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4109, "bufsize - 1 < 2147483647"
))))
;
4110
4111 len = tvb_captured_length_remaining(tvb, offset);
4112 if (len <= 0) {
4113 buffer[0] = '\0';
4114 return 0;
4115 }
4116 if (len > (int)(bufsize - 1))
4117 len = (int)(bufsize - 1);
4118
4119 /* Copy the string to buffer */
4120 tvb_memcpy(tvb, buffer, offset, len);
4121 buffer[len] = '\0';
4122 return len;
4123}
4124
4125bool_Bool
4126tvb_ascii_isprint(tvbuff_t *tvb, const int offset, const int length)
4127{
4128 const uint8_t* buf = tvb_get_ptr(tvb, offset, length);
4129 unsigned abs_offset, abs_length = length;
4130
4131 if (length == -1) {
4132 /* tvb_get_ptr has already checked for exceptions. */
4133 compute_offset_and_remaining(tvb, offset, &abs_offset, &abs_length);
4134 }
4135 for (unsigned i = 0; i < abs_length; i++, buf++)
4136 if (!g_ascii_isprint(*buf)((g_ascii_table[(guchar) (*buf)] & G_ASCII_PRINT) != 0))
4137 return false0;
4138
4139 return true1;
4140}
4141
4142bool_Bool
4143tvb_utf_8_isprint(tvbuff_t *tvb, const int offset, const int length)
4144{
4145 const uint8_t* buf = tvb_get_ptr(tvb, offset, length);
4146 unsigned abs_offset, abs_length = length;
4147
4148 if (length == -1) {
4149 /* tvb_get_ptr has already checked for exceptions. */
4150 compute_offset_and_remaining(tvb, offset, &abs_offset, &abs_length);
4151 }
4152
4153 return isprint_utf8_string((const char*)buf, abs_length);
4154}
4155
4156bool_Bool
4157tvb_ascii_isdigit(tvbuff_t *tvb, const int offset, const int length)
4158{
4159 const uint8_t* buf = tvb_get_ptr(tvb, offset, length);
4160 unsigned abs_offset, abs_length = length;
4161
4162 if (length == -1) {
4163 /* tvb_get_ptr has already checked for exceptions. */
4164 compute_offset_and_remaining(tvb, offset, &abs_offset, &abs_length);
4165 }
4166 for (unsigned i = 0; i < abs_length; i++, buf++)
4167 if (!g_ascii_isdigit(*buf)((g_ascii_table[(guchar) (*buf)] & G_ASCII_DIGIT) != 0))
4168 return false0;
4169
4170 return true1;
4171}
4172
4173static ws_mempbrk_pattern pbrk_crlf;
4174/*
4175 * Given a tvbuff, an offset into the tvbuff, and a length that starts
4176 * at that offset (which may be -1 for "all the way to the end of the
4177 * tvbuff"), find the end of the (putative) line that starts at the
4178 * specified offset in the tvbuff, going no further than the specified
4179 * length.
4180 *
4181 * Return the length of the line (not counting the line terminator at
4182 * the end), or, if we don't find a line terminator:
4183 *
4184 * if "desegment" is true, return -1;
4185 *
4186 * if "desegment" is false, return the amount of data remaining in
4187 * the buffer.
4188 *
4189 * If "next_offset" is not NULL, set "*next_offset" to the offset of the
4190 * character past the line terminator, or past the end of the buffer if
4191 * we don't find a line terminator. (It's not set if we return -1.)
4192 */
4193int
4194tvb_find_line_end(tvbuff_t *tvb, const int offset, int len, int *next_offset, const bool_Bool desegment)
4195{
4196 int eob_offset;
4197 int eol_offset;
4198 int linelen;
4199 unsigned char found_needle = 0;
4200 static bool_Bool compiled = false0;
4201
4202 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4202, "tvb && tvb->initialized"
))))
;
4203
4204 if (len == -1) {
4205 len = _tvb_captured_length_remaining(tvb, offset);
4206 /* if offset is past the end of the tvbuff, len is now 0 */
4207 }
4208
4209 eob_offset = offset + len;
4210
4211 if (!compiled) {
4212 ws_mempbrk_compile(&pbrk_crlf, "\r\n");
4213 compiled = true1;
4214 }
4215
4216 /*
4217 * Look either for a CR or an LF.
4218 */
4219 eol_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset, len, &pbrk_crlf, &found_needle);
4220 if (eol_offset == -1) {
4221 /*
4222 * No CR or LF - line is presumably continued in next packet.
4223 */
4224 if (desegment) {
4225 /*
4226 * Tell our caller we saw no EOL, so they can
4227 * try to desegment and get the entire line
4228 * into one tvbuff.
4229 */
4230 return -1;
4231 } else {
4232 /*
4233 * Pretend the line runs to the end of the tvbuff.
4234 */
4235 linelen = eob_offset - offset;
4236 if (next_offset)
4237 *next_offset = eob_offset;
4238 }
4239 } else {
4240 /*
4241 * Find the number of bytes between the starting offset
4242 * and the CR or LF.
4243 */
4244 linelen = eol_offset - offset;
4245
4246 /*
4247 * Is it a CR?
4248 */
4249 if (found_needle == '\r') {
4250 /*
4251 * Yes - is it followed by an LF?
4252 */
4253 if (eol_offset + 1 >= eob_offset) {
4254 /*
4255 * Dunno - the next byte isn't in this
4256 * tvbuff.
4257 */
4258 if (desegment) {
4259 /*
4260 * We'll return -1, although that
4261 * runs the risk that if the line
4262 * really *is* terminated with a CR,
4263 * we won't properly dissect this
4264 * tvbuff.
4265 *
4266 * It's probably more likely that
4267 * the line ends with CR-LF than
4268 * that it ends with CR by itself.
4269 */
4270 return -1;
4271 }
4272 } else {
4273 /*
4274 * Well, we can at least look at the next
4275 * byte.
4276 */
4277 if (tvb_get_uint8(tvb, eol_offset + 1) == '\n') {
4278 /*
4279 * It's an LF; skip over the CR.
4280 */
4281 eol_offset++;
4282 }
4283 }
4284 }
4285
4286 /*
4287 * Return the offset of the character after the last
4288 * character in the line, skipping over the last character
4289 * in the line terminator.
4290 */
4291 if (next_offset)
4292 *next_offset = eol_offset + 1;
4293 }
4294 return linelen;
4295}
4296
4297static ws_mempbrk_pattern pbrk_crlf_dquote;
4298/*
4299 * Given a tvbuff, an offset into the tvbuff, and a length that starts
4300 * at that offset (which may be -1 for "all the way to the end of the
4301 * tvbuff"), find the end of the (putative) line that starts at the
4302 * specified offset in the tvbuff, going no further than the specified
4303 * length.
4304 *
4305 * However, treat quoted strings inside the buffer specially - don't
4306 * treat newlines in quoted strings as line terminators.
4307 *
4308 * Return the length of the line (not counting the line terminator at
4309 * the end), or the amount of data remaining in the buffer if we don't
4310 * find a line terminator.
4311 *
4312 * If "next_offset" is not NULL, set "*next_offset" to the offset of the
4313 * character past the line terminator, or past the end of the buffer if
4314 * we don't find a line terminator.
4315 */
4316int
4317tvb_find_line_end_unquoted(tvbuff_t *tvb, const int offset, int len, int *next_offset)
4318{
4319 int cur_offset, char_offset;
4320 bool_Bool is_quoted;
4321 unsigned char c = 0;
4322 int eob_offset;
4323 int linelen;
4324 static bool_Bool compiled = false0;
4325
4326 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4326, "tvb && tvb->initialized"
))))
;
4327
4328 if (len == -1)
4329 len = _tvb_captured_length_remaining(tvb, offset);
4330
4331 if (!compiled) {
4332 ws_mempbrk_compile(&pbrk_crlf_dquote, "\r\n\"");
4333 compiled = true1;
4334 }
4335
4336 /*
4337 * XXX - what if "len" is still -1, meaning "offset is past the
4338 * end of the tvbuff"?
4339 */
4340 eob_offset = offset + len;
4341
4342 cur_offset = offset;
4343 is_quoted = false0;
4344 for (;;) {
4345 /*
4346 * Is this part of the string quoted?
4347 */
4348 if (is_quoted) {
4349 /*
4350 * Yes - look only for the terminating quote.
4351 */
4352 char_offset = tvb_find_uint8(tvb, cur_offset, len,
4353 '"');
4354 } else {
4355 /*
4356 * Look either for a CR, an LF, or a '"'.
4357 */
4358 char_offset = tvb_ws_mempbrk_pattern_uint8(tvb, cur_offset, len, &pbrk_crlf_dquote, &c);
4359 }
4360 if (char_offset == -1) {
4361 /*
4362 * Not found - line is presumably continued in
4363 * next packet.
4364 * We pretend the line runs to the end of the tvbuff.
4365 */
4366 linelen = eob_offset - offset;
4367 if (next_offset)
4368 *next_offset = eob_offset;
4369 break;
4370 }
4371
4372 if (is_quoted) {
4373 /*
4374 * We're processing a quoted string.
4375 * We only looked for ", so we know it's a ";
4376 * as we're processing a quoted string, it's a
4377 * closing quote.
4378 */
4379 is_quoted = false0;
4380 } else {
4381 /*
4382 * OK, what is it?
4383 */
4384 if (c == '"') {
4385 /*
4386 * Un-quoted "; it begins a quoted
4387 * string.
4388 */
4389 is_quoted = true1;
4390 } else {
4391 /*
4392 * It's a CR or LF; we've found a line
4393 * terminator.
4394 *
4395 * Find the number of bytes between the
4396 * starting offset and the CR or LF.
4397 */
4398 linelen = char_offset - offset;
4399
4400 /*
4401 * Is it a CR?
4402 */
4403 if (c == '\r') {
4404 /*
4405 * Yes; is it followed by an LF?
4406 */
4407 if (char_offset + 1 < eob_offset &&
4408 tvb_get_uint8(tvb, char_offset + 1)
4409 == '\n') {
4410 /*
4411 * Yes; skip over the CR.
4412 */
4413 char_offset++;
4414 }
4415 }
4416
4417 /*
4418 * Return the offset of the character after
4419 * the last character in the line, skipping
4420 * over the last character in the line
4421 * terminator, and quit.
4422 */
4423 if (next_offset)
4424 *next_offset = char_offset + 1;
4425 break;
4426 }
4427 }
4428
4429 /*
4430 * Step past the character we found.
4431 */
4432 cur_offset = char_offset + 1;
4433 if (cur_offset >= eob_offset) {
4434 /*
4435 * The character we found was the last character
4436 * in the tvbuff - line is presumably continued in
4437 * next packet.
4438 * We pretend the line runs to the end of the tvbuff.
4439 */
4440 linelen = eob_offset - offset;
4441 if (next_offset)
4442 *next_offset = eob_offset;
4443 break;
4444 }
4445 }
4446 return linelen;
4447}
4448
4449/*
4450 * Copied from the mgcp dissector. (This function should be moved to /epan )
4451 * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
4452 * character following offset or offset + maxlength -1 whichever
4453 * is smaller.
4454 *
4455 * Parameters:
4456 * tvb - The tvbuff in which we are skipping whitespace.
4457 * offset - The offset in tvb from which we begin trying to skip whitespace.
4458 * maxlength - The maximum distance from offset that we may try to skip
4459 * whitespace.
4460 *
4461 * Returns: The position in tvb of the first non-whitespace
4462 * character following offset or offset + maxlength -1 whichever
4463 * is smaller.
4464 */
4465int
4466tvb_skip_wsp(tvbuff_t *tvb, const int offset, const int maxlength)
4467{
4468 int counter;
4469 int end, tvb_len;
4470 uint8_t tempchar;
4471
4472 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4472, "tvb && tvb->initialized"
))))
;
4473
4474 /* Get the length remaining */
4475 /*tvb_len = tvb_captured_length(tvb);*/
4476 tvb_len = tvb->length;
4477
4478 end = offset + maxlength;
4479 if (end >= tvb_len)
4480 {
4481 end = tvb_len;
4482 }
4483
4484 /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
4485 for (counter = offset;
4486 counter < end &&
4487 ((tempchar = tvb_get_uint8(tvb,counter)) == ' ' ||
4488 tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
4489 counter++);
4490
4491 return (counter);
4492}
4493
4494int
4495tvb_skip_wsp_return(tvbuff_t *tvb, const int offset)
4496{
4497 int counter;
4498 uint8_t tempchar;
4499
4500 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4500, "tvb && tvb->initialized"
))))
;
4501
4502 for (counter = offset; counter > 0 &&
4503 ((tempchar = tvb_get_uint8(tvb,counter)) == ' ' ||
4504 tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
4505 counter++;
4506
4507 return (counter);
4508}
4509
4510int
4511tvb_skip_uint8(tvbuff_t *tvb, int offset, const int maxlength, const uint8_t ch)
4512{
4513 int end, tvb_len;
4514
4515 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4515, "tvb && tvb->initialized"
))))
;
4516
4517 /* Get the length remaining */
4518 /*tvb_len = tvb_captured_length(tvb);*/
4519 tvb_len = tvb->length;
4520
4521 end = offset + maxlength;
4522 if (end >= tvb_len)
4523 end = tvb_len;
4524
4525 while (offset < end) {
4526 uint8_t tempch = tvb_get_uint8(tvb, offset);
4527
4528 if (tempch != ch)
4529 break;
4530 offset++;
4531 }
4532
4533 return offset;
4534}
4535
4536static ws_mempbrk_pattern pbrk_whitespace;
4537
4538int tvb_get_token_len(tvbuff_t *tvb, const int offset, int len, int *next_offset, const bool_Bool desegment)
4539{
4540 int eob_offset;
4541 int eot_offset;
4542 int tokenlen;
4543 unsigned char found_needle = 0;
4544 static bool_Bool compiled = false0;
4545
4546 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4546, "tvb && tvb->initialized"
))))
;
4547
4548 if (len == -1) {
4549 len = _tvb_captured_length_remaining(tvb, offset);
4550 /* if offset is past the end of the tvbuff, len is now 0 */
4551 }
4552
4553 eob_offset = offset + len;
4554
4555 if (!compiled) {
4556 ws_mempbrk_compile(&pbrk_whitespace, " \r\n");
4557 compiled = true1;
4558 }
4559
4560 /*
4561 * Look either for a space, CR, or LF.
4562 */
4563 eot_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset, len, &pbrk_whitespace, &found_needle);
4564 if (eot_offset == -1) {
4565 /*
4566 * No space, CR or LF - token is presumably continued in next packet.
4567 */
4568 if (desegment) {
4569 /*
4570 * Tell our caller we saw no whitespace, so they can
4571 * try to desegment and get the entire line
4572 * into one tvbuff.
4573 */
4574 return -1;
4575 }
4576 else {
4577 /*
4578 * Pretend the token runs to the end of the tvbuff.
4579 */
4580 tokenlen = eob_offset - offset;
4581 if (next_offset)
4582 *next_offset = eob_offset;
4583 }
4584 }
4585 else {
4586 /*
4587 * Find the number of bytes between the starting offset
4588 * and the space, CR or LF.
4589 */
4590 tokenlen = eot_offset - offset;
4591
4592 /*
4593 * Return the offset of the character after the last
4594 * character in the line, skipping over the last character
4595 * in the line terminator.
4596 */
4597 if (next_offset)
4598 *next_offset = eot_offset + 1;
4599 }
4600 return tokenlen;
4601}
4602
4603/*
4604 * Format a bunch of data from a tvbuff as bytes, returning a pointer
4605 * to the string with the formatted data, with "punct" as a byte
4606 * separator.
4607 */
4608char *
4609tvb_bytes_to_str_punct(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int len, const char punct)
4610{
4611 DISSECTOR_ASSERT(len >= 0)((void) ((len >= 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4611, "len >= 0"
))))
;
4612 return bytes_to_str_punct(scope, ensure_contiguous(tvb, offset, len), len, punct)bytes_to_str_punct_maxlen(scope, ensure_contiguous(tvb, offset
, len), len, punct, 24)
;
4613}
4614
4615/*
4616 * Given a wmem scope, a tvbuff, an offset, a length, an input digit
4617 * set, and a boolean indicator, fetch BCD-encoded digits from a
4618 * tvbuff starting from either the low or high half byte of the
4619 * first byte depending on the boolean indicator (true means "start
4620 * with the high half byte, ignoring the low half byte", and false
4621 * means "start with the low half byte and proceed to the high half
4622 * byte), formating the digits into characters according to the
4623 * input digit set, and return a pointer to a UTF-8 string, allocated
4624 * using the wmem scope. A nibble of 0xf is considered a 'filler'
4625 * and will end the conversion. Similarly if odd is set the last
4626 * high nibble will be omitted. (Note that if both skip_first and
4627 * odd are true, then both the first and last semi-octet are skipped,
4628 * i.e. an even number of nibbles are considered.)
4629 */
4630char *
4631tvb_get_bcd_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int len, const dgt_set_t *dgt, bool_Bool skip_first, bool_Bool odd, bool_Bool bigendian)
4632{
4633 const uint8_t *ptr;
4634 int i = 0;
4635 char *digit_str;
4636 uint8_t octet, nibble;
4637
4638 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4638, "tvb && tvb->initialized"
))))
;
4639
4640 if (len == -1) {
4641 /*
4642 * Run to the end of the captured data.
4643 *
4644 * XXX - captured, or total?
4645 */
4646 /*length = tvb_captured_length(tvb);*/
4647 len = tvb->length;
4648 if (len < offset) {
4649 return (char *)"";
4650 }
4651 len -= offset;
4652 }
4653
4654 ptr = ensure_contiguous(tvb, offset, len);
4655
4656 /*
4657 * XXX - map illegal digits (digits that map to 0) to REPLACEMENT
4658 * CHARACTER, and have all the tables in epan/tvbuff.c use 0 rather
4659 * than '?'?
4660 */
4661 digit_str = (char *)wmem_alloc(scope, len*2 + 1);
4662
4663 while (len > 0) {
4664 octet = *ptr;
4665 if (!skip_first) {
4666 if (bigendian) {
4667 nibble = (octet >> 4) & 0x0f;
4668 } else {
4669 nibble = octet & 0x0f;
4670 }
4671 if (nibble == 0x0f) {
4672 /*
4673 * Stop digit.
4674 */
4675 break;
4676 }
4677 digit_str[i] = dgt->out[nibble];
4678 i++;
4679 }
4680 skip_first = false0;
4681
4682 /*
4683 * unpack second value in byte
4684 */
4685 if (bigendian) {
4686 nibble = octet & 0x0f;
4687 } else {
4688 nibble = octet >> 4;
4689 }
4690
4691 if (nibble == 0x0f) {
4692 /*
4693 * This is the stop digit or a filler digit. Ignore
4694 * it.
4695 */
4696 break;
4697 }
4698 if ((len == 1) && (odd == true1 )){
4699 /* Last octet, skip last high nibble in case of odd number of digits */
4700 break;
4701 }
4702 digit_str[i] = dgt->out[nibble];
4703 i++;
4704
4705 ptr++;
4706 len--;
4707 }
4708 digit_str[i] = '\0';
4709 return digit_str;
4710}
4711
4712/* XXXX Fix me - needs odd indicator added */
4713const char *
4714tvb_bcd_dig_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int len, const dgt_set_t *dgt, bool_Bool skip_first)
4715{
4716 if (!dgt)
4717 dgt = &Dgt0_9_bcd;
4718
4719 return tvb_get_bcd_string(scope, tvb, offset, len, dgt, skip_first, false0, false0);
4720}
4721
4722const char *
4723tvb_bcd_dig_to_str_be(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int len, const dgt_set_t *dgt, bool_Bool skip_first)
4724{
4725 if (!dgt)
4726 dgt = &Dgt0_9_bcd;
4727
4728 return tvb_get_bcd_string(scope, tvb, offset, len, dgt, skip_first, false0, true1);
4729}
4730
4731/*
4732 * Format a bunch of data from a tvbuff as bytes, returning a pointer
4733 * to the string with the formatted data.
4734 */
4735char *tvb_bytes_to_str(wmem_allocator_t *allocator, tvbuff_t *tvb,
4736 const int offset, const int len)
4737{
4738 DISSECTOR_ASSERT(len >= 0)((void) ((len >= 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4738, "len >= 0"
))))
;
4739 return bytes_to_str(allocator, ensure_contiguous(tvb, offset, len), len)bytes_to_str_maxlen(allocator, ensure_contiguous(tvb, offset,
len), len, 36)
;
4740}
4741
4742/* Find a needle tvbuff within a haystack tvbuff. */
4743int
4744tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const int haystack_offset)
4745{
4746 unsigned haystack_abs_offset = 0, haystack_abs_length = 0;
4747 const uint8_t *haystack_data;
4748 const uint8_t *needle_data;
4749 const unsigned needle_len = needle_tvb->length;
4750 const uint8_t *location;
4751
4752 DISSECTOR_ASSERT(haystack_tvb && haystack_tvb->initialized)((void) ((haystack_tvb && haystack_tvb->initialized
) ? (void)0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/tvbuff.c", 4752, "haystack_tvb && haystack_tvb->initialized"
))))
;
4753
4754 if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
4755 return -1;
4756 }
4757
4758 /* Get pointers to the tvbuffs' data. */
4759 haystack_data = ensure_contiguous(haystack_tvb, 0, -1);
4760 needle_data = ensure_contiguous(needle_tvb, 0, -1);
4761
4762 check_offset_length(haystack_tvb, haystack_offset, -1,
4763 &haystack_abs_offset, &haystack_abs_length);
4764
4765 location = ws_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
4766 needle_data, needle_len);
4767
4768 if (location) {
4769 return (int) (location - haystack_data);
4770 }
4771
4772 return -1;
4773}
4774
4775int
4776tvb_raw_offset(tvbuff_t *tvb)
4777{
4778 return ((tvb->raw_offset==-1) ? (tvb->raw_offset = tvb_offset_from_real_beginning(tvb)) : tvb->raw_offset);
4779}
4780
4781void
4782tvb_set_fragment(tvbuff_t *tvb)
4783{
4784 tvb->flags |= TVBUFF_FRAGMENT0x00000001;
4785}
4786
4787struct tvbuff *
4788tvb_get_ds_tvb(tvbuff_t *tvb)
4789{
4790 return(tvb->ds_tvb);
4791}
4792
4793unsigned
4794tvb_get_varint(tvbuff_t *tvb, unsigned offset, unsigned maxlen, uint64_t *value, const unsigned encoding)
4795{
4796 *value = 0;
4797
4798 switch (encoding & ENC_VARINT_MASK(0x00000002|0x00000004|0x00000008|0x00000010)) {
4799 case ENC_VARINT_PROTOBUF0x00000002:
4800 {
4801 unsigned i;
4802 uint64_t b; /* current byte */
4803
4804 for (i = 0; ((i < FT_VARINT_MAX_LEN10) && (i < maxlen)); ++i) {
4805 b = tvb_get_uint8(tvb, offset++);
4806 *value |= ((b & 0x7F) << (i * 7)); /* add lower 7 bits to val */
4807
4808 if (b < 0x80) {
4809 /* end successfully because of last byte's msb(most significant bit) is zero */
4810 return i + 1;
4811 }
4812 }
4813 break;
4814 }
4815
4816 case ENC_VARINT_ZIGZAG0x00000008:
4817 {
4818 unsigned i;
4819 uint64_t b; /* current byte */
4820
4821 for (i = 0; ((i < FT_VARINT_MAX_LEN10) && (i < maxlen)); ++i) {
4822 b = tvb_get_uint8(tvb, offset++);
4823 *value |= ((b & 0x7F) << (i * 7)); /* add lower 7 bits to val */
4824
4825 if (b < 0x80) {
4826 /* end successfully because of last byte's msb(most significant bit) is zero */
4827 *value = (*value >> 1) ^ ((*value & 1) ? -1 : 0);
4828 return i + 1;
4829 }
4830 }
4831 break;
4832 }
4833
4834 case ENC_VARINT_SDNV0x00000010:
4835 {
4836 /* Decodes similar to protobuf but in MSByte order */
4837 unsigned i;
4838 uint64_t b; /* current byte */
4839
4840 for (i = 0; ((i < FT_VARINT_MAX_LEN10) && (i < maxlen)); ++i) {
4841 b = tvb_get_uint8(tvb, offset++);
4842 if ((i == 9) && (*value >= UINT64_C(1)1UL<<(64-7))) {
4843 // guaranteed overflow, not valid SDNV
4844 return 0;
4845 }
4846 *value <<= 7;
4847 *value |= (b & 0x7F); /* add lower 7 bits to val */
4848
4849 if (b < 0x80) {
4850 /* end successfully because of last byte's msb(most significant bit) is zero */
4851 return i + 1;
4852 }
4853 }
4854 break;
4855 }
4856
4857 case ENC_VARINT_QUIC0x00000004:
4858 {
4859 /* calculate variable length */
4860 *value = tvb_get_uint8(tvb, offset);
4861 switch((*value) >> 6) {
4862 case 0: /* 0b00 => 1 byte length (6 bits Usable) */
4863 (*value) &= 0x3F;
4864 return 1;
4865 case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
4866 *value = tvb_get_ntohs(tvb, offset) & 0x3FFF;
4867 return 2;
4868 case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
4869 *value = tvb_get_ntohl(tvb, offset) & 0x3FFFFFFF;
4870 return 4;
4871 case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
4872 *value = tvb_get_ntoh64(tvb, offset) & UINT64_C(0x3FFFFFFFFFFFFFFF)0x3FFFFFFFFFFFFFFFUL;
4873 return 8;
4874 default: /* No Possible */
4875 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/tvbuff.c", 4875,
__func__, "assertion \"not reached\" failed")
;
4876 break;
4877 }
4878 break;
4879 }
4880
4881 default:
4882 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/tvbuff.c", 4882))
;
4883 }
4884
4885 return 0; /* 10 bytes scanned, but no bytes' msb is zero */
4886}
4887
4888/*
4889 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4890 *
4891 * Local variables:
4892 * c-basic-offset: 8
4893 * tab-width: 8
4894 * indent-tabs-mode: t
4895 * End:
4896 *
4897 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4898 * :indentSize=8:tabSize=8:noTabs=false:
4899 */