Bug Summary

File:epan/tvbuff.c
Warning:line 428, column 17
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

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