update epan/dissectors/pidl/drsuapi/drsuapi.idl from samba
[wireshark-sm.git] / epan / tvbtest.c
blobadd2380a561dfc32a4c7b3e14f3da4bd6a08c7a3
1 /* tvbtest.c
2 * Standalone program to test functionality of tvbuffs.
4 * tvbtest : tvbtest.o tvbuff.o except.o
6 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
18 #include "tvbuff.h"
19 #include "proto.h"
20 #include "exceptions.h"
21 #include "wsutil/array.h"
22 #include "wsutil/pint.h"
24 #include <ws_diag_control.h>
26 bool failed;
28 typedef struct {
29 struct {
30 uint8_t needle;
31 int offset;
32 } g8;
33 struct {
34 bool test;
35 uint16_t needle;
36 int offset;
37 } g16;
38 struct {
39 bool test;
40 ws_mempbrk_pattern pattern;
41 int offset;
42 unsigned char found_needle;
43 } mempbrk;
44 } search_test_params;
46 static bool
47 test_searches(tvbuff_t *tvb, int offset, search_test_params *sp)
49 volatile bool ex_thrown = false;
51 TRY {
52 sp->g8.offset = tvb_find_uint8(tvb, offset, -1, sp->g8.needle);
53 if (sp->g16.test) {
54 sp->g16.offset = tvb_find_uint16(tvb, offset, -1, sp->g16.needle);
56 if (sp->mempbrk.test) {
57 sp->mempbrk.offset =
58 tvb_ws_mempbrk_pattern_uint8(tvb, offset, -1,
59 &sp->mempbrk.pattern, &sp->mempbrk.found_needle);
62 CATCH_ALL {
63 ex_thrown = true;
65 ENDTRY;
66 return ex_thrown;
69 /* Tests a tvbuff against the expected pattern/length.
70 * Returns true if all tests succeeed, false if any test fails */
71 static bool
72 test(tvbuff_t *tvb, const char* name,
73 uint8_t* expected_data, unsigned expected_length, unsigned expected_reported_length)
75 unsigned length;
76 unsigned reported_length;
77 uint8_t *ptr;
78 volatile bool ex_thrown;
79 volatile uint32_t val32;
80 uint32_t expected32;
81 unsigned incr, i;
83 length = tvb_captured_length(tvb);
85 if (length != expected_length) {
86 printf("01: Failed TVB=%s Length of tvb=%u while expected length=%u\n",
87 name, length, expected_length);
88 failed = true;
89 return false;
92 reported_length = tvb_reported_length(tvb);
94 if (reported_length != expected_reported_length) {
95 printf("01: Failed TVB=%s Reported length of tvb=%u while expected reported length=%u\n",
96 name, reported_length, expected_reported_length);
97 failed = true;
98 return false;
101 /* Test boundary case. A BoundsError exception should be thrown. */
102 ex_thrown = false;
103 TRY {
104 tvb_get_ptr(tvb, 0, length + 1);
106 CATCH(BoundsError) {
107 ex_thrown = true;
109 CATCH(FragmentBoundsError) {
110 printf("02: Caught wrong exception: FragmentBoundsError\n");
112 CATCH(ReportedBoundsError) {
113 printf("02: Caught wrong exception: ReportedBoundsError\n");
115 CATCH_ALL {
116 printf("02: Caught wrong exception: %lu\n", exc->except_id.except_code);
118 ENDTRY;
120 if (!ex_thrown) {
121 printf("02: Failed TVB=%s No BoundsError when retrieving %u bytes\n",
122 name, length + 1);
123 failed = true;
124 return false;
127 /* Test boundary case with reported_length+1. A ReportedBoundsError
128 exception should be thrown. */
129 ex_thrown = false;
130 TRY {
131 tvb_get_ptr(tvb, 0, reported_length + 1);
133 CATCH(BoundsError) {
134 printf("03: Caught wrong exception: BoundsError\n");
136 CATCH(FragmentBoundsError) {
137 printf("03: Caught wrong exception: FragmentBoundsError\n");
139 CATCH(ReportedBoundsError) {
140 ex_thrown = true;
142 CATCH_ALL {
143 printf("03: Caught wrong exception: %lu\n", exc->except_id.except_code);
145 ENDTRY;
147 if (!ex_thrown) {
148 printf("03: Failed TVB=%s No ReportedBoundsError when retrieving %u bytes\n",
149 name, reported_length + 1);
150 failed = true;
151 return false;
154 /* Test boundary case. A BoundsError exception should be thrown. */
155 ex_thrown = false;
156 TRY {
157 tvb_get_ptr(tvb, -1, 2);
159 CATCH(BoundsError) {
160 ex_thrown = true;
162 CATCH(FragmentBoundsError) {
163 printf("04: Caught wrong exception: FragmentBoundsError\n");
165 CATCH(ReportedBoundsError) {
166 printf("04: Caught wrong exception: ReportedBoundsError\n");
168 CATCH_ALL {
169 printf("04: Caught wrong exception: %lu\n", exc->except_id.except_code);
171 ENDTRY;
173 if (!ex_thrown) {
174 printf("04: Failed TVB=%s No BoundsError when retrieving 2 bytes from"
175 " offset -1\n", name);
176 failed = true;
177 return false;
180 /* Test boundary case. A BoundsError exception should not be thrown. */
181 ex_thrown = false;
182 TRY {
183 tvb_get_ptr(tvb, 0, length ? 1 : 0);
185 CATCH(BoundsError) {
186 ex_thrown = true;
188 CATCH(FragmentBoundsError) {
189 printf("05: Caught wrong exception: FragmentBoundsError\n");
191 CATCH(ReportedBoundsError) {
192 printf("05: Caught wrong exception: ReportedBoundsError\n");
194 CATCH_ALL {
195 printf("05: Caught wrong exception: %lu\n", exc->except_id.except_code);
197 ENDTRY;
199 if (ex_thrown) {
200 printf("05: Failed TVB=%s BoundsError when retrieving 1 bytes from"
201 " offset 0\n", name);
202 failed = true;
203 return false;
206 /* Test boundary case. A BoundsError exception should not be thrown. */
207 ex_thrown = false;
208 TRY {
209 tvb_get_ptr(tvb, -1, length ? 1 : 0);
211 CATCH(BoundsError) {
212 ex_thrown = true;
214 CATCH(FragmentBoundsError) {
215 printf("06: Caught wrong exception: FragmentBoundsError\n");
217 CATCH(ReportedBoundsError) {
218 printf("06: Caught wrong exception: ReportedBoundsError\n");
220 CATCH_ALL {
221 printf("06: Caught wrong exception: %lu\n", exc->except_id.except_code);
223 ENDTRY;
225 if (ex_thrown) {
226 printf("06: Failed TVB=%s BoundsError when retrieving 1 bytes from"
227 " offset -1\n", name);
228 failed = true;
229 return false;
233 /* Check data at boundary. An exception should not be thrown. */
234 if (length >= 4) {
235 ex_thrown = false;
236 TRY {
237 val32 = tvb_get_ntohl(tvb, 0);
239 CATCH_ALL {
240 ex_thrown = true;
242 ENDTRY;
244 if (ex_thrown) {
245 printf("07: Failed TVB=%s Exception when retrieving "
246 "uint32_t from offset 0\n", name);
247 failed = true;
248 return false;
251 expected32 = pntoh32(expected_data);
252 if (val32 != expected32) {
253 printf("08: Failed TVB=%s uint32_t @ 0 %u != expected %u\n",
254 name, val32, expected32);
255 failed = true;
256 return false;
260 /* Check data at boundary. An exception should not be thrown. */
261 if (length >= 4) {
262 ex_thrown = false;
263 TRY {
264 val32 = tvb_get_ntohl(tvb, -4);
266 CATCH_ALL {
267 ex_thrown = true;
269 ENDTRY;
271 if (ex_thrown) {
272 printf("09: Failed TVB=%s Exception when retrieving "
273 "uint32_t from offset 0\n", name);
274 failed = true;
275 return false;
278 expected32 = pntoh32(&expected_data[length-4]);
279 if (val32 != expected32) {
280 printf("10: Failed TVB=%s uint32_t @ -4 %u != expected %u\n",
281 name, val32, expected32);
282 failed = true;
283 return false;
287 /* Sweep across data in various sized increments checking
288 * tvb_memdup() */
289 for (incr = 1; incr < length; incr++) {
290 for (i = 0; i < length - incr; i += incr) {
291 ptr = (uint8_t*)tvb_memdup(NULL, tvb, i, incr);
292 if (memcmp(ptr, &expected_data[i], incr) != 0) {
293 printf("11: Failed TVB=%s Offset=%u Length=%u "
294 "Bad memdup\n",
295 name, i, incr);
296 failed = true;
297 wmem_free(NULL, ptr);
298 return false;
300 wmem_free(NULL, ptr);
304 /* One big memdup */
305 ptr = (uint8_t*)tvb_memdup(NULL, tvb, 0, -1);
306 if ((length != 0 && memcmp(ptr, expected_data, length) != 0) ||
307 (length == 0 && ptr != NULL)) {
308 printf("12: Failed TVB=%s Offset=0 Length=-1 "
309 "Bad memdup\n", name);
310 failed = true;
311 wmem_free(NULL, ptr);
312 return false;
314 wmem_free(NULL, ptr);
316 /* Test some searches.
317 * For now, just do a few trivial searches with easily verifiable
318 * results... each of the searches is expected to find their target at
319 * the offset from which the search commences. Walk through the tvb
320 * and run these tests at each byte position. */
321 for (i = 0; i < length; i++) {
322 search_test_params sp;
324 memset(&sp, 0, sizeof sp);
326 /* Search for the uint8_t at this offset. */
327 sp.g8.needle = expected_data[i];
329 /* If at least two bytes left, search for the uint16_t at this offset. */
330 sp.g16.test = length - i > 1;
331 if (sp.g16.test) {
332 sp.g16.needle = (expected_data[i] << 8) | expected_data[i + 1];
335 /* If the uint8_t at this offset is nonzero, try
336 * tvb_ws_mempbrk_pattern_uint8 as well.
337 * ws_mempbrk_compile("\0") is not effective... */
338 sp.mempbrk.test = expected_data[i] != 0;
339 if (sp.mempbrk.test) {
340 char pattern_string[2] = {expected_data[i], '\0'};
342 ws_mempbrk_compile(&sp.mempbrk.pattern, pattern_string);
345 ex_thrown = test_searches(tvb, i, &sp);
346 if (ex_thrown) {
347 printf("13: Failed TVB=%s Exception when searching, offset %d\n",
348 name, i);
349 failed = true;
350 return false;
352 if ((unsigned)sp.g8.offset != i) {
353 printf("13: Failed TVB=%s Wrong offset for uint8_t:%02x,"
354 " got %d, expected %d\n",
355 name, sp.g8.needle, sp.g8.offset, i);
356 failed = true;
357 return false;
359 if (sp.g16.test && (unsigned)sp.g16.offset != i) {
360 printf("13: Failed TVB=%s Wrong offset for uint16_t:%04x,"
361 " got %d, expected %d\n",
362 name, sp.g16.needle, sp.g16.offset, i);
363 failed = true;
364 return false;
366 if (sp.mempbrk.test && (unsigned)sp.mempbrk.offset != i) {
367 printf("13: Failed TVB=%s Wrong offset for mempbrk:%02x,"
368 " got %d, expected %d\n",
369 name, expected_data[i], sp.mempbrk.offset, i);
370 failed = true;
371 return false;
373 if (sp.mempbrk.test && sp.mempbrk.found_needle != expected_data[i]) {
374 printf("13: Failed TVB=%s Wrong needle found for mempbrk:%02x,"
375 " got %02x, expected %02x\n",
376 name, expected_data[i], sp.mempbrk.found_needle, expected_data[i]);
377 failed = true;
378 return false;
383 printf("Passed TVB=%s\n", name);
385 return true;
388 static void
389 run_tests(void)
391 int i, j;
393 tvbuff_t *tvb_parent;
394 tvbuff_t *tvb_empty;
395 tvbuff_t *tvb_small[3];
396 tvbuff_t *tvb_large[3];
397 tvbuff_t *tvb_subset[6];
398 tvbuff_t *tvb_empty_subset;
399 uint8_t *small[3];
400 unsigned small_length[3];
401 unsigned small_reported_length[3];
402 uint8_t *large[3];
403 unsigned large_length[3];
404 unsigned large_reported_length[3];
405 uint8_t *subset[6];
406 unsigned subset_length[6];
407 unsigned subset_reported_length[6];
408 uint8_t temp;
409 uint8_t *comp[6];
410 tvbuff_t *tvb_comp[6];
411 unsigned comp_length[6];
412 unsigned comp_reported_length[6];
413 tvbuff_t *tvb_comp_subset;
414 unsigned comp_subset_length;
415 unsigned comp_subset_reported_length;
416 uint8_t *comp_subset;
417 int len;
419 tvb_parent = tvb_new_real_data((const uint8_t*)"", 0, 0);
420 for (i = 0; i < 3; i++) {
421 small[i] = g_new(uint8_t, 16);
423 temp = 16 * i;
424 for (j = 0; j < 16; j++) {
425 small[i][j] = temp + j;
427 small_length[i] = 16;
428 small_reported_length[i] = 17;
429 tvb_small[i] = tvb_new_child_real_data(tvb_parent, small[i], 16, 17);
430 tvb_set_free_cb(tvb_small[i], g_free);
433 for (i = 0; i < 3; i++) {
434 large[i] = g_new(uint8_t, 19);
436 temp = 19 * i;
437 for (j = 0; j < 19; j++) {
438 large[i][j] = temp + j;
441 large_length[i] = 19;
442 large_reported_length[i] = 20;
443 tvb_large[i] = tvb_new_child_real_data(tvb_parent, large[i], 19, 20);
444 tvb_set_free_cb(tvb_large[i], g_free);
447 /* Test empty tvb */
448 tvb_empty = tvb_new_child_real_data(tvb_parent, NULL, 0, 1);
449 test(tvb_empty, "Empty", NULL, 0, 1);
451 /* Test the "real" tvbuff objects. */
452 test(tvb_small[0], "Small 0", small[0], small_length[0], small_reported_length[0]);
453 test(tvb_small[1], "Small 1", small[1], small_length[1], small_reported_length[1]);
454 test(tvb_small[2], "Small 2", small[2], small_length[2], small_reported_length[2]);
456 test(tvb_large[0], "Large 0", large[0], large_length[0], large_reported_length[0]);
457 test(tvb_large[1], "Large 1", large[1], large_length[1], large_reported_length[1]);
458 test(tvb_large[2], "Large 2", large[2], large_length[2], large_reported_length[2]);
460 subset_length[0] = 8;
461 subset_reported_length[0] = 9;
462 tvb_subset[0] = tvb_new_subset_length_caplen(tvb_small[0], 0, 8, 9);
463 subset[0] = &small[0][0];
465 subset_length[1] = 10;
466 subset_reported_length[1] = 11;
467 tvb_subset[1] = tvb_new_subset_length_caplen(tvb_large[0], -10, 10, 11);
468 subset[1] = &large[0][9];
470 subset_length[2] = 16;
471 subset_reported_length[2] = 17;
472 tvb_subset[2] = tvb_new_subset_length_caplen(tvb_small[1], -16, -1, 17);
473 subset[2] = &small[1][0];
475 subset_length[3] = 3;
476 subset_reported_length[3] = 4;
477 tvb_subset[3] = tvb_new_subset_length_caplen(tvb_subset[0], 0, 3, 4);
478 subset[3] = &small[0][0];
480 subset_length[4] = 5;
481 subset_reported_length[4] = 6;
482 tvb_subset[4] = tvb_new_subset_length_caplen(tvb_subset[1], -5, 5, 6);
483 subset[4] = &large[0][14];
485 subset_length[5] = 8;
486 subset_reported_length[5] = 9;
487 tvb_subset[5] = tvb_new_subset_length_caplen(tvb_subset[2], 4, 8, 9);
488 subset[5] = &small[1][4];
490 /* Test the "subset" tvbuff objects. */
491 test(tvb_subset[0], "Subset 0", subset[0], subset_length[0], subset_reported_length[0]);
492 test(tvb_subset[1], "Subset 1", subset[1], subset_length[1], subset_reported_length[1]);
493 test(tvb_subset[2], "Subset 2", subset[2], subset_length[2], subset_reported_length[2]);
494 test(tvb_subset[3], "Subset 3", subset[3], subset_length[3], subset_reported_length[3]);
495 test(tvb_subset[4], "Subset 4", subset[4], subset_length[4], subset_reported_length[4]);
496 test(tvb_subset[5], "Subset 5", subset[5], subset_length[5], subset_reported_length[5]);
498 /* Subset of an empty tvb. */
499 tvb_empty_subset = tvb_new_subset_length_caplen(tvb_empty, 0, 0, 1);
500 test(tvb_empty_subset, "Empty Subset", NULL, 0, 1);
502 /* One Real */
503 printf("Making Composite 0\n");
504 tvb_comp[0] = tvb_new_composite();
505 comp_length[0] = small_length[0];
506 comp_reported_length[0] = small_reported_length[0];
507 comp[0] = small[0];
508 tvb_composite_append(tvb_comp[0], tvb_small[0]);
509 tvb_composite_finalize(tvb_comp[0]);
511 /* Two Reals */
512 printf("Making Composite 1\n");
513 tvb_comp[1] = tvb_new_composite();
514 comp_length[1] = small_length[0] + small_length[1];
515 comp_reported_length[1] = small_reported_length[0] + small_reported_length[1];
516 comp[1] = (uint8_t*)g_malloc(comp_length[1]);
517 memcpy(comp[1], small[0], small_length[0]);
518 memcpy(&comp[1][small_length[0]], small[1], small_length[1]);
519 tvb_composite_append(tvb_comp[1], tvb_small[0]);
520 tvb_composite_append(tvb_comp[1], tvb_small[1]);
521 tvb_composite_finalize(tvb_comp[1]);
523 /* One subset */
524 printf("Making Composite 2\n");
525 tvb_comp[2] = tvb_new_composite();
526 comp_length[2] = subset_length[1];
527 comp_reported_length[2] = subset_reported_length[1];
528 comp[2] = subset[1];
529 tvb_composite_append(tvb_comp[2], tvb_subset[1]);
530 tvb_composite_finalize(tvb_comp[2]);
532 /* Two subsets */
533 printf("Making Composite 3\n");
534 tvb_comp[3] = tvb_new_composite();
535 comp_length[3] = subset_length[4] + subset_length[5];
536 comp_reported_length[3] = subset_reported_length[4] + subset_reported_length[5];
537 comp[3] = (uint8_t*)g_malloc(comp_length[3]);
538 memcpy(comp[3], subset[4], subset_length[4]);
539 memcpy(&comp[3][subset_length[4]], subset[5], subset_length[5]);
540 tvb_composite_append(tvb_comp[3], tvb_subset[4]);
541 tvb_composite_append(tvb_comp[3], tvb_subset[5]);
542 tvb_composite_finalize(tvb_comp[3]);
544 /* One real, one subset */
545 printf("Making Composite 4\n");
546 tvb_comp[4] = tvb_new_composite();
547 comp_length[4] = small_length[0] + subset_length[1];
548 comp_reported_length[4] = small_reported_length[0] + subset_reported_length[1];
549 comp[4] = (uint8_t*)g_malloc(comp_length[4]);
550 memcpy(&comp[4][0], small[0], small_length[0]);
551 memcpy(&comp[4][small_length[0]], subset[1], subset_length[1]);
552 tvb_composite_append(tvb_comp[4], tvb_small[0]);
553 tvb_composite_append(tvb_comp[4], tvb_subset[1]);
554 tvb_composite_finalize(tvb_comp[4]);
556 /* 4 composites */
557 printf("Making Composite 5\n");
558 tvb_comp[5] = tvb_new_composite();
559 comp_length[5] = comp_length[0] +
560 comp_length[1] +
561 comp_length[2] +
562 comp_length[3];
563 comp_reported_length[5] = comp_reported_length[0] +
564 comp_reported_length[1] +
565 comp_reported_length[2] +
566 comp_reported_length[3];
567 comp[5] = (uint8_t*)g_malloc(comp_length[5]);
569 len = 0;
570 memcpy(&comp[5][len], comp[0], comp_length[0]);
571 len += comp_length[0];
572 memcpy(&comp[5][len], comp[1], comp_length[1]);
573 len += comp_length[1];
574 memcpy(&comp[5][len], comp[2], comp_length[2]);
575 len += comp_length[2];
576 memcpy(&comp[5][len], comp[3], comp_length[3]);
578 tvb_composite_append(tvb_comp[5], tvb_comp[0]);
579 tvb_composite_append(tvb_comp[5], tvb_comp[1]);
580 tvb_composite_append(tvb_comp[5], tvb_comp[2]);
581 tvb_composite_append(tvb_comp[5], tvb_comp[3]);
582 tvb_composite_finalize(tvb_comp[5]);
584 /* A subset of one of the composites. */
585 tvb_comp_subset = tvb_new_subset_remaining(tvb_comp[1], 1);
586 comp_subset = &comp[1][1];
587 comp_subset_length = comp_length[1] - 1;
588 comp_subset_reported_length = comp_reported_length[1] - 1;
590 /* Test the "composite" tvbuff objects. */
591 test(tvb_comp[0], "Composite 0", comp[0], comp_length[0], comp_reported_length[0]);
592 test(tvb_comp[1], "Composite 1", comp[1], comp_length[1], comp_reported_length[1]);
593 test(tvb_comp[2], "Composite 2", comp[2], comp_length[2], comp_reported_length[2]);
594 test(tvb_comp[3], "Composite 3", comp[3], comp_length[3], comp_reported_length[3]);
595 test(tvb_comp[4], "Composite 4", comp[4], comp_length[4], comp_reported_length[4]);
596 test(tvb_comp[5], "Composite 5", comp[5], comp_length[5], comp_reported_length[5]);
598 /* Test the subset of the composite. */
599 test(tvb_comp_subset, "Subset of Composite", comp_subset, comp_subset_length, comp_subset_reported_length);
601 /* free memory. */
602 /* Don't free: comp[0] */
603 g_free(comp[1]);
604 /* Don't free: comp[2] */
605 g_free(comp[3]);
606 g_free(comp[4]);
607 g_free(comp[5]);
609 tvb_free_chain(tvb_parent); /* should free all tvb's and associated data */
612 typedef struct
614 // Raw bytes
615 int enc_len;
616 const uint8_t *enc;
617 // Varint parameters
618 int encoding;
619 int maxlen;
620 // Results
621 unsigned long expect_except;
622 uint64_t expect_val;
623 unsigned expect_len;
624 } varint_test_s;
626 DIAG_OFF_PEDANTIC
627 varint_test_s varint[] = {
628 {0, (const uint8_t *)"", 0, FT_VARINT_MAX_LEN, DissectorError, 0, 0}, // no encoding specified
629 // ENC_VARINT_PROTOBUF
630 {0, (const uint8_t *)"", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, ReportedBoundsError, 0, 0},
631 {1, (const uint8_t *)"\x00", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0, 1},
632 {1, (const uint8_t *)"\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 1, 1},
633 {1, (const uint8_t *)"\x7f", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0x7f, 1},
634 {2, (const uint8_t *)"\x80\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, UINT64_C(1)<<7, 2},
635 {1, (const uint8_t *)"\x80", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, ReportedBoundsError, 0, 0}, // truncated data
636 {2, (const uint8_t *)"\x80\x01", ENC_VARINT_PROTOBUF, 1, 0, 0, 0}, // truncated read
637 {5, (const uint8_t *)"\x80\x80\x80\x80\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, UINT64_C(1)<<28, 5},
638 {10, (const uint8_t *)"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, UINT64_C(1)<<63, 10},
639 {10, (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0xffffffffffffffff, 10},
640 {10, (const uint8_t *)"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x02", ENC_VARINT_PROTOBUF, FT_VARINT_MAX_LEN, 0, 0, 10}, // overflow
641 // ENC_VARINT_SDNV
642 {0, (const uint8_t *)"", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, ReportedBoundsError, 0, 0},
643 {1, (const uint8_t *)"\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 0, 1},
644 {1, (const uint8_t *)"\x01", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 1, 1},
645 {1, (const uint8_t *)"\x7f", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 0x7f, 1},
646 {2, (const uint8_t *)"\x81\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, UINT64_C(1)<<7, 2},
647 {1, (const uint8_t *)"\x81", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, ReportedBoundsError, 1, 0}, // truncated data
648 {2, (const uint8_t *)"\x81\x00", ENC_VARINT_SDNV, 1, 0, 1, 0}, // truncated read
649 {5, (const uint8_t *)"\x81\x80\x80\x80\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, UINT64_C(1)<<28, 5},
650 {10, (const uint8_t *)"\x81\x80\x80\x80\x80\x80\x80\x80\x80\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, UINT64_C(1)<<63, 10},
651 {10, (const uint8_t *)"\x81\xff\xff\xff\xff\xff\xff\xff\xff\x7f", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, 0xffffffffffffffff, 10},
652 {10, (const uint8_t *)"\x82\x80\x80\x80\x80\x80\x80\x80\x80\x00", ENC_VARINT_SDNV, FT_VARINT_MAX_LEN, 0, UINT64_C(1)<<57, 0}, // overflow
654 DIAG_ON_PEDANTIC
656 static void
657 varint_tests(void)
659 tvbuff_t *tvb_parent, *tvb;
660 volatile unsigned long got_ex;
661 uint64_t got_val;
662 volatile unsigned got_len;
664 tvb_parent = tvb_new_real_data((const uint8_t*)"", 0, 0);
666 for (size_t ix = 0; ix < array_length(varint); ++ix) {
667 const varint_test_s *vit = &varint[ix];
668 tvb = tvb_new_child_real_data(tvb_parent, vit->enc, vit->enc_len, vit->enc_len);
670 got_ex = 0;
671 got_val = 0;
672 got_len = 0;
673 TRY {
674 got_len = tvb_get_varint(tvb, 0, vit->maxlen, &got_val, vit->encoding);
676 CATCH_ALL {
677 got_ex = exc->except_id.except_code;
679 ENDTRY;
680 if (got_ex != vit->expect_except) {
681 printf("Failed varint #%zu with exception=%lu while expected exception=%lu\n",
682 ix, got_ex, vit->expect_except);
683 failed = true;
684 continue;
686 if (got_val != vit->expect_val) {
687 printf("Failed varint #%zu value=%" PRIu64 " while expected value=%" PRIu64 "\n",
688 ix, got_val, vit->expect_val);
689 failed = true;
690 continue;
692 if (got_len != vit->expect_len) {
693 printf("Failed varint #%zu length=%u while expected length=%u\n",
694 ix, got_len, vit->expect_len);
695 failed = true;
696 continue;
698 printf("Passed varint #%zu\n", ix);
701 tvb_free_chain(tvb_parent); /* should free all tvb's and associated data */
704 #define DATA_AND_LEN(X) .data = X, .len = sizeof(X) - 1
706 static void
707 zstd_tests (void) {
708 #ifdef HAVE_ZSTD
709 typedef struct {
710 const char* desc;
711 const uint8_t* data;
712 size_t len;
713 const char* expect;
714 } zstd_testcase;
716 zstd_testcase tests[] = {
718 .desc = "Uncompressing 'foobar'",
719 DATA_AND_LEN ("\x28\xb5\x2f\xfd\x20\x07\x39\x00\x00\x66\x6f\x6f\x62\x61\x72\x00"),
720 .expect = "foobar"
723 .desc = "Uncompressing invalid data",
724 DATA_AND_LEN ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"),
725 .expect = NULL
728 .desc = "Uncompressing too short length",
729 .data = "\x28\xb5\x2f\xfd\x20\x07\x39\x00\x00\x66\x6f\x6f\x62\x61\x72\x00",
730 .len = 1,
731 .expect = NULL
734 .desc = "Uncompressing two frames of data",
735 // data is two frames of compressed data with compression level 1.
736 // the first frame is the string "foo" with no null terminator.
737 // the second frame is the string "bar" with a null terminator.
738 DATA_AND_LEN ("\x28\xb5\x2f\xfd\x20\x03\x19\x00\x00\x66\x6f\x6f"
739 "\x28\xb5\x2f\xfd\x20\x04\x21\x00\x00\x62\x61\x72\x00"),
740 .expect = "foobar"
743 .desc = "Uncompressing two frames of data. 2nd frame has too short length.",
744 // data is two frames of compressed data with compression level 1.
745 // the first frame is the string "foo" with no null terminator.
746 // the second frame is the string "bar" with a null terminator.
747 .data ="\x28\xb5\x2f\xfd\x20\x03\x19\x00\x00\x66\x6f\x6f"
748 "\x28\xb5\x2f\xfd\x20\x04\x21\x00\x00\x62\x61\x72\x00",
749 .len = 13,
750 .expect = NULL
753 .desc = "Uncompressing two frames of data. 2nd frame is malformed.",
754 // data is two frames of compressed data with compression level 1.
755 // the first frame is the string "foo" with no null terminator.
756 // the second frame is malformed.
757 DATA_AND_LEN ("\x28\xb5\x2f\xfd\x20\x03\x19\x00\x00\x66\x6f\x6f"
758 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"),
759 .expect = NULL
762 .desc = "Uncompressing no data",
763 .data = "\0",
764 .len = 0,
765 .expect = ""
770 for (size_t i = 0; i < array_length(tests); i++) {
771 zstd_testcase *t = tests + i;
773 printf ("ZSTD test: %s ... begin\n", t->desc);
775 tvbuff_t *tvb = tvb_new_real_data (t->data, (const unsigned) t->len, (const unsigned) t->len);
776 tvbuff_t *got = tvb_uncompress_zstd (tvb, 0, (int) t->len);
777 if (!t->expect) {
778 if (got) {
779 fprintf (stderr, "ZSTD test: %s ... FAIL: Expected error, but got non-NULL from uncompress\n", t->desc);
780 failed = true;
781 return;
783 } else {
784 if (!got) {
785 printf ("ZSTD test: %s ... FAIL: Expected success, but got NULL from uncompress.\n", t->desc);
786 failed = true;
787 return;
789 char * got_str = tvb_get_string_enc (NULL, got, 0, tvb_reported_length (got), ENC_ASCII);
790 if (0 != strcmp (got_str, t->expect)) {
791 printf ("ZSTD test: %s ... FAIL: Expected \"%s\", got \"%s\".\n", t->desc, t->expect, got_str);
792 failed = true;
793 return;
795 wmem_free (NULL, got_str);
796 tvb_free (got);
799 tvb_free (tvb);
801 printf ("ZSTD test: %s ... OK\n", t->desc);
803 #else
804 printf ("Skipping ZSTD test. ZSTD is not available.\n");
805 #endif
807 /* Note: valgrind can be used to check for tvbuff memory leaks */
809 main(void)
811 /* For valgrind: See GLib documentation: "Running GLib Applications" */
812 g_setenv("G_DEBUG", "gc-friendly", 1);
813 g_setenv("G_SLICE", "always-malloc", 1);
815 except_init();
816 run_tests();
817 varint_tests();
818 zstd_tests ();
819 except_deinit();
820 exit(failed?1:0);
824 * Editor modelines - https://www.wireshark.org/tools/modelines.html
826 * Local variables:
827 * c-basic-offset: 8
828 * tab-width: 8
829 * indent-tabs-mode: t
830 * End:
832 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
833 * :indentSize=8:tabSize=8:noTabs=false: