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