Bug Summary

File:builds/wireshark/wireshark/epan/tvbuff.c
Warning:line 2375, column 26
The result of left shift is undefined because the right operand '64' is not smaller than 64, the capacity of 'unsigned long'

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-18/lib/clang/18 -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/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-18/lib/clang/18/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 -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 -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -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 -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/libxml2 -isystem /usr/include/lua5.4 -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIC /builds/wireshark/wireshark/epan/tvbuff.c -o /builds/wireshark/wireshark/sbout/2024-11-21-100252-3913-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2024-11-21-100252-3913-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"
))))
;
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) {
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)) {
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"
))))
;
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) {
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);
408
409 /* shift tvb data bit_offset bits to the left */
410 for (i = 0; i < datalen; i++)
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];
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 pntoh16(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 pntoh16(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 pntoh24(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 pntoh32(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 pntoh32(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 pntoh40(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 pntoh48(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 pntoh56(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 pntoh64(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 pntoh64(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 pletoh16(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 pletoh16(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 pletoh24(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 pletoh32(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 pletoh32(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 pletoh40(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 pletoh48(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 pletoh56(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 pletoh64(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 pletoh64(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 = pntoh32(ptr + 0);
2170 guid->data2 = pntoh16(ptr + 4);
2171 guid->data3 = pntoh16(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 = pletoh32(ptr + 0);
2181 guid->data2 = pletoh16(ptr + 4);
2182 guid->data3 = pletoh16(ptr + 6);
2183 memcpy(guid->data4, ptr + 8, sizeof guid->data4);
2184}
2185
2186/*
2187 * NOTE: to support code written when proto_tree_add_item() took a
2188 * bool as its last argument, with false meaning "big-endian"
2189 * and true meaning "little-endian", we treat any non-zero value of
2190 * "encoding" as meaning "little-endian".
2191 */
2192void
2193tvb_get_guid(tvbuff_t *tvb, const int offset, e_guid_t *guid, const unsigned encoding)
2194{
2195 if (encoding) {
2196 tvb_get_letohguid(tvb, offset, guid);
2197 } else {
2198 tvb_get_ntohguid(tvb, offset, guid);
2199 }
2200}
2201
2202static const uint8_t bit_mask8[] = {
2203 0x00,
2204 0x01,
2205 0x03,
2206 0x07,
2207 0x0f,
2208 0x1f,
2209 0x3f,
2210 0x7f,
2211 0xff
2212};
2213
2214
2215/* Get a variable amount of bits
2216 *
2217 * Return a byte array with bit limited data.
2218 * When encoding is ENC_BIG_ENDIAN, the data is aligned to the left.
2219 * When encoding is ENC_LITTLE_ENDIAN, the data is aligned to the right.
2220 */
2221uint8_t *
2222tvb_get_bits_array(wmem_allocator_t *scope, tvbuff_t *tvb, const int bit_offset,
2223 size_t no_of_bits, size_t *data_length, const unsigned encoding)
2224{
2225 tvbuff_t *sub_tvb;
2226 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
2227 sub_tvb = tvb_new_octet_right_aligned(tvb, bit_offset, (int32_t) no_of_bits);
2228 } else {
2229 sub_tvb = tvb_new_octet_aligned(tvb, bit_offset, (int32_t) no_of_bits);
2230 }
2231 *data_length = tvb_reported_length(sub_tvb);
2232 return (uint8_t*)tvb_memdup(scope, sub_tvb, 0, *data_length);
2233}
2234
2235/* Get 1 - 8 bits */
2236uint8_t
2237tvb_get_bits8(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits)
2238{
2239 return (uint8_t)_tvb_get_bits64(tvb, bit_offset, no_of_bits);
2240}
2241
2242/* Get 1 - 16 bits */
2243uint16_t
2244tvb_get_bits16(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2245{
2246 return (uint16_t)tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
2247}
2248
2249/* Get 1 - 32 bits */
2250uint32_t
2251tvb_get_bits32(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2252{
2253 return (uint32_t)tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
2254}
2255
2256/* Get 1 - 64 bits */
2257uint64_t
2258tvb_get_bits64(tvbuff_t *tvb, unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2259{
2260 /* encoding determines bit numbering within octet array */
2261 if (encoding & ENC_LITTLE_ENDIAN0x80000000) {
2
Assuming the condition is true
3
Taking true branch
2262 return _tvb_get_bits64_le(tvb, bit_offset, no_of_bits);
4
Calling '_tvb_get_bits64_le'
2263 } else {
2264 return _tvb_get_bits64(tvb, bit_offset, no_of_bits);
2265 }
2266}
2267
2268/*
2269 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
2270 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
2271 * Offset should be given in bits from the start of the tvb.
2272 * Bits within octet are numbered from MSB (0) to LSB (7). Bit at bit_offset is return value most significant bit.
2273 * The function tolerates requests for more than 64 bits, but will only return the least significant 64 bits.
2274 */
2275static uint64_t
2276_tvb_get_bits64(tvbuff_t *tvb, unsigned bit_offset, const int total_no_of_bits)
2277{
2278 uint64_t value;
2279 unsigned octet_offset = bit_offset >> 3;
2280 uint8_t required_bits_in_first_octet = 8 - (bit_offset % 8);
2281
2282 if(required_bits_in_first_octet > total_no_of_bits)
2283 {
2284 /* the required bits don't extend to the end of the first octet */
2285 uint8_t right_shift = required_bits_in_first_octet - total_no_of_bits;
2286 value = (tvb_get_uint8(tvb, octet_offset) >> right_shift) & bit_mask8[total_no_of_bits % 8];
2287 }
2288 else
2289 {
2290 uint8_t remaining_bit_length = total_no_of_bits;
2291
2292 /* get the bits up to the first octet boundary */
2293 value = 0;
2294 required_bits_in_first_octet %= 8;
2295 if(required_bits_in_first_octet != 0)
2296 {
2297 value = tvb_get_uint8(tvb, octet_offset) & bit_mask8[required_bits_in_first_octet];
2298 remaining_bit_length -= required_bits_in_first_octet;
2299 octet_offset ++;
2300 }
2301 /* take the biggest words, shorts or octets that we can */
2302 while (remaining_bit_length > 7)
2303 {
2304 switch (remaining_bit_length >> 4)
2305 {
2306 case 0:
2307 /* 8 - 15 bits. (note that 0 - 7 would have dropped out of the while() loop) */
2308 value <<= 8;
2309 value += tvb_get_uint8(tvb, octet_offset);
2310 remaining_bit_length -= 8;
2311 octet_offset ++;
2312 break;
2313
2314 case 1:
2315 /* 16 - 31 bits */
2316 value <<= 16;
2317 value += tvb_get_ntohs(tvb, octet_offset);
2318 remaining_bit_length -= 16;
2319 octet_offset += 2;
2320 break;
2321
2322 case 2:
2323 case 3:
2324 /* 32 - 63 bits */
2325 value <<= 32;
2326 value += tvb_get_ntohl(tvb, octet_offset);
2327 remaining_bit_length -= 32;
2328 octet_offset += 4;
2329 break;
2330
2331 default:
2332 /* 64 bits (or more???) */
2333 value = tvb_get_ntoh64(tvb, octet_offset);
2334 remaining_bit_length -= 64;
2335 octet_offset += 8;
2336 break;
2337 }
2338 }
2339 /* get bits from any partial octet at the tail */
2340 if(remaining_bit_length)
2341 {
2342 value <<= remaining_bit_length;
2343 value += (tvb_get_uint8(tvb, octet_offset) >> (8 - remaining_bit_length));
2344 }
2345 }
2346 return value;
2347}
2348
2349/*
2350 * Offset should be given in bits from the start of the tvb.
2351 * Bits within octet are numbered from LSB (0) to MSB (7). Bit at bit_offset is return value least significant bit.
2352 * The function tolerates requests for more than 64 bits, but will only return the least significant 64 bits.
2353 */
2354static uint64_t
2355_tvb_get_bits64_le(tvbuff_t *tvb, unsigned bit_offset, const int total_no_of_bits)
2356{
2357 uint64_t value = 0;
2358 unsigned octet_offset = bit_offset / 8;
2359 int remaining_bits = total_no_of_bits;
2360 int shift = 0;
2361
2362 if (remaining_bits > 64)
5
Assuming 'remaining_bits' is > 64
6
Taking true branch
2363 {
2364 remaining_bits = 64;
7
The value 64 is assigned to 'remaining_bits'
2365 }
2366
2367 if (bit_offset % 8)
8
Assuming the condition is true
9
Taking true branch
2368 {
2369 /* not aligned, extract bits from first octet */
2370 shift = 8 - (bit_offset % 8);
2371 value = tvb_get_uint8(tvb, octet_offset) >> (bit_offset % 8);
2372 if (shift > remaining_bits)
10
Assuming 'shift' is > 'remaining_bits'
11
Taking true branch
2373 {
2374 /* keep only the requested bits */
2375 value &= (UINT64_C(1)1UL << remaining_bits) - 1;
12
The result of left shift is undefined because the right operand '64' is not smaller than 64, the capacity of 'unsigned long'
2376 remaining_bits = 0;
2377 }
2378 else
2379 {
2380 remaining_bits -= shift;
2381 }
2382 octet_offset++;
2383 }
2384
2385 while (remaining_bits > 0)
2386 {
2387 /* take the biggest words, shorts or octets that we can */
2388 if (remaining_bits >= 32)
2389 {
2390 value |= ((uint64_t)tvb_get_letohl(tvb, octet_offset) << shift);
2391 shift += 32;
2392 remaining_bits -= 32;
2393 octet_offset += 4;
2394 }
2395 else if (remaining_bits >= 16)
2396 {
2397 value |= ((uint64_t)tvb_get_letohs(tvb, octet_offset) << shift);
2398 shift += 16;
2399 remaining_bits -= 16;
2400 octet_offset += 2;
2401 }
2402 else if (remaining_bits >= 8)
2403 {
2404 value |= ((uint64_t)tvb_get_uint8(tvb, octet_offset) << shift);
2405 shift += 8;
2406 remaining_bits -= 8;
2407 octet_offset += 1;
2408 }
2409 else
2410 {
2411 unsigned mask = (1 << remaining_bits) - 1;
2412 value |= (((uint64_t)tvb_get_uint8(tvb, octet_offset) & mask) << shift);
2413 shift += remaining_bits;
2414 remaining_bits = 0;
2415 octet_offset += 1;
2416 }
2417 }
2418 return value;
2419}
2420
2421/* Get 1 - 32 bits (should be deprecated as same as tvb_get_bits32??) */
2422uint32_t
2423tvb_get_bits(tvbuff_t *tvb, const unsigned bit_offset, const int no_of_bits, const unsigned encoding)
2424{
2425 return (uint32_t)tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
1
Calling 'tvb_get_bits64'
2426}
2427
2428static int
2429tvb_find_uint8_generic(tvbuff_t *tvb, unsigned abs_offset, unsigned limit, uint8_t needle)
2430{
2431 const uint8_t *ptr;
2432 const uint8_t *result;
2433
2434 ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr() */
2435 if (!ptr)
2436 return -1;
2437
2438 result = (const uint8_t *) memchr(ptr, needle, limit);
2439 if (!result)
2440 return -1;
2441
2442 return (int) ((result - ptr) + abs_offset);
2443}
2444
2445/* Find first occurrence of needle in tvbuff, starting at offset. Searches
2446 * at most maxlength number of bytes; if maxlength is -1, searches to
2447 * end of tvbuff.
2448 * Returns the offset of the found needle, or -1 if not found.
2449 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
2450 * in that case, -1 will be returned if the boundary is reached before
2451 * finding needle. */
2452int
2453tvb_find_uint8(tvbuff_t *tvb, const int offset, const int maxlength, const uint8_t needle)
2454{
2455 const uint8_t *result;
2456 unsigned abs_offset = 0;
2457 unsigned limit = 0;
2458 int exception;
2459
2460 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2460, "tvb && tvb->initialized"
))))
;
2461
2462 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
2463 if (exception)
2464 THROW(exception)except_throw(1, (exception), ((void*)0));
2465
2466 /* Only search to end of tvbuff, w/o throwing exception. */
2467 if (maxlength >= 0 && limit > (unsigned) maxlength) {
2468 /* Maximum length doesn't go past end of tvbuff; search
2469 to that value. */
2470 limit = (unsigned) maxlength;
2471 }
2472
2473 /* If we have real data, perform our search now. */
2474 if (tvb->real_data) {
2475 result = (const uint8_t *)memchr(tvb->real_data + abs_offset, needle, limit);
2476 if (result == NULL((void*)0)) {
2477 return -1;
2478 }
2479 else {
2480 return (int) (result - tvb->real_data);
2481 }
2482 }
2483
2484 if (tvb->ops->tvb_find_uint8)
2485 return tvb->ops->tvb_find_uint8(tvb, abs_offset, limit, needle);
2486
2487 return tvb_find_uint8_generic(tvb, offset, limit, needle);
2488}
2489
2490/* Same as tvb_find_uint8() with 16bit needle. */
2491int
2492tvb_find_uint16(tvbuff_t *tvb, const int offset, const int maxlength,
2493 const uint16_t needle)
2494{
2495 unsigned abs_offset = 0;
2496 unsigned limit = 0;
2497 int exception;
2498
2499 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
2500 if (exception)
2501 THROW(exception)except_throw(1, (exception), ((void*)0));
2502
2503 /* Only search to end of tvbuff, w/o throwing exception. */
2504 if (maxlength >= 0 && limit > (unsigned) maxlength) {
2505 /* Maximum length doesn't go past end of tvbuff; search
2506 to that value. */
2507 limit = (unsigned) maxlength;
2508 }
2509
2510 const uint8_t needle1 = ((needle & 0xFF00) >> 8);
2511 const uint8_t needle2 = ((needle & 0x00FF) >> 0);
2512 unsigned searched_bytes = 0;
2513 unsigned pos = abs_offset;
2514
2515 do {
2516 int offset1 =
2517 tvb_find_uint8(tvb, pos, limit - searched_bytes, needle1);
2518 int offset2 = -1;
2519
2520 if (offset1 == -1) {
2521 return -1;
2522 }
2523
2524 searched_bytes = (unsigned)offset1 - abs_offset + 1;
2525
2526 if (searched_bytes >= limit) {
2527 return -1;
2528 }
2529
2530 offset2 = tvb_find_uint8(tvb, offset1 + 1, 1, needle2);
2531
2532 searched_bytes += 1;
2533
2534 if (offset2 != -1) {
2535 if (searched_bytes > limit) {
2536 return -1;
2537 }
2538 return offset1;
2539 }
2540
2541 pos = offset1 + 1;
2542 } while (searched_bytes < limit);
2543
2544 return -1;
2545}
2546
2547static inline int
2548tvb_ws_mempbrk_uint8_generic(tvbuff_t *tvb, unsigned abs_offset, unsigned limit, const ws_mempbrk_pattern* pattern, unsigned char *found_needle)
2549{
2550 const uint8_t *ptr;
2551 const uint8_t *result;
2552
2553 ptr = ensure_contiguous(tvb, abs_offset, limit); /* tvb_get_ptr */
2554 if (!ptr)
2555 return -1;
2556
2557 result = ws_mempbrk_exec(ptr, limit, pattern, found_needle);
2558 if (!result)
2559 return -1;
2560
2561 return (int) ((result - ptr) + abs_offset);
2562}
2563
2564
2565/* Find first occurrence of any of the pattern chars in tvbuff, starting at offset.
2566 * Searches at most maxlength number of bytes; if maxlength is -1, searches
2567 * to end of tvbuff.
2568 * Returns the offset of the found needle, or -1 if not found.
2569 * Will not throw an exception, even if maxlength exceeds boundary of tvbuff;
2570 * in that case, -1 will be returned if the boundary is reached before
2571 * finding needle. */
2572int
2573tvb_ws_mempbrk_pattern_uint8(tvbuff_t *tvb, const int offset, const int maxlength,
2574 const ws_mempbrk_pattern* pattern, unsigned char *found_needle)
2575{
2576 const uint8_t *result;
2577 unsigned abs_offset = 0;
2578 unsigned limit = 0;
2579 int exception;
2580
2581 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2581, "tvb && tvb->initialized"
))))
;
2582
2583 exception = compute_offset_and_remaining(tvb, offset, &abs_offset, &limit);
2584 if (exception)
2585 THROW(exception)except_throw(1, (exception), ((void*)0));
2586
2587 /* Only search to end of tvbuff, w/o throwing exception. */
2588 if (limit > (unsigned) maxlength) {
2589 /* Maximum length doesn't go past end of tvbuff; search
2590 to that value. */
2591 limit = maxlength;
2592 }
2593
2594 /* If we have real data, perform our search now. */
2595 if (tvb->real_data) {
2596 result = ws_mempbrk_exec(tvb->real_data + abs_offset, limit, pattern, found_needle);
2597 if (result == NULL((void*)0)) {
2598 return -1;
2599 }
2600 else {
2601 return (int) (result - tvb->real_data);
2602 }
2603 }
2604
2605 if (tvb->ops->tvb_ws_mempbrk_pattern_uint8)
2606 return tvb->ops->tvb_ws_mempbrk_pattern_uint8(tvb, abs_offset, limit, pattern, found_needle);
2607
2608 return tvb_ws_mempbrk_uint8_generic(tvb, abs_offset, limit, pattern, found_needle);
2609}
2610
2611/* Find size of stringz (NUL-terminated string) by looking for terminating
2612 * NUL. The size of the string includes the terminating NUL.
2613 *
2614 * If the NUL isn't found, it throws the appropriate exception.
2615 */
2616unsigned
2617tvb_strsize(tvbuff_t *tvb, const int offset)
2618{
2619 unsigned abs_offset = 0, junk_length;
2620 int nul_offset;
2621
2622 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2622, "tvb && tvb->initialized"
))))
;
2623
2624 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
2625 nul_offset = tvb_find_uint8(tvb, abs_offset, -1, 0);
2626 if (nul_offset == -1) {
2627 /*
2628 * OK, we hit the end of the tvbuff, so we should throw
2629 * an exception.
2630 */
2631 if (tvb->length < tvb->contained_length) {
2632 THROW(BoundsError)except_throw(1, (1), ((void*)0));
2633 } else if (tvb->flags & TVBUFF_FRAGMENT0x00000001) {
2634 THROW(FragmentBoundsError)except_throw(1, (4), ((void*)0));
2635 } else if (tvb->length < tvb->reported_length) {
2636 THROW(ContainedBoundsError)except_throw(1, (2), ((void*)0));
2637 } else {
2638 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
2639 }
2640 }
2641 return (nul_offset - abs_offset) + 1;
2642}
2643
2644/* UTF-16/UCS-2 version of tvb_strsize */
2645/* Returns number of bytes including the (two-bytes) null terminator */
2646unsigned
2647tvb_unicode_strsize(tvbuff_t *tvb, const int offset)
2648{
2649 unsigned i = 0;
2650 gunichar2 uchar;
2651
2652 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2652, "tvb && tvb->initialized"
))))
;
2653
2654 do {
2655 /* Endianness doesn't matter when looking for null */
2656 uchar = tvb_get_ntohs(tvb, offset + i);
2657 i += 2;
2658 } while(uchar != 0);
2659
2660 return i;
2661}
2662
2663/* Find length of string by looking for end of string ('\0'), up to
2664 * 'maxlength' characters'; if 'maxlength' is -1, searches to end
2665 * of tvbuff.
2666 * Returns -1 if 'maxlength' reached before finding EOS. */
2667int
2668tvb_strnlen(tvbuff_t *tvb, const int offset, const unsigned maxlength)
2669{
2670 int result_offset;
2671 unsigned abs_offset = 0, junk_length;
2672
2673 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2673, "tvb && tvb->initialized"
))))
;
2674
2675 check_offset_length(tvb, offset, 0, &abs_offset, &junk_length);
2676
2677 result_offset = tvb_find_uint8(tvb, abs_offset, maxlength, 0);
2678
2679 if (result_offset == -1) {
2680 return -1;
2681 }
2682 else {
2683 return result_offset - abs_offset;
2684 }
2685}
2686
2687/*
2688 * Implement strneql etc
2689 */
2690
2691/*
2692 * Call strncmp after checking if enough chars left, returning 0 if
2693 * it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2694 */
2695int
2696tvb_strneql(tvbuff_t *tvb, const int offset, const char *str, const size_t size)
2697{
2698 const uint8_t *ptr;
2699
2700 ptr = ensure_contiguous_no_exception(tvb, offset, (int)size, NULL((void*)0));
2701
2702 if (ptr) {
2703 int cmp = strncmp((const char *)ptr, str, size);
2704
2705 /*
2706 * Return 0 if equal, -1 otherwise.
2707 */
2708 return (cmp == 0 ? 0 : -1);
2709 } else {
2710 /*
2711 * Not enough characters in the tvbuff to match the
2712 * string.
2713 */
2714 return -1;
2715 }
2716}
2717
2718/*
2719 * Call g_ascii_strncasecmp after checking if enough chars left, returning
2720 * 0 if it returns 0 (meaning "equal") and -1 otherwise, otherwise return -1.
2721 */
2722int
2723tvb_strncaseeql(tvbuff_t *tvb, const int offset, const char *str, const size_t size)
2724{
2725 const uint8_t *ptr;
2726
2727 ptr = ensure_contiguous_no_exception(tvb, offset, (int)size, NULL((void*)0));
2728
2729 if (ptr) {
2730 int cmp = g_ascii_strncasecmp((const char *)ptr, str, size);
2731
2732 /*
2733 * Return 0 if equal, -1 otherwise.
2734 */
2735 return (cmp == 0 ? 0 : -1);
2736 } else {
2737 /*
2738 * Not enough characters in the tvbuff to match the
2739 * string.
2740 */
2741 return -1;
2742 }
2743}
2744
2745/*
2746 * Check that the tvbuff contains at least size bytes, starting at
2747 * offset, and that those bytes are equal to str. Return 0 for success
2748 * and -1 for error. This function does not throw an exception.
2749 */
2750int
2751tvb_memeql(tvbuff_t *tvb, const int offset, const uint8_t *str, size_t size)
2752{
2753 const uint8_t *ptr;
2754
2755 ptr = ensure_contiguous_no_exception(tvb, offset, (int) size, NULL((void*)0));
2756
2757 if (ptr) {
2758 int cmp = memcmp(ptr, str, size);
2759
2760 /*
2761 * Return 0 if equal, -1 otherwise.
2762 */
2763 return (cmp == 0 ? 0 : -1);
2764 } else {
2765 /*
2766 * Not enough characters in the tvbuff to match the
2767 * string.
2768 */
2769 return -1;
2770 }
2771}
2772
2773/**
2774 * Format the data in the tvb from offset for size.
2775 */
2776char *
2777tvb_format_text(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int size)
2778{
2779 const uint8_t *ptr;
2780 int len;
2781
2782 len = (size > 0) ? size : 0;
2783
2784 ptr = ensure_contiguous(tvb, offset, size);
2785 return format_text(scope, ptr, len);
2786}
2787
2788/*
2789 * Format the data in the tvb from offset for length ...
2790 */
2791char *
2792tvb_format_text_wsp(wmem_allocator_t* allocator, tvbuff_t *tvb, const int offset, const int size)
2793{
2794 const uint8_t *ptr;
2795 int len;
2796
2797 len = (size > 0) ? size : 0;
2798
2799 ptr = ensure_contiguous(tvb, offset, size);
2800 return format_text_wsp(allocator, ptr, len);
2801}
2802
2803/**
2804 * Like "tvb_format_text()", but for null-padded strings; don't show
2805 * the null padding characters as "\000".
2806 */
2807char *
2808tvb_format_stringzpad(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int size)
2809{
2810 const uint8_t *ptr, *p;
2811 int len;
2812 int stringlen;
2813
2814 len = (size > 0) ? size : 0;
2815
2816 ptr = ensure_contiguous(tvb, offset, size);
2817 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2818 ;
2819 return format_text(scope, ptr, stringlen);
2820}
2821
2822/*
2823 * Like "tvb_format_text_wsp()", but for null-padded strings; don't show
2824 * the null padding characters as "\000".
2825 */
2826char *
2827tvb_format_stringzpad_wsp(wmem_allocator_t* allocator, tvbuff_t *tvb, const int offset, const int size)
2828{
2829 const uint8_t *ptr, *p;
2830 int len;
2831 int stringlen;
2832
2833 len = (size > 0) ? size : 0;
2834
2835 ptr = ensure_contiguous(tvb, offset, size);
2836 for (p = ptr, stringlen = 0; stringlen < len && *p != '\0'; p++, stringlen++)
2837 ;
2838 return format_text_wsp(allocator, ptr, stringlen);
2839}
2840
2841/*
2842 * All string functions below take a scope as an argument.
2843 *
2844 *
2845 * If scope is NULL, memory is allocated with g_malloc() and user must
2846 * explicitly free it with g_free().
2847 * If scope is not NULL, memory is allocated with the corresponding pool
2848 * lifetime.
2849 *
2850 * All functions throw an exception if the tvbuff ends before the string
2851 * does.
2852 */
2853
2854/*
2855 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2856 * of bytes referred to by the tvbuff, offset, and length as an ASCII string,
2857 * with all bytes with the high-order bit set being invalid, and return a
2858 * pointer to a UTF-8 string, allocated using the wmem scope.
2859 *
2860 * Octets with the highest bit set will be converted to the Unicode
2861 * REPLACEMENT CHARACTER.
2862 */
2863static uint8_t *
2864tvb_get_ascii_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
2865{
2866 const uint8_t *ptr;
2867
2868 ptr = ensure_contiguous(tvb, offset, length);
2869 return get_ascii_string(scope, ptr, length);
2870}
2871
2872/*
2873 * Given a wmem scope, a tvbuff, an offset, a length, and a translation table,
2874 * treat the string of bytes referred to by the tvbuff, offset, and length
2875 * as a string encoded using one octet per character, with octets with the
2876 * high-order bit clear being mapped by the translation table to 2-byte
2877 * Unicode Basic Multilingual Plane characters (including REPLACEMENT
2878 * CHARACTER) and octets with the high-order bit set being mapped to
2879 * REPLACEMENT CHARACTER, and return a pointer to a UTF-8 string,
2880 * allocated using the wmem scope.
2881 *
2882 * Octets with the highest bit set will be converted to the Unicode
2883 * REPLACEMENT CHARACTER.
2884 */
2885static uint8_t *
2886tvb_get_iso_646_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length, const gunichar2 table[0x80])
2887{
2888 const uint8_t *ptr;
2889
2890 ptr = ensure_contiguous(tvb, offset, length);
2891 return get_iso_646_string(scope, ptr, length, table);
2892}
2893
2894/*
2895 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2896 * of bytes referred to by the tvbuff, the offset. and the length as a UTF-8
2897 * string, and return a pointer to a UTF-8 string, allocated using the wmem
2898 * scope, with all ill-formed sequences replaced with the Unicode REPLACEMENT
2899 * CHARACTER according to the recommended "best practices" given in the Unicode
2900 * Standard and specified by W3C/WHATWG.
2901 *
2902 * Note that in conformance with the Unicode Standard, this treats three
2903 * byte sequences corresponding to UTF-16 surrogate halves (paired or unpaired)
2904 * and two byte overlong encodings of 7-bit ASCII characters as invalid and
2905 * substitutes REPLACEMENT CHARACTER for them. Explicit support for nonstandard
2906 * derivative encoding formats (e.g. CESU-8, Java Modified UTF-8, WTF-8) could
2907 * be added later.
2908 */
2909static uint8_t *
2910tvb_get_utf_8_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int length)
2911{
2912 const uint8_t *ptr;
2913
2914 ptr = ensure_contiguous(tvb, offset, length);
2915 return get_utf_8_string(scope, ptr, length);
2916}
2917
2918/*
2919 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2920 * of bytes referred to by the tvbuff, the offset, and the length as a
2921 * raw string, and return a pointer to that string, allocated using the
2922 * wmem scope. This means a null is appended at the end, but no replacement
2923 * checking is done otherwise, unlike tvb_get_utf_8_string().
2924 *
2925 * Also, this one allows a length of -1 to mean get all, but does not
2926 * allow a negative offset.
2927 */
2928static inline uint8_t *
2929tvb_get_raw_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int length)
2930{
2931 uint8_t *strbuf;
2932 int abs_length = length;
2933
2934 DISSECTOR_ASSERT(offset >= 0)((void) ((offset >= 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2934, "offset >= 0"
))))
;
2935 DISSECTOR_ASSERT(abs_length >= -1)((void) ((abs_length >= -1) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 2935, "abs_length >= -1"
))))
;
2936
2937 if (abs_length < 0)
2938 abs_length = tvb->length - offset;
2939
2940 tvb_ensure_bytes_exist(tvb, offset, abs_length);
2941 strbuf = (uint8_t *)wmem_alloc(scope, abs_length + 1);
2942 tvb_memcpy(tvb, strbuf, offset, abs_length);
2943 strbuf[abs_length] = '\0';
2944 return strbuf;
2945}
2946
2947/*
2948 * Given a wmem scope, a tvbuff, an offset, and a length, treat the string
2949 * of bytes referred to by the tvbuff, the offset, and the length as an
2950 * ISO 8859/1 string, and return a pointer to a UTF-8 string, allocated
2951 * using the wmem scope.
2952 */
2953static uint8_t *
2954tvb_get_string_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
2955{
2956 const uint8_t *ptr;
2957
2958 ptr = ensure_contiguous(tvb, offset, length);
2959 return get_8859_1_string(scope, ptr, length);
2960}
2961
2962/*
2963 * Given a wmem scope, a tvbuff, an offset, a length, and a translation
2964 * table, treat the string of bytes referred to by the tvbuff, the offset,
2965 * and the length as a string encoded using one octet per character, with
2966 * octets with the high-order bit clear being ASCII and octets with the
2967 * high-order bit set being mapped by the translation table to 2-byte
2968 * Unicode Basic Multilingual Plane characters (including REPLACEMENT
2969 * CHARACTER), and return a pointer to a UTF-8 string, allocated with the
2970 * wmem scope.
2971 */
2972static uint8_t *
2973tvb_get_string_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length, const gunichar2 table[0x80])
2974{
2975 const uint8_t *ptr;
2976
2977 ptr = ensure_contiguous(tvb, offset, length);
2978 return get_unichar2_string(scope, ptr, length, table);
2979}
2980
2981/*
2982 * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
2983 * giving the byte order, treat the string of bytes referred to by the
2984 * tvbuff, the offset, and the length as a UCS-2 encoded string in
2985 * the byte order in question, containing characters from the Basic
2986 * Multilingual Plane (plane 0) of Unicode, and return a pointer to a
2987 * UTF-8 string, allocated with the wmem scope.
2988 *
2989 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
2990 *
2991 * Specify length in bytes.
2992 *
2993 * XXX - should map lead and trail surrogate values to REPLACEMENT
2994 * CHARACTERs (0xFFFD)?
2995 * XXX - if there are an odd number of bytes, should put a
2996 * REPLACEMENT CHARACTER at the end.
2997 */
2998static uint8_t *
2999tvb_get_ucs_2_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length, const unsigned encoding)
3000{
3001 const uint8_t *ptr;
3002
3003 ptr = ensure_contiguous(tvb, offset, length);
3004 return get_ucs_2_string(scope, ptr, length, encoding);
3005}
3006
3007/*
3008 * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
3009 * giving the byte order, treat the string of bytes referred to by the
3010 * tvbuff, the offset, and the length as a UTF-16 encoded string in
3011 * the byte order in question, and return a pointer to a UTF-8 string,
3012 * allocated with the wmem scope.
3013 *
3014 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN.
3015 *
3016 * Specify length in bytes.
3017 *
3018 * XXX - should map surrogate errors to REPLACEMENT CHARACTERs (0xFFFD).
3019 * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
3020 * XXX - if there are an odd number of bytes, should put a
3021 * REPLACEMENT CHARACTER at the end.
3022 */
3023static uint8_t *
3024tvb_get_utf_16_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length, const unsigned encoding)
3025{
3026 const uint8_t *ptr;
3027
3028 ptr = ensure_contiguous(tvb, offset, length);
3029 return get_utf_16_string(scope, ptr, length, encoding);
3030}
3031
3032/*
3033 * Given a wmem scope, a tvbuff, an offset, a length, and an encoding
3034 * giving the byte order, treat the string of bytes referred to by the
3035 * tvbuff, the offset, and the length as a UCS-4 encoded string in
3036 * the byte order in question, and return a pointer to a UTF-8 string,
3037 * allocated with the wmem scope.
3038 *
3039 * Encoding parameter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN
3040 *
3041 * Specify length in bytes
3042 *
3043 * XXX - should map lead and trail surrogate values to a "substitute"
3044 * UTF-8 character?
3045 * XXX - should map code points > 10FFFF to REPLACEMENT CHARACTERs.
3046 * XXX - if the number of bytes isn't a multiple of 4, should put a
3047 * REPLACEMENT CHARACTER at the end.
3048 */
3049static char *
3050tvb_get_ucs_4_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int length, const unsigned encoding)
3051{
3052 const uint8_t *ptr;
3053
3054 ptr = ensure_contiguous(tvb, offset, length);
3055 return get_ucs_4_string(scope, ptr, length, encoding);
3056}
3057
3058char *
3059tvb_get_ts_23_038_7bits_string_packed(wmem_allocator_t *scope, tvbuff_t *tvb,
3060 const int bit_offset, int no_of_chars)
3061{
3062 int in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
3063 int length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
3064 const uint8_t *ptr;
3065
3066 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3066, "tvb && tvb->initialized"
))))
;
3067
3068 ptr = ensure_contiguous(tvb, in_offset, length);
3069 return get_ts_23_038_7bits_string_packed(scope, ptr, bit_offset, no_of_chars);
3070}
3071
3072char *
3073tvb_get_ts_23_038_7bits_string_unpacked(wmem_allocator_t *scope, tvbuff_t *tvb,
3074 const int offset, int length)
3075{
3076 const uint8_t *ptr;
3077
3078 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3078, "tvb && tvb->initialized"
))))
;
3079
3080 ptr = ensure_contiguous(tvb, offset, length);
3081 return get_ts_23_038_7bits_string_unpacked(scope, ptr, length);
3082}
3083
3084char *
3085tvb_get_etsi_ts_102_221_annex_a_string(wmem_allocator_t *scope, tvbuff_t *tvb,
3086 const int offset, int length)
3087{
3088 const uint8_t *ptr;
3089
3090 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3090, "tvb && tvb->initialized"
))))
;
3091
3092 ptr = ensure_contiguous(tvb, offset, length);
3093 return get_etsi_ts_102_221_annex_a_string(scope, ptr, length);
3094}
3095
3096char *
3097tvb_get_ascii_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb,
3098 const int bit_offset, int no_of_chars)
3099{
3100 int in_offset = bit_offset >> 3; /* Current pointer to the input buffer */
3101 int length = ((no_of_chars + 1) * 7 + (bit_offset & 0x07)) >> 3;
3102 const uint8_t *ptr;
3103
3104 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3104, "tvb && tvb->initialized"
))))
;
3105
3106 ptr = ensure_contiguous(tvb, in_offset, length);
3107 return get_ascii_7bits_string(scope, ptr, bit_offset, no_of_chars);
3108}
3109
3110/*
3111 * Given a wmem scope, a tvbuff, an offset, a length, and a translation
3112 * table, treat the string of bytes referred to by the tvbuff, the offset,
3113 * and the length as a string encoded using one octet per character, with
3114 * octets being mapped by the translation table to 2-byte Unicode Basic
3115 * Multilingual Plane characters (including REPLACEMENT CHARACTER), and
3116 * return a pointer to a UTF-8 string, allocated with the wmem scope.
3117 */
3118static uint8_t *
3119tvb_get_nonascii_unichar2_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length, const gunichar2 table[256])
3120{
3121 const uint8_t *ptr;
3122
3123 ptr = ensure_contiguous(tvb, offset, length);
3124 return get_nonascii_unichar2_string(scope, ptr, length, table);
3125}
3126
3127/*
3128 * Given a wmem scope, a tvbuff, an offset, and a length, treat the bytes
3129 * referred to by the tvbuff, offset, and length as a GB18030 encoded string,
3130 * and return a pointer to a UTF-8 string, allocated with the wmem scope,
3131 * converted having substituted REPLACEMENT CHARACTER according to the
3132 * Unicode Standard 5.22 U+FFFD Substitution for Conversion.
3133 * ( https://www.unicode.org/versions/Unicode13.0.0/ch05.pdf )
3134 *
3135 * As expected, this will also decode GBK and GB2312 strings.
3136 */
3137static uint8_t *
3138tvb_get_gb18030_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3139{
3140 const uint8_t *ptr;
3141
3142 ptr = ensure_contiguous(tvb, offset, length);
3143 return get_gb18030_string(scope, ptr, length);
3144}
3145
3146/*
3147 * Given a wmem scope, a tvbuff, an offset, and a length, treat the bytes
3148 * referred to by the tvbuff, offset, and length as a EUC-KR encoded string,
3149 * and return a pointer to a UTF-8 string, allocated with the wmem scope,
3150 * converted having substituted REPLACEMENT CHARACTER according to the
3151 * Unicode Standard 5.22 U+FFFD Substitution for Conversion.
3152 * ( https://www.unicode.org/versions/Unicode13.0.0/ch05.pdf )
3153 */
3154static uint8_t *
3155tvb_get_euc_kr_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3156{
3157 const uint8_t *ptr;
3158
3159 ptr = ensure_contiguous(tvb, offset, length);
3160 return get_euc_kr_string(scope, ptr, length);
3161}
3162
3163static uint8_t *
3164tvb_get_t61_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3165{
3166 const uint8_t *ptr;
3167
3168 ptr = ensure_contiguous(tvb, offset, length);
3169 return get_t61_string(scope, ptr, length);
3170}
3171
3172/*
3173 * Encoding tables for BCD strings.
3174 */
3175static const dgt_set_t Dgt0_9_bcd = {
3176 {
3177 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3178 '0','1','2','3','4','5','6','7','8','9','?','?','?','?','?','?'
3179 }
3180};
3181
3182static const dgt_set_t Dgt_keypad_abc_tbcd = {
3183 {
3184 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3185 '0','1','2','3','4','5','6','7','8','9','*','#','a','b','c','?'
3186 }
3187};
3188
3189static const dgt_set_t Dgt_ansi_tbcd = {
3190 {
3191 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3192 '0','1','2','3','4','5','6','7','8','9','?','B','C','*','#','?'
3193 }
3194};
3195
3196static const dgt_set_t Dgt_dect_standard_4bits_tbcd = {
3197 {
3198 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
3199 '0','1','2','3','4','5','6','7','8','9','?',' ','?','?','?','?'
3200 }
3201};
3202
3203static uint8_t *
3204tvb_get_apn_string(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset,
3205 int length)
3206{
3207 wmem_strbuf_t *str;
3208
3209 /*
3210 * This is a domain name.
3211 *
3212 * 3GPP TS 23.003, section 19.4.2 "Fully Qualified Domain Names
3213 * (FQDNs)", subsection 19.4.2.1 "General", says:
3214 *
3215 * The encoding of any identifier used as part of a Fully
3216 * Qualifed Domain Name (FQDN) shall follow the Name Syntax
3217 * defined in IETF RFC 2181 [18], IETF RFC 1035 [19] and
3218 * IETF RFC 1123 [20]. An FQDN consists of one or more
3219 * labels. Each label is coded as a one octet length field
3220 * followed by that number of octets coded as 8 bit ASCII
3221 * characters.
3222 *
3223 * so this does not appear to use full-blown DNS compression -
3224 * the upper 2 bits of the length don't indicate that it's a
3225 * pointer or an extended label (RFC 2673).
3226 */
3227 str = wmem_strbuf_new_sized(scope, length + 1);
3228 if (length > 0) {
3229 const uint8_t *ptr;
3230
3231 ptr = ensure_contiguous(tvb, offset, length);
3232
3233 for (;;) {
3234 unsigned label_len;
3235
3236 /*
3237 * Process this label.
3238 */
3239 label_len = *ptr;
3240 ptr++;
3241 length--;
3242
3243 while (label_len != 0) {
3244 uint8_t ch;
3245
3246 if (length == 0)
3247 goto end;
3248
3249 ch = *ptr;
3250 if (ch < 0x80)
3251 wmem_strbuf_append_c(str, ch);
3252 else
3253 wmem_strbuf_append_unichar_repl(str)wmem_strbuf_append_unichar(str, 0x00FFFD);
3254 ptr++;
3255 label_len--;
3256 length--;
3257 }
3258
3259 if (length == 0)
3260 goto end;
3261
3262 wmem_strbuf_append_c(str, '.');
3263 }
3264 }
3265
3266end:
3267 return (uint8_t *) wmem_strbuf_finalize(str);
3268}
3269
3270static uint8_t *
3271tvb_get_dect_standard_8bits_string(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int length)
3272{
3273 const uint8_t *ptr;
3274
3275 ptr = ensure_contiguous(tvb, offset, length);
3276 return get_dect_standard_8bits_string(scope, ptr, length);
3277}
3278
3279/*
3280 * Given a tvbuff, an offset, a length, and an encoding, allocate a
3281 * buffer big enough to hold a non-null-terminated string of that length
3282 * at that offset, plus a trailing '\0', copy into the buffer the
3283 * string as converted from the appropriate encoding to UTF-8, and
3284 * return a pointer to the string.
3285 */
3286uint8_t *
3287tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset,
3288 const int length, const unsigned encoding)
3289{
3290 uint8_t *strptr;
3291 bool_Bool odd, skip_first;
3292
3293 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3293, "tvb && tvb->initialized"
))))
;
3294
3295 /* make sure length = -1 fails */
3296 if (length < 0) {
3297 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
3298 }
3299
3300 switch (encoding & ENC_CHARENCODING_MASK0x0000FFFE) {
3301
3302 case ENC_ASCII0x00000000:
3303 default:
3304 /*
3305 * For now, we treat bogus values as meaning
3306 * "ASCII" rather than reporting an error,
3307 * for the benefit of old dissectors written
3308 * when the last argument to proto_tree_add_item()
3309 * was a bool for the byte order, not an
3310 * encoding value, and passed non-zero values
3311 * other than true to mean "little-endian".
3312 */
3313 strptr = tvb_get_ascii_string(scope, tvb, offset, length);
3314 break;
3315
3316 case ENC_UTF_80x00000002:
3317 strptr = tvb_get_utf_8_string(scope, tvb, offset, length);
3318 break;
3319
3320 case ENC_UTF_160x00000004:
3321 strptr = tvb_get_utf_16_string(scope, tvb, offset, length,
3322 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3323 break;
3324
3325 case ENC_UCS_20x00000006:
3326 strptr = tvb_get_ucs_2_string(scope, tvb, offset, length,
3327 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3328 break;
3329
3330 case ENC_UCS_40x00000008:
3331 strptr = tvb_get_ucs_4_string(scope, tvb, offset, length,
3332 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3333 break;
3334
3335 case ENC_ISO_8859_10x0000000A:
3336 /*
3337 * ISO 8859-1 printable code point values are equal
3338 * to the equivalent Unicode code point value, so
3339 * no translation table is needed.
3340 */
3341 strptr = tvb_get_string_8859_1(scope, tvb, offset, length);
3342 break;
3343
3344 case ENC_ISO_8859_20x0000000C:
3345 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_2);
3346 break;
3347
3348 case ENC_ISO_8859_30x0000000E:
3349 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_3);
3350 break;
3351
3352 case ENC_ISO_8859_40x00000010:
3353 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_4);
3354 break;
3355
3356 case ENC_ISO_8859_50x00000012:
3357 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_5);
3358 break;
3359
3360 case ENC_ISO_8859_60x00000014:
3361 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_6);
3362 break;
3363
3364 case ENC_ISO_8859_70x00000016:
3365 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_7);
3366 break;
3367
3368 case ENC_ISO_8859_80x00000018:
3369 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_8);
3370 break;
3371
3372 case ENC_ISO_8859_90x0000001A:
3373 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_9);
3374 break;
3375
3376 case ENC_ISO_8859_100x0000001C:
3377 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_10);
3378 break;
3379
3380 case ENC_ISO_8859_110x0000001E:
3381 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_11);
3382 break;
3383
3384 case ENC_ISO_8859_130x00000022:
3385 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_13);
3386 break;
3387
3388 case ENC_ISO_8859_140x00000024:
3389 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_14);
3390 break;
3391
3392 case ENC_ISO_8859_150x00000026:
3393 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_15);
3394 break;
3395
3396 case ENC_ISO_8859_160x00000028:
3397 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_iso_8859_16);
3398 break;
3399
3400 case ENC_WINDOWS_12500x0000002A:
3401 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1250);
3402 break;
3403
3404 case ENC_WINDOWS_12510x0000003C:
3405 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1251);
3406 break;
3407
3408 case ENC_WINDOWS_12520x0000003A:
3409 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp1252);
3410 break;
3411
3412 case ENC_MAC_ROMAN0x00000030:
3413 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_mac_roman);
3414 break;
3415
3416 case ENC_CP4370x00000032:
3417 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp437);
3418 break;
3419
3420 case ENC_CP8550x0000003E:
3421 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp855);
3422 break;
3423
3424 case ENC_CP8660x00000040:
3425 strptr = tvb_get_string_unichar2(scope, tvb, offset, length, charset_table_cp866);
3426 break;
3427
3428 case ENC_ISO_646_BASIC0x00000042:
3429 strptr = tvb_get_iso_646_string(scope, tvb, offset, length, charset_table_iso_646_basic);
3430 break;
3431
3432 case ENC_3GPP_TS_23_038_7BITS_PACKED0x0000002C:
3433 {
3434 int bit_offset = offset << 3;
3435 int no_of_chars = (length << 3) / 7;
3436 strptr = tvb_get_ts_23_038_7bits_string_packed(scope, tvb, bit_offset, no_of_chars);
3437 }
3438 break;
3439
3440 case ENC_ASCII_7BITS0x00000034:
3441 {
3442 int bit_offset = offset << 3;
3443 int no_of_chars = (length << 3) / 7;
3444 strptr = tvb_get_ascii_7bits_string(scope, tvb, bit_offset, no_of_chars);
3445 }
3446 break;
3447
3448 case ENC_EBCDIC0x0000002E:
3449 /*
3450 * "Common" EBCDIC, covering all characters with the
3451 * same code point in all Roman-alphabet EBCDIC code
3452 * pages.
3453 */
3454 strptr = tvb_get_nonascii_unichar2_string(scope, tvb, offset, length, charset_table_ebcdic);
3455 break;
3456
3457 case ENC_EBCDIC_CP0370x00000038:
3458 /*
3459 * EBCDIC code page 037.
3460 */
3461 strptr = tvb_get_nonascii_unichar2_string(scope, tvb, offset, length, charset_table_ebcdic_cp037);
3462 break;
3463
3464 case ENC_EBCDIC_CP5000x00000060:
3465 /*
3466 * EBCDIC code page 500.
3467 */
3468 strptr = tvb_get_nonascii_unichar2_string(scope, tvb, offset, length, charset_table_ebcdic_cp500);
3469 break;
3470
3471 case ENC_T610x00000036:
3472 strptr = tvb_get_t61_string(scope, tvb, offset, length);
3473 break;
3474
3475 case ENC_BCD_DIGITS_0_90x00000044:
3476 /*
3477 * Packed BCD, with digits 0-9.
3478 */
3479 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3480 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3481 strptr = tvb_get_bcd_string(scope, tvb, offset, length, &Dgt0_9_bcd, skip_first, odd, !(encoding & ENC_LITTLE_ENDIAN0x80000000));
3482 break;
3483
3484 case ENC_KEYPAD_ABC_TBCD0x00000046:
3485 /*
3486 * Keypad-with-a/b/c "telephony BCD" - packed BCD, with
3487 * digits 0-9 and symbols *, #, a, b, and c.
3488 */
3489 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3490 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3491 strptr = tvb_get_bcd_string(scope, tvb, offset, length, &Dgt_keypad_abc_tbcd, skip_first, odd, !(encoding & ENC_LITTLE_ENDIAN0x80000000));
3492 break;
3493
3494 case ENC_KEYPAD_BC_TBCD0x00000048:
3495 /*
3496 * Keypad-with-B/C "telephony BCD" - packed BCD, with
3497 * digits 0-9 and symbols B, C, *, and #.
3498 */
3499 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3500 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3501 strptr = tvb_get_bcd_string(scope, tvb, offset, length, &Dgt_ansi_tbcd, skip_first, odd, !(encoding & ENC_LITTLE_ENDIAN0x80000000));
3502 break;
3503
3504 case ENC_3GPP_TS_23_038_7BITS_UNPACKED0x0000004C:
3505 strptr = tvb_get_ts_23_038_7bits_string_unpacked(scope, tvb, offset, length);
3506 break;
3507
3508 case ENC_ETSI_TS_102_221_ANNEX_A0x0000004E:
3509 strptr = tvb_get_etsi_ts_102_221_annex_a_string(scope, tvb, offset, length);
3510 break;
3511
3512 case ENC_GB180300x00000050:
3513 strptr = tvb_get_gb18030_string(scope, tvb, offset, length);
3514 break;
3515
3516 case ENC_EUC_KR0x00000052:
3517 strptr = tvb_get_euc_kr_string(scope, tvb, offset, length);
3518 break;
3519
3520 case ENC_APN_STR0x00000054:
3521 strptr = tvb_get_apn_string(scope, tvb, offset, length);
3522 break;
3523
3524 case ENC_DECT_STANDARD_8BITS0x00000056:
3525 strptr = tvb_get_dect_standard_8bits_string(scope, tvb, offset, length);
3526 break;
3527
3528 case ENC_DECT_STANDARD_4BITS_TBCD0x00000058:
3529 /*
3530 * DECT standard 4bits "telephony BCD" - packed BCD, with
3531 * digits 0-9 and symbol SPACE for 0xb.
3532 */
3533 odd = (encoding & ENC_BCD_ODD_NUM_DIG0x00010000) >> 16;
3534 skip_first = (encoding & ENC_BCD_SKIP_FIRST0x00020000) >> 17;
3535 strptr = tvb_get_bcd_string(scope, tvb, offset, length, &Dgt_dect_standard_4bits_tbcd, skip_first, odd, false0);
3536 break;
3537 }
3538 return strptr;
3539}
3540
3541/*
3542 * This is like tvb_get_string_enc(), except that it handles null-padded
3543 * strings.
3544 *
3545 * Currently, string values are stored as UTF-8 null-terminated strings,
3546 * so nothing needs to be done differently for null-padded strings; we
3547 * could save a little memory by not storing the null padding.
3548 *
3549 * If we ever store string values differently, in a fashion that doesn't
3550 * involve null termination, that might change.
3551 */
3552uint8_t *
3553tvb_get_stringzpad(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset,
3554 const int length, const unsigned encoding)
3555{
3556 return tvb_get_string_enc(scope, tvb, offset, length, encoding);
3557}
3558
3559/*
3560 * These routines are like the above routines, except that they handle
3561 * null-terminated strings. They find the length of that string (and
3562 * throw an exception if the tvbuff ends before we find the null), and
3563 * also return through a pointer the length of the string, in bytes,
3564 * including the terminating null (the terminating null being 2 bytes
3565 * for UCS-2 and UTF-16, 4 bytes for UCS-4, and 1 byte for other
3566 * encodings).
3567 */
3568static uint8_t *
3569tvb_get_ascii_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3570{
3571 unsigned size;
3572 const uint8_t *ptr;
3573
3574 size = tvb_strsize(tvb, offset);
3575 ptr = ensure_contiguous(tvb, offset, size);
3576 /* XXX, conversion between signed/unsigned integer */
3577 if (lengthp)
3578 *lengthp = size;
3579 return get_ascii_string(scope, ptr, size);
3580}
3581
3582static uint8_t *
3583tvb_get_iso_646_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp, const gunichar2 table[0x80])
3584{
3585 unsigned size;
3586 const uint8_t *ptr;
3587
3588 size = tvb_strsize(tvb, offset);
3589 ptr = ensure_contiguous(tvb, offset, size);
3590 /* XXX, conversion between signed/unsigned integer */
3591 if (lengthp)
3592 *lengthp = size;
3593 return get_iso_646_string(scope, ptr, size, table);
3594}
3595
3596static uint8_t *
3597tvb_get_utf_8_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp)
3598{
3599 unsigned size;
3600 const uint8_t *ptr;
3601
3602 size = tvb_strsize(tvb, offset);
3603 ptr = ensure_contiguous(tvb, offset, size);
3604 /* XXX, conversion between signed/unsigned integer */
3605 if (lengthp)
3606 *lengthp = size;
3607 return get_utf_8_string(scope, ptr, size);
3608}
3609
3610static uint8_t *
3611tvb_get_stringz_8859_1(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3612{
3613 unsigned size;
3614 const uint8_t *ptr;
3615
3616 size = tvb_strsize(tvb, offset);
3617 ptr = ensure_contiguous(tvb, offset, size);
3618 /* XXX, conversion between signed/unsigned integer */
3619 if (lengthp)
3620 *lengthp = size;
3621 return get_8859_1_string(scope, ptr, size);
3622}
3623
3624static uint8_t *
3625tvb_get_stringz_unichar2(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp, const gunichar2 table[0x80])
3626{
3627 unsigned size;
3628 const uint8_t *ptr;
3629
3630 size = tvb_strsize(tvb, offset);
3631 ptr = ensure_contiguous(tvb, offset, size);
3632 /* XXX, conversion between signed/unsigned integer */
3633 if (lengthp)
3634 *lengthp = size;
3635 return get_unichar2_string(scope, ptr, size, table);
3636}
3637
3638/*
3639 * Given a tvbuff and an offset, with the offset assumed to refer to
3640 * a null-terminated string, find the length of that string (and throw
3641 * an exception if the tvbuff ends before we find the null), ensure that
3642 * the TVB is flat, and return a pointer to the string (in the TVB).
3643 * Also return the length of the string (including the terminating null)
3644 * through a pointer.
3645 *
3646 * As long as we aren't using composite TVBs, this saves the cycles used
3647 * (often unnecessariliy) in allocating a buffer and copying the string into
3648 * it. (If we do start using composite TVBs, we may want to replace this
3649 * function with the _ephemeral version.)
3650 */
3651const uint8_t *
3652tvb_get_const_stringz(tvbuff_t *tvb, const int offset, int *lengthp)
3653{
3654 unsigned size;
3655 const uint8_t *strptr;
3656
3657 size = tvb_strsize(tvb, offset);
3658 strptr = ensure_contiguous(tvb, offset, size);
3659 if (lengthp)
3660 *lengthp = size;
3661 return strptr;
3662}
3663
3664static char *
3665tvb_get_ucs_2_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3666{
3667 int size; /* Number of bytes in string */
3668 const uint8_t *ptr;
3669
3670 size = tvb_unicode_strsize(tvb, offset);
3671 ptr = ensure_contiguous(tvb, offset, size);
3672 /* XXX, conversion between signed/unsigned integer */
3673 if (lengthp)
3674 *lengthp = size;
3675 return get_ucs_2_string(scope, ptr, size, encoding);
3676}
3677
3678static char *
3679tvb_get_utf_16_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3680{
3681 int size;
3682 const uint8_t *ptr;
3683
3684 size = tvb_unicode_strsize(tvb, offset);
3685 ptr = ensure_contiguous(tvb, offset, size);
3686 /* XXX, conversion between signed/unsigned integer */
3687 if (lengthp)
3688 *lengthp = size;
3689 return get_utf_16_string(scope, ptr, size, encoding);
3690}
3691
3692static char *
3693tvb_get_ucs_4_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3694{
3695 int size;
3696 gunichar uchar;
3697 const uint8_t *ptr;
3698
3699 size = 0;
3700 do {
3701 /* Endianness doesn't matter when looking for null */
3702 uchar = tvb_get_ntohl(tvb, offset + size);
3703 size += 4;
3704 } while(uchar != 0);
3705
3706 ptr = ensure_contiguous(tvb, offset, size);
3707 /* XXX, conversion between signed/unsigned integer */
3708 if (lengthp)
3709 *lengthp = size;
3710 return get_ucs_4_string(scope, ptr, size, encoding);
3711}
3712
3713static uint8_t *
3714tvb_get_nonascii_unichar2_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp, const gunichar2 table[256])
3715{
3716 unsigned size;
3717 const uint8_t *ptr;
3718
3719 size = tvb_strsize(tvb, offset);
3720 ptr = ensure_contiguous(tvb, offset, size);
3721 /* XXX, conversion between signed/unsigned integer */
3722 if (lengthp)
3723 *lengthp = size;
3724 return get_nonascii_unichar2_string(scope, ptr, size, table);
3725}
3726
3727static uint8_t *
3728tvb_get_t61_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3729{
3730 unsigned size;
3731 const uint8_t *ptr;
3732
3733 size = tvb_strsize(tvb, offset);
3734 ptr = ensure_contiguous(tvb, offset, size);
3735 /* XXX, conversion between signed/unsigned integer */
3736 if (lengthp)
3737 *lengthp = size;
3738 return get_t61_string(scope, ptr, size);
3739}
3740
3741static uint8_t *
3742tvb_get_gb18030_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3743{
3744 unsigned size;
3745 const uint8_t *ptr;
3746
3747 size = tvb_strsize(tvb, offset);
3748 ptr = ensure_contiguous(tvb, offset, size);
3749 /* XXX, conversion between signed/unsigned integer */
3750 if (lengthp)
3751 *lengthp = size;
3752 return get_gb18030_string(scope, ptr, size);
3753}
3754
3755static uint8_t *
3756tvb_get_euc_kr_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3757{
3758 unsigned size;
3759 const uint8_t *ptr;
3760
3761 size = tvb_strsize(tvb, offset);
3762 ptr = ensure_contiguous(tvb, offset, size);
3763 /* XXX, conversion between signed/unsigned integer */
3764 if (lengthp)
3765 *lengthp = size;
3766 return get_euc_kr_string(scope, ptr, size);
3767}
3768
3769static uint8_t *
3770tvb_get_dect_standard_8bits_stringz(wmem_allocator_t *scope, tvbuff_t *tvb, int offset, int *lengthp)
3771{
3772 unsigned size;
3773 const uint8_t *ptr;
3774
3775 size = tvb_strsize(tvb, offset);
3776 ptr = ensure_contiguous(tvb, offset, size);
3777 /* XXX, conversion between signed/unsigned integer */
3778 if (lengthp)
3779 *lengthp = size;
3780 return get_t61_string(scope, ptr, size);
3781}
3782
3783uint8_t *
3784tvb_get_stringz_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, int *lengthp, const unsigned encoding)
3785{
3786 uint8_t *strptr;
3787
3788 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 3788, "tvb && tvb->initialized"
))))
;
3789
3790 switch (encoding & ENC_CHARENCODING_MASK0x0000FFFE) {
3791
3792 case ENC_ASCII0x00000000:
3793 default:
3794 /*
3795 * For now, we treat bogus values as meaning
3796 * "ASCII" rather than reporting an error,
3797 * for the benefit of old dissectors written
3798 * when the last argument to proto_tree_add_item()
3799 * was a bool for the byte order, not an
3800 * encoding value, and passed non-zero values
3801 * other than true to mean "little-endian".
3802 */
3803 strptr = tvb_get_ascii_stringz(scope, tvb, offset, lengthp);
3804 break;
3805
3806 case ENC_UTF_80x00000002:
3807 /*
3808 * XXX - should map all invalid UTF-8 sequences
3809 * to a "substitute" UTF-8 character.
3810 * XXX - should map code points > 10FFFF to REPLACEMENT
3811 * CHARACTERs.
3812 */
3813 strptr = tvb_get_utf_8_stringz(scope, tvb, offset, lengthp);
3814 break;
3815
3816 case ENC_UTF_160x00000004:
3817 strptr = tvb_get_utf_16_stringz(scope, tvb, offset, lengthp,
3818 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3819 break;
3820
3821 case ENC_UCS_20x00000006:
3822 strptr = tvb_get_ucs_2_stringz(scope, tvb, offset, lengthp,
3823 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3824 break;
3825
3826 case ENC_UCS_40x00000008:
3827 strptr = tvb_get_ucs_4_stringz(scope, tvb, offset, lengthp,
3828 encoding & (ENC_LITTLE_ENDIAN0x80000000|ENC_BOM0x20000000));
3829 break;
3830
3831 case ENC_ISO_8859_10x0000000A:
3832 /*
3833 * ISO 8859-1 printable code point values are equal
3834 * to the equivalent Unicode code point value, so
3835 * no translation table is needed.
3836 */
3837 strptr = tvb_get_stringz_8859_1(scope, tvb, offset, lengthp);
3838 break;
3839
3840 case ENC_ISO_8859_20x0000000C:
3841 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_2);
3842 break;
3843
3844 case ENC_ISO_8859_30x0000000E:
3845 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_3);
3846 break;
3847
3848 case ENC_ISO_8859_40x00000010:
3849 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_4);
3850 break;
3851
3852 case ENC_ISO_8859_50x00000012:
3853 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_5);
3854 break;
3855
3856 case ENC_ISO_8859_60x00000014:
3857 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_6);
3858 break;
3859
3860 case ENC_ISO_8859_70x00000016:
3861 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_7);
3862 break;
3863
3864 case ENC_ISO_8859_80x00000018:
3865 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_8);
3866 break;
3867
3868 case ENC_ISO_8859_90x0000001A:
3869 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_9);
3870 break;
3871
3872 case ENC_ISO_8859_100x0000001C:
3873 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_10);
3874 break;
3875
3876 case ENC_ISO_8859_110x0000001E:
3877 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_11);
3878 break;
3879
3880 case ENC_ISO_8859_130x00000022:
3881 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_13);
3882 break;
3883
3884 case ENC_ISO_8859_140x00000024:
3885 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_14);
3886 break;
3887
3888 case ENC_ISO_8859_150x00000026:
3889 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_15);
3890 break;
3891
3892 case ENC_ISO_8859_160x00000028:
3893 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_iso_8859_16);
3894 break;
3895
3896 case ENC_WINDOWS_12500x0000002A:
3897 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1250);
3898 break;
3899
3900 case ENC_WINDOWS_12510x0000003C:
3901 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1251);
3902 break;
3903
3904 case ENC_WINDOWS_12520x0000003A:
3905 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp1252);
3906 break;
3907
3908 case ENC_MAC_ROMAN0x00000030:
3909 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_mac_roman);
3910 break;
3911
3912 case ENC_CP4370x00000032:
3913 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp437);
3914 break;
3915
3916 case ENC_CP8550x0000003E:
3917 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp855);
3918 break;
3919
3920 case ENC_CP8660x00000040:
3921 strptr = tvb_get_stringz_unichar2(scope, tvb, offset, lengthp, charset_table_cp866);
3922 break;
3923
3924 case ENC_ISO_646_BASIC0x00000042:
3925 strptr = tvb_get_iso_646_stringz(scope, tvb, offset, lengthp, charset_table_iso_646_basic);
3926 break;
3927
3928 case ENC_3GPP_TS_23_038_7BITS_PACKED0x0000002C:
3929 case ENC_3GPP_TS_23_038_7BITS_UNPACKED0x0000004C:
3930 case ENC_ETSI_TS_102_221_ANNEX_A0x0000004E:
3931 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"
)
;
3932 break;
3933
3934 case ENC_ASCII_7BITS0x00000034:
3935 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"
)
;
3936 break;
3937
3938 case ENC_EBCDIC0x0000002E:
3939 /*
3940 * "Common" EBCDIC, covering all characters with the
3941 * same code point in all Roman-alphabet EBCDIC code
3942 * pages.
3943 */
3944 strptr = tvb_get_nonascii_unichar2_stringz(scope, tvb, offset, lengthp, charset_table_ebcdic);
3945 break;
3946
3947 case ENC_EBCDIC_CP0370x00000038:
3948 /*
3949 * EBCDIC code page 037.
3950 */
3951 strptr = tvb_get_nonascii_unichar2_stringz(scope, tvb, offset, lengthp, charset_table_ebcdic_cp037);
3952 break;
3953
3954 case ENC_EBCDIC_CP5000x00000060:
3955 /*
3956 * EBCDIC code page 500.
3957 */
3958 strptr = tvb_get_nonascii_unichar2_stringz(scope, tvb, offset, lengthp, charset_table_ebcdic_cp500);
3959 break;
3960
3961 case ENC_T610x00000036:
3962 strptr = tvb_get_t61_stringz(scope, tvb, offset, lengthp);
3963 break;
3964
3965 case ENC_GB180300x00000050:
3966 strptr = tvb_get_gb18030_stringz(scope, tvb, offset, lengthp);
3967 break;
3968
3969 case ENC_EUC_KR0x00000052:
3970 strptr = tvb_get_euc_kr_stringz(scope, tvb, offset, lengthp);
3971 break;
3972
3973 case ENC_DECT_STANDARD_8BITS0x00000056:
3974 strptr = tvb_get_dect_standard_8bits_stringz(scope, tvb, offset, lengthp);
3975 break;
3976 }
3977
3978 return strptr;
3979}
3980
3981/* Looks for a stringz (NUL-terminated string) in tvbuff and copies
3982 * no more than bufsize number of bytes, including terminating NUL, to buffer.
3983 * Returns length of string (not including terminating NUL), or -1 if the string was
3984 * truncated in the buffer due to not having reached the terminating NUL.
3985 * In this way, it acts like snprintf().
3986 *
3987 * bufsize MUST be greater than 0.
3988 *
3989 * When processing a packet where the remaining number of bytes is less
3990 * than bufsize, an exception is not thrown if the end of the packet
3991 * is reached before the NUL is found. If no NUL is found before reaching
3992 * the end of the short packet, -1 is still returned, and the string
3993 * is truncated with a NUL, albeit not at buffer[bufsize - 1], but
3994 * at the correct spot, terminating the string.
3995 *
3996 * *bytes_copied will contain the number of bytes actually copied,
3997 * including the terminating-NUL.
3998 */
3999static int
4000_tvb_get_raw_bytes_as_stringz(tvbuff_t *tvb, const int offset, const unsigned bufsize, uint8_t* buffer, int *bytes_copied)
4001{
4002 int stringlen;
4003 unsigned abs_offset = 0;
4004 int limit, len = 0;
4005 bool_Bool decreased_max = false0;
4006
4007 /* Only read to end of tvbuff, w/o throwing exception. */
4008 check_offset_length(tvb, offset, -1, &abs_offset, &len);
4009
4010 /* There must at least be room for the terminating NUL. */
4011 DISSECTOR_ASSERT(bufsize != 0)((void) ((bufsize != 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4011, "bufsize != 0"
))))
;
4012
4013 /* If there's no room for anything else, just return the NUL. */
4014 if (bufsize == 1) {
4015 buffer[0] = 0;
4016 *bytes_copied = 1;
4017 return 0;
4018 }
4019
4020 /* check_offset_length() won't throw an exception if we're
4021 * looking at the byte immediately after the end of the tvbuff. */
4022 if (len == 0) {
4023 THROW(ReportedBoundsError)except_throw(1, (3), ((void*)0));
4024 }
4025
4026 /* This should not happen because check_offset_length() would
4027 * have already thrown an exception if 'offset' were out-of-bounds.
4028 */
4029 DISSECTOR_ASSERT(len != -1)((void) ((len != -1) ? (void)0 : (proto_report_dissector_bug(
"%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4029, "len != -1"
))))
;
4030
4031 /*
4032 * If we've been passed a negative number, bufsize will
4033 * be huge.
4034 */
4035 DISSECTOR_ASSERT(bufsize <= INT_MAX)((void) ((bufsize <= 2147483647) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4035, "bufsize <= 2147483647"
))))
;
4036
4037 if ((unsigned)len < bufsize) {
4038 limit = len;
4039 decreased_max = true1;
4040 }
4041 else {
4042 limit = bufsize;
4043 }
4044
4045 stringlen = tvb_strnlen(tvb, abs_offset, limit - 1);
4046 /* If NUL wasn't found, copy the data and return -1 */
4047 if (stringlen == -1) {
4048 tvb_memcpy(tvb, buffer, abs_offset, limit);
4049 if (decreased_max) {
4050 buffer[limit] = 0;
4051 /* Add 1 for the extra NUL that we set at buffer[limit],
4052 * pretending that it was copied as part of the string. */
4053 *bytes_copied = limit + 1;
4054 }
4055 else {
4056 *bytes_copied = limit;
4057 }
4058 return -1;
4059 }
4060
4061 /* Copy the string to buffer */
4062 tvb_memcpy(tvb, buffer, abs_offset, stringlen + 1);
4063 *bytes_copied = stringlen + 1;
4064 return stringlen;
4065}
4066
4067int
4068tvb_get_raw_bytes_as_stringz(tvbuff_t *tvb, const int offset, const unsigned bufsize, uint8_t* buffer)
4069{
4070 int len, bytes_copied;
4071
4072 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4072, "tvb && tvb->initialized"
))))
;
4073
4074 len = _tvb_get_raw_bytes_as_stringz(tvb, offset, bufsize, buffer, &bytes_copied);
4075
4076 if (len == -1) {
4077 buffer[bufsize - 1] = 0;
4078 return bytes_copied - 1;
4079 }
4080 else {
4081 return len;
4082 }
4083}
4084
4085/*
4086 * Given a tvbuff, an offset into the tvbuff, a buffer, and a buffer size,
4087 * extract as many raw bytes from the tvbuff, starting at the offset,
4088 * as 1) are available in the tvbuff and 2) will fit in the buffer, leaving
4089 * room for a terminating NUL.
4090 */
4091int
4092tvb_get_raw_bytes_as_string(tvbuff_t *tvb, const int offset, char *buffer, size_t bufsize)
4093{
4094 int len = 0;
4095
4096 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4096, "tvb && tvb->initialized"
))))
;
4097
4098 /* There must be room for the string and the terminating NUL. */
4099 DISSECTOR_ASSERT(bufsize > 0)((void) ((bufsize > 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4099, "bufsize > 0"
))))
;
4100
4101 DISSECTOR_ASSERT(bufsize - 1 < INT_MAX)((void) ((bufsize - 1 < 2147483647) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4101, "bufsize - 1 < 2147483647"
))))
;
4102
4103 len = tvb_captured_length_remaining(tvb, offset);
4104 if (len <= 0) {
4105 buffer[0] = '\0';
4106 return 0;
4107 }
4108 if (len > (int)(bufsize - 1))
4109 len = (int)(bufsize - 1);
4110
4111 /* Copy the string to buffer */
4112 tvb_memcpy(tvb, buffer, offset, len);
4113 buffer[len] = '\0';
4114 return len;
4115}
4116
4117bool_Bool
4118tvb_ascii_isprint(tvbuff_t *tvb, const int offset, const int length)
4119{
4120 const uint8_t* buf = tvb_get_ptr(tvb, offset, length);
4121 unsigned abs_offset, abs_length = length;
4122
4123 if (length == -1) {
4124 /* tvb_get_ptr has already checked for exceptions. */
4125 compute_offset_and_remaining(tvb, offset, &abs_offset, &abs_length);
4126 }
4127 for (unsigned i = 0; i < abs_length; i++, buf++)
4128 if (!g_ascii_isprint(*buf)((g_ascii_table[(guchar) (*buf)] & G_ASCII_PRINT) != 0))
4129 return false0;
4130
4131 return true1;
4132}
4133
4134bool_Bool
4135tvb_utf_8_isprint(tvbuff_t *tvb, const int offset, const int length)
4136{
4137 const uint8_t* buf = tvb_get_ptr(tvb, offset, length);
4138 unsigned abs_offset, abs_length = length;
4139
4140 if (length == -1) {
4141 /* tvb_get_ptr has already checked for exceptions. */
4142 compute_offset_and_remaining(tvb, offset, &abs_offset, &abs_length);
4143 }
4144
4145 return isprint_utf8_string(buf, abs_length);
4146}
4147
4148bool_Bool
4149tvb_ascii_isdigit(tvbuff_t *tvb, const int offset, const int length)
4150{
4151 const uint8_t* buf = tvb_get_ptr(tvb, offset, length);
4152 unsigned abs_offset, abs_length = length;
4153
4154 if (length == -1) {
4155 /* tvb_get_ptr has already checked for exceptions. */
4156 compute_offset_and_remaining(tvb, offset, &abs_offset, &abs_length);
4157 }
4158 for (unsigned i = 0; i < abs_length; i++, buf++)
4159 if (!g_ascii_isdigit(*buf)((g_ascii_table[(guchar) (*buf)] & G_ASCII_DIGIT) != 0))
4160 return false0;
4161
4162 return true1;
4163}
4164
4165static ws_mempbrk_pattern pbrk_crlf;
4166/*
4167 * Given a tvbuff, an offset into the tvbuff, and a length that starts
4168 * at that offset (which may be -1 for "all the way to the end of the
4169 * tvbuff"), find the end of the (putative) line that starts at the
4170 * specified offset in the tvbuff, going no further than the specified
4171 * length.
4172 *
4173 * Return the length of the line (not counting the line terminator at
4174 * the end), or, if we don't find a line terminator:
4175 *
4176 * if "desegment" is true, return -1;
4177 *
4178 * if "desegment" is false, return the amount of data remaining in
4179 * the buffer.
4180 *
4181 * If "next_offset" is not NULL, set "*next_offset" to the offset of the
4182 * character past the line terminator, or past the end of the buffer if
4183 * we don't find a line terminator. (It's not set if we return -1.)
4184 */
4185int
4186tvb_find_line_end(tvbuff_t *tvb, const int offset, int len, int *next_offset, const bool_Bool desegment)
4187{
4188 int eob_offset;
4189 int eol_offset;
4190 int linelen;
4191 unsigned char found_needle = 0;
4192 static bool_Bool compiled = false0;
4193
4194 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4194, "tvb && tvb->initialized"
))))
;
4195
4196 if (len == -1) {
4197 len = _tvb_captured_length_remaining(tvb, offset);
4198 /* if offset is past the end of the tvbuff, len is now 0 */
4199 }
4200
4201 eob_offset = offset + len;
4202
4203 if (!compiled) {
4204 ws_mempbrk_compile(&pbrk_crlf, "\r\n");
4205 compiled = true1;
4206 }
4207
4208 /*
4209 * Look either for a CR or an LF.
4210 */
4211 eol_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset, len, &pbrk_crlf, &found_needle);
4212 if (eol_offset == -1) {
4213 /*
4214 * No CR or LF - line is presumably continued in next packet.
4215 */
4216 if (desegment) {
4217 /*
4218 * Tell our caller we saw no EOL, so they can
4219 * try to desegment and get the entire line
4220 * into one tvbuff.
4221 */
4222 return -1;
4223 } else {
4224 /*
4225 * Pretend the line runs to the end of the tvbuff.
4226 */
4227 linelen = eob_offset - offset;
4228 if (next_offset)
4229 *next_offset = eob_offset;
4230 }
4231 } else {
4232 /*
4233 * Find the number of bytes between the starting offset
4234 * and the CR or LF.
4235 */
4236 linelen = eol_offset - offset;
4237
4238 /*
4239 * Is it a CR?
4240 */
4241 if (found_needle == '\r') {
4242 /*
4243 * Yes - is it followed by an LF?
4244 */
4245 if (eol_offset + 1 >= eob_offset) {
4246 /*
4247 * Dunno - the next byte isn't in this
4248 * tvbuff.
4249 */
4250 if (desegment) {
4251 /*
4252 * We'll return -1, although that
4253 * runs the risk that if the line
4254 * really *is* terminated with a CR,
4255 * we won't properly dissect this
4256 * tvbuff.
4257 *
4258 * It's probably more likely that
4259 * the line ends with CR-LF than
4260 * that it ends with CR by itself.
4261 */
4262 return -1;
4263 }
4264 } else {
4265 /*
4266 * Well, we can at least look at the next
4267 * byte.
4268 */
4269 if (tvb_get_uint8(tvb, eol_offset + 1) == '\n') {
4270 /*
4271 * It's an LF; skip over the CR.
4272 */
4273 eol_offset++;
4274 }
4275 }
4276 }
4277
4278 /*
4279 * Return the offset of the character after the last
4280 * character in the line, skipping over the last character
4281 * in the line terminator.
4282 */
4283 if (next_offset)
4284 *next_offset = eol_offset + 1;
4285 }
4286 return linelen;
4287}
4288
4289static ws_mempbrk_pattern pbrk_crlf_dquote;
4290/*
4291 * Given a tvbuff, an offset into the tvbuff, and a length that starts
4292 * at that offset (which may be -1 for "all the way to the end of the
4293 * tvbuff"), find the end of the (putative) line that starts at the
4294 * specified offset in the tvbuff, going no further than the specified
4295 * length.
4296 *
4297 * However, treat quoted strings inside the buffer specially - don't
4298 * treat newlines in quoted strings as line terminators.
4299 *
4300 * Return the length of the line (not counting the line terminator at
4301 * the end), or the amount of data remaining in the buffer if we don't
4302 * find a line terminator.
4303 *
4304 * If "next_offset" is not NULL, set "*next_offset" to the offset of the
4305 * character past the line terminator, or past the end of the buffer if
4306 * we don't find a line terminator.
4307 */
4308int
4309tvb_find_line_end_unquoted(tvbuff_t *tvb, const int offset, int len, int *next_offset)
4310{
4311 int cur_offset, char_offset;
4312 bool_Bool is_quoted;
4313 unsigned char c = 0;
4314 int eob_offset;
4315 int linelen;
4316 static bool_Bool compiled = false0;
4317
4318 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4318, "tvb && tvb->initialized"
))))
;
4319
4320 if (len == -1)
4321 len = _tvb_captured_length_remaining(tvb, offset);
4322
4323 if (!compiled) {
4324 ws_mempbrk_compile(&pbrk_crlf_dquote, "\r\n\"");
4325 compiled = true1;
4326 }
4327
4328 /*
4329 * XXX - what if "len" is still -1, meaning "offset is past the
4330 * end of the tvbuff"?
4331 */
4332 eob_offset = offset + len;
4333
4334 cur_offset = offset;
4335 is_quoted = false0;
4336 for (;;) {
4337 /*
4338 * Is this part of the string quoted?
4339 */
4340 if (is_quoted) {
4341 /*
4342 * Yes - look only for the terminating quote.
4343 */
4344 char_offset = tvb_find_uint8(tvb, cur_offset, len,
4345 '"');
4346 } else {
4347 /*
4348 * Look either for a CR, an LF, or a '"'.
4349 */
4350 char_offset = tvb_ws_mempbrk_pattern_uint8(tvb, cur_offset, len, &pbrk_crlf_dquote, &c);
4351 }
4352 if (char_offset == -1) {
4353 /*
4354 * Not found - line is presumably continued in
4355 * next packet.
4356 * We pretend the line runs to the end of the tvbuff.
4357 */
4358 linelen = eob_offset - offset;
4359 if (next_offset)
4360 *next_offset = eob_offset;
4361 break;
4362 }
4363
4364 if (is_quoted) {
4365 /*
4366 * We're processing a quoted string.
4367 * We only looked for ", so we know it's a ";
4368 * as we're processing a quoted string, it's a
4369 * closing quote.
4370 */
4371 is_quoted = false0;
4372 } else {
4373 /*
4374 * OK, what is it?
4375 */
4376 if (c == '"') {
4377 /*
4378 * Un-quoted "; it begins a quoted
4379 * string.
4380 */
4381 is_quoted = true1;
4382 } else {
4383 /*
4384 * It's a CR or LF; we've found a line
4385 * terminator.
4386 *
4387 * Find the number of bytes between the
4388 * starting offset and the CR or LF.
4389 */
4390 linelen = char_offset - offset;
4391
4392 /*
4393 * Is it a CR?
4394 */
4395 if (c == '\r') {
4396 /*
4397 * Yes; is it followed by an LF?
4398 */
4399 if (char_offset + 1 < eob_offset &&
4400 tvb_get_uint8(tvb, char_offset + 1)
4401 == '\n') {
4402 /*
4403 * Yes; skip over the CR.
4404 */
4405 char_offset++;
4406 }
4407 }
4408
4409 /*
4410 * Return the offset of the character after
4411 * the last character in the line, skipping
4412 * over the last character in the line
4413 * terminator, and quit.
4414 */
4415 if (next_offset)
4416 *next_offset = char_offset + 1;
4417 break;
4418 }
4419 }
4420
4421 /*
4422 * Step past the character we found.
4423 */
4424 cur_offset = char_offset + 1;
4425 if (cur_offset >= eob_offset) {
4426 /*
4427 * The character we found was the last character
4428 * in the tvbuff - line is presumably continued in
4429 * next packet.
4430 * We pretend the line runs to the end of the tvbuff.
4431 */
4432 linelen = eob_offset - offset;
4433 if (next_offset)
4434 *next_offset = eob_offset;
4435 break;
4436 }
4437 }
4438 return linelen;
4439}
4440
4441/*
4442 * Copied from the mgcp dissector. (This function should be moved to /epan )
4443 * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
4444 * character following offset or offset + maxlength -1 whichever
4445 * is smaller.
4446 *
4447 * Parameters:
4448 * tvb - The tvbuff in which we are skipping whitespace.
4449 * offset - The offset in tvb from which we begin trying to skip whitespace.
4450 * maxlength - The maximum distance from offset that we may try to skip
4451 * whitespace.
4452 *
4453 * Returns: The position in tvb of the first non-whitespace
4454 * character following offset or offset + maxlength -1 whichever
4455 * is smaller.
4456 */
4457int
4458tvb_skip_wsp(tvbuff_t *tvb, const int offset, const int maxlength)
4459{
4460 int counter;
4461 int end, tvb_len;
4462 uint8_t tempchar;
4463
4464 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4464, "tvb && tvb->initialized"
))))
;
4465
4466 /* Get the length remaining */
4467 /*tvb_len = tvb_captured_length(tvb);*/
4468 tvb_len = tvb->length;
4469
4470 end = offset + maxlength;
4471 if (end >= tvb_len)
4472 {
4473 end = tvb_len;
4474 }
4475
4476 /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
4477 for (counter = offset;
4478 counter < end &&
4479 ((tempchar = tvb_get_uint8(tvb,counter)) == ' ' ||
4480 tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
4481 counter++);
4482
4483 return (counter);
4484}
4485
4486int
4487tvb_skip_wsp_return(tvbuff_t *tvb, const int offset)
4488{
4489 int counter;
4490 uint8_t tempchar;
4491
4492 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4492, "tvb && tvb->initialized"
))))
;
4493
4494 for (counter = offset; counter > 0 &&
4495 ((tempchar = tvb_get_uint8(tvb,counter)) == ' ' ||
4496 tempchar == '\t' || tempchar == '\n' || tempchar == '\r'); counter--);
4497 counter++;
4498
4499 return (counter);
4500}
4501
4502int
4503tvb_skip_uint8(tvbuff_t *tvb, int offset, const int maxlength, const uint8_t ch)
4504{
4505 int end, tvb_len;
4506
4507 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4507, "tvb && tvb->initialized"
))))
;
4508
4509 /* Get the length remaining */
4510 /*tvb_len = tvb_captured_length(tvb);*/
4511 tvb_len = tvb->length;
4512
4513 end = offset + maxlength;
4514 if (end >= tvb_len)
4515 end = tvb_len;
4516
4517 while (offset < end) {
4518 uint8_t tempch = tvb_get_uint8(tvb, offset);
4519
4520 if (tempch != ch)
4521 break;
4522 offset++;
4523 }
4524
4525 return offset;
4526}
4527
4528static ws_mempbrk_pattern pbrk_whitespace;
4529
4530int tvb_get_token_len(tvbuff_t *tvb, const int offset, int len, int *next_offset, const bool_Bool desegment)
4531{
4532 int eob_offset;
4533 int eot_offset;
4534 int tokenlen;
4535 unsigned char found_needle = 0;
4536 static bool_Bool compiled = false0;
4537
4538 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4538, "tvb && tvb->initialized"
))))
;
4539
4540 if (len == -1) {
4541 len = _tvb_captured_length_remaining(tvb, offset);
4542 /* if offset is past the end of the tvbuff, len is now 0 */
4543 }
4544
4545 eob_offset = offset + len;
4546
4547 if (!compiled) {
4548 ws_mempbrk_compile(&pbrk_whitespace, " \r\n");
4549 compiled = true1;
4550 }
4551
4552 /*
4553 * Look either for a space, CR, or LF.
4554 */
4555 eot_offset = tvb_ws_mempbrk_pattern_uint8(tvb, offset, len, &pbrk_whitespace, &found_needle);
4556 if (eot_offset == -1) {
4557 /*
4558 * No space, CR or LF - token is presumably continued in next packet.
4559 */
4560 if (desegment) {
4561 /*
4562 * Tell our caller we saw no whitespace, so they can
4563 * try to desegment and get the entire line
4564 * into one tvbuff.
4565 */
4566 return -1;
4567 }
4568 else {
4569 /*
4570 * Pretend the token runs to the end of the tvbuff.
4571 */
4572 tokenlen = eob_offset - offset;
4573 if (next_offset)
4574 *next_offset = eob_offset;
4575 }
4576 }
4577 else {
4578 /*
4579 * Find the number of bytes between the starting offset
4580 * and the space, CR or LF.
4581 */
4582 tokenlen = eot_offset - offset;
4583
4584 /*
4585 * Return the offset of the character after the last
4586 * character in the line, skipping over the last character
4587 * in the line terminator.
4588 */
4589 if (next_offset)
4590 *next_offset = eot_offset + 1;
4591 }
4592 return tokenlen;
4593}
4594
4595/*
4596 * Format a bunch of data from a tvbuff as bytes, returning a pointer
4597 * to the string with the formatted data, with "punct" as a byte
4598 * separator.
4599 */
4600char *
4601tvb_bytes_to_str_punct(wmem_allocator_t *scope, tvbuff_t *tvb, const int offset, const int len, const char punct)
4602{
4603 DISSECTOR_ASSERT(len > 0)((void) ((len > 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4603, "len > 0"
))))
;
4604 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)
;
4605}
4606
4607/*
4608 * Given a wmem scope, a tvbuff, an offset, a length, an input digit
4609 * set, and a boolean indicator, fetch BCD-encoded digits from a
4610 * tvbuff starting from either the low or high half byte of the
4611 * first byte depending on the boolean indicator (true means "start
4612 * with the high half byte, ignoring the low half byte", and false
4613 * means "start with the low half byte and proceed to the high half
4614 * byte), formating the digits into characters according to the
4615 * input digit set, and return a pointer to a UTF-8 string, allocated
4616 * using the wmem scope. A nibble of 0xf is considered a 'filler'
4617 * and will end the conversion. Similarly if odd is set the last
4618 * high nibble will be omitted. (Note that if both skip_first and
4619 * odd are true, then both the first and last semi-octet are skipped,
4620 * i.e. an even number of nibbles are considered.)
4621 */
4622char *
4623tvb_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)
4624{
4625 const uint8_t *ptr;
4626 int i = 0;
4627 char *digit_str;
4628 uint8_t octet, nibble;
4629
4630 DISSECTOR_ASSERT(tvb && tvb->initialized)((void) ((tvb && tvb->initialized) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4630, "tvb && tvb->initialized"
))))
;
4631
4632 if (len == -1) {
4633 /*
4634 * Run to the end of the captured data.
4635 *
4636 * XXX - captured, or total?
4637 */
4638 /*length = tvb_captured_length(tvb);*/
4639 len = tvb->length;
4640 if (len < offset) {
4641 return (char *)"";
4642 }
4643 len -= offset;
4644 }
4645
4646 ptr = ensure_contiguous(tvb, offset, len);
4647
4648 /*
4649 * XXX - map illegal digits (digits that map to 0) to REPLACEMENT
4650 * CHARACTER, and have all the tables in epan/tvbuff.c use 0 rather
4651 * than '?'?
4652 */
4653 digit_str = (char *)wmem_alloc(scope, len*2 + 1);
4654
4655 while (len > 0) {
4656 octet = *ptr;
4657 if (!skip_first) {
4658 if (bigendian) {
4659 nibble = (octet >> 4) & 0x0f;
4660 } else {
4661 nibble = octet & 0x0f;
4662 }
4663 if (nibble == 0x0f) {
4664 /*
4665 * Stop digit.
4666 */
4667 break;
4668 }
4669 digit_str[i] = dgt->out[nibble];
4670 i++;
4671 }
4672 skip_first = false0;
4673
4674 /*
4675 * unpack second value in byte
4676 */
4677 if (bigendian) {
4678 nibble = octet & 0x0f;
4679 } else {
4680 nibble = octet >> 4;
4681 }
4682
4683 if (nibble == 0x0f) {
4684 /*
4685 * This is the stop digit or a filler digit. Ignore
4686 * it.
4687 */
4688 break;
4689 }
4690 if ((len == 1) && (odd == true1 )){
4691 /* Last octet, skip last high nibble in case of odd number of digits */
4692 break;
4693 }
4694 digit_str[i] = dgt->out[nibble];
4695 i++;
4696
4697 ptr++;
4698 len--;
4699 }
4700 digit_str[i] = '\0';
4701 return digit_str;
4702}
4703
4704/* XXXX Fix me - needs odd indicator added */
4705const char *
4706tvb_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)
4707{
4708 if (!dgt)
4709 dgt = &Dgt0_9_bcd;
4710
4711 return tvb_get_bcd_string(scope, tvb, offset, len, dgt, skip_first, false0, false0);
4712}
4713
4714const char *
4715tvb_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)
4716{
4717 if (!dgt)
4718 dgt = &Dgt0_9_bcd;
4719
4720 return tvb_get_bcd_string(scope, tvb, offset, len, dgt, skip_first, false0, true1);
4721}
4722
4723/*
4724 * Format a bunch of data from a tvbuff as bytes, returning a pointer
4725 * to the string with the formatted data.
4726 */
4727char *tvb_bytes_to_str(wmem_allocator_t *allocator, tvbuff_t *tvb,
4728 const int offset, const int len)
4729{
4730 DISSECTOR_ASSERT(len > 0)((void) ((len > 0) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/tvbuff.c", 4730, "len > 0"
))))
;
4731 return bytes_to_str(allocator, ensure_contiguous(tvb, offset, len), len)bytes_to_str_maxlen(allocator, ensure_contiguous(tvb, offset,
len), len, 36)
;
4732}
4733
4734/* Find a needle tvbuff within a haystack tvbuff. */
4735int
4736tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const int haystack_offset)
4737{
4738 unsigned haystack_abs_offset = 0, haystack_abs_length = 0;
4739 const uint8_t *haystack_data;
4740 const uint8_t *needle_data;
4741 const unsigned needle_len = needle_tvb->length;
4742 const uint8_t *location;
4743
4744 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", 4744, "haystack_tvb && haystack_tvb->initialized"
))))
;
4745
4746 if (haystack_tvb->length < 1 || needle_tvb->length < 1) {
4747 return -1;
4748 }
4749
4750 /* Get pointers to the tvbuffs' data. */
4751 haystack_data = ensure_contiguous(haystack_tvb, 0, -1);
4752 needle_data = ensure_contiguous(needle_tvb, 0, -1);
4753
4754 check_offset_length(haystack_tvb, haystack_offset, -1,
4755 &haystack_abs_offset, &haystack_abs_length);
4756
4757 location = ws_memmem(haystack_data + haystack_abs_offset, haystack_abs_length,
4758 needle_data, needle_len);
4759
4760 if (location) {
4761 return (int) (location - haystack_data);
4762 }
4763
4764 return -1;
4765}
4766
4767int
4768tvb_raw_offset(tvbuff_t *tvb)
4769{
4770 return ((tvb->raw_offset==-1) ? (tvb->raw_offset = tvb_offset_from_real_beginning(tvb)) : tvb->raw_offset);
4771}
4772
4773void
4774tvb_set_fragment(tvbuff_t *tvb)
4775{
4776 tvb->flags |= TVBUFF_FRAGMENT0x00000001;
4777}
4778
4779struct tvbuff *
4780tvb_get_ds_tvb(tvbuff_t *tvb)
4781{
4782 return(tvb->ds_tvb);
4783}
4784
4785unsigned
4786tvb_get_varint(tvbuff_t *tvb, unsigned offset, unsigned maxlen, uint64_t *value, const unsigned encoding)
4787{
4788 *value = 0;
4789
4790 switch (encoding & ENC_VARINT_MASK(0x00000002|0x00000004|0x00000008|0x00000010)) {
4791 case ENC_VARINT_PROTOBUF0x00000002:
4792 {
4793 unsigned i;
4794 uint64_t b; /* current byte */
4795
4796 for (i = 0; ((i < FT_VARINT_MAX_LEN10) && (i < maxlen)); ++i) {
4797 b = tvb_get_uint8(tvb, offset++);
4798 *value |= ((b & 0x7F) << (i * 7)); /* add lower 7 bits to val */
4799
4800 if (b < 0x80) {
4801 /* end successfully becauseof last byte's msb(most significant bit) is zero */
4802 return i + 1;
4803 }
4804 }
4805 break;
4806 }
4807
4808 case ENC_VARINT_ZIGZAG0x00000008:
4809 {
4810 unsigned i;
4811 uint64_t b; /* current byte */
4812
4813 for (i = 0; ((i < FT_VARINT_MAX_LEN10) && (i < maxlen)); ++i) {
4814 b = tvb_get_uint8(tvb, offset++);
4815 *value |= ((b & 0x7F) << (i * 7)); /* add lower 7 bits to val */
4816
4817 if (b < 0x80) {
4818 /* end successfully becauseof last byte's msb(most significant bit) is zero */
4819 *value = (*value >> 1) ^ ((*value & 1) ? -1 : 0);
4820 return i + 1;
4821 }
4822 }
4823 break;
4824 }
4825
4826 case ENC_VARINT_SDNV0x00000010:
4827 {
4828 /* Decodes similar to protobuf but in MSByte order */
4829 unsigned i;
4830 uint64_t b; /* current byte */
4831
4832 for (i = 0; ((i < FT_VARINT_MAX_LEN10) && (i < maxlen)); ++i) {
4833 b = tvb_get_uint8(tvb, offset++);
4834 if ((i == 9) && (*value >= UINT64_C(1)1UL<<(64-7))) {
4835 // guaranteed overflow, not valid SDNV
4836 return 0;
4837 }
4838 *value <<= 7;
4839 *value |= (b & 0x7F); /* add lower 7 bits to val */
4840
4841 if (b < 0x80) {
4842 /* end successfully because of last byte's msb(most significant bit) is zero */
4843 return i + 1;
4844 }
4845 }
4846 break;
4847 }
4848
4849 case ENC_VARINT_QUIC0x00000004:
4850 {
4851 /* calculate variable length */
4852 *value = tvb_get_uint8(tvb, offset);
4853 switch((*value) >> 6) {
4854 case 0: /* 0b00 => 1 byte length (6 bits Usable) */
4855 (*value) &= 0x3F;
4856 return 1;
4857 case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
4858 *value = tvb_get_ntohs(tvb, offset) & 0x3FFF;
4859 return 2;
4860 case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
4861 *value = tvb_get_ntohl(tvb, offset) & 0x3FFFFFFF;
4862 return 4;
4863 case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
4864 *value = tvb_get_ntoh64(tvb, offset) & UINT64_C(0x3FFFFFFFFFFFFFFF)0x3FFFFFFFFFFFFFFFUL;
4865 return 8;
4866 default: /* No Possible */
4867 ws_assert_not_reached()ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/tvbuff.c", 4867,
__func__, "assertion \"not reached\" failed")
;
4868 break;
4869 }
4870 break;
4871 }
4872
4873 default:
4874 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/tvbuff.c", 4874))
;
4875 }
4876
4877 return 0; /* 10 bytes scanned, but no bytes' msb is zero */
4878}
4879
4880/*
4881 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4882 *
4883 * Local variables:
4884 * c-basic-offset: 8
4885 * tab-width: 8
4886 * indent-tabs-mode: t
4887 * End:
4888 *
4889 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4890 * :indentSize=8:tabSize=8:noTabs=false:
4891 */