dcerpc-netlogon: remove unused variable
[wireshark-sm.git] / epan / tvbuff_zstd.c
blob6d5fc144ec2285ac4dc58bf2c11e9504916e9bc9
1 /* tvbuff_zstd.c
2 * Copyright 2022, Kevin Albertson <kevin.eric.albertson [AT] gmail.com>
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
12 * Decompress ZSTD: http://facebook.github.io/zstd/
15 #include "config.h"
17 #ifdef HAVE_ZSTD
18 #include <zstd.h>
19 #endif
21 #include "proto.h" // DISSECTOR_ASSERT_HINT
22 #include "tvbuff.h"
24 #include "tvbuff-int.h" // tvb_add_to_chain
26 #define MAX_LOOP_ITERATIONS 100
28 tvbuff_t *tvb_uncompress_zstd(tvbuff_t *tvb, const int offset, int comprlen)
30 #ifndef HAVE_ZSTD
31 // Cast to void to silence unused warnings.
32 (void)tvb;
33 (void)offset;
34 (void)comprlen;
35 return NULL;
36 #else
37 ZSTD_inBuffer input = {tvb_memdup(NULL, tvb, offset, comprlen), comprlen, 0};
38 ZSTD_DStream *zds = ZSTD_createDStream();
39 size_t rc = 0;
40 uint8_t *uncompr = NULL;
41 size_t uncompr_len = 0;
42 bool ok = false;
43 int count = 0;
45 // ZSTD does not consume the last byte of the frame until it has flushed all of the decompressed data of the frame.
46 // Therefore, loop while there is more input.
47 ZSTD_outBuffer output = {g_malloc(ZSTD_DStreamOutSize()), ZSTD_DStreamOutSize(), 0};
48 while (input.pos < input.size && count < MAX_LOOP_ITERATIONS)
50 rc = ZSTD_decompressStream(zds, &output, &input);
51 if (ZSTD_isError(rc))
53 goto end;
56 if (output.pos > 0)
58 if (!uncompr)
60 DISSECTOR_ASSERT (uncompr_len == 0);
61 uncompr = g_malloc(output.pos);
62 } else {
63 uncompr = g_realloc(uncompr, uncompr_len + output.pos);
65 memcpy (uncompr + uncompr_len, output.dst, output.pos);
66 uncompr_len += output.pos;
67 // Reset the output buffer.
68 output.pos = 0;
70 count++;
71 DISSECTOR_ASSERT_HINT(count < MAX_LOOP_ITERATIONS, "MAX_LOOP_ITERATIONS exceeded");
73 if (rc > 0)
75 // There is extra data that was not decompressed.
76 goto end;
79 ok = true;
80 end:
81 g_free((void *)output.dst);
82 wmem_free(NULL, (void *)input.src);
83 ZSTD_freeDStream(zds);
84 if (ok)
86 tvbuff_t *uncompr_tvb;
87 uncompr_tvb = tvb_new_real_data (uncompr, (unsigned)uncompr_len, (unsigned)uncompr_len);
88 tvb_set_free_cb (uncompr_tvb, g_free);
89 return uncompr_tvb;
92 if (uncompr)
94 g_free (uncompr);
97 return NULL;
98 #endif /* HAVE_ZSTD */
101 tvbuff_t *tvb_child_uncompress_zstd(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
103 tvbuff_t *uncompressed = tvb_uncompress_zstd(tvb, offset, comprlen);
104 if (!uncompressed)
106 return uncompressed;
108 tvb_add_to_chain(parent, uncompressed);
109 return uncompressed;