Bug Summary

File:epan/tvbuff.c
Warning:line 445, column 17
The left expression of the compound assignment uses uninitialized memory

Annotated Source Code

Press '?' to see keyboard shortcuts

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