Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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