summaryrefslogtreecommitdiffstats
path: root/epan/tvbuff_zstd.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/tvbuff_zstd.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/tvbuff_zstd.c')
-rw-r--r--epan/tvbuff_zstd.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/epan/tvbuff_zstd.c b/epan/tvbuff_zstd.c
new file mode 100644
index 0000000..0ce65c0
--- /dev/null
+++ b/epan/tvbuff_zstd.c
@@ -0,0 +1,110 @@
+/* tvbuff_zstd.c
+ * Copyright 2022, Kevin Albertson <kevin.eric.albertson [AT] gmail.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+ * Decompress ZSTD: http://facebook.github.io/zstd/
+ */
+
+#include "config.h"
+
+#ifdef HAVE_ZSTD
+#include <zstd.h>
+#endif
+
+#include "proto.h" // DISSECTOR_ASSERT_HINT
+#include "tvbuff.h"
+
+#include "tvbuff-int.h" // tvb_add_to_chain
+
+#define MAX_LOOP_ITERATIONS 100
+
+tvbuff_t *tvb_uncompress_zstd(tvbuff_t *tvb, const int offset, int comprlen)
+{
+#ifndef HAVE_ZSTD
+ // Cast to void to silence unused warnings.
+ (void)tvb;
+ (void)offset;
+ (void)comprlen;
+ return NULL;
+#else
+ ZSTD_inBuffer input = {tvb_memdup(NULL, tvb, offset, comprlen), comprlen, 0};
+ ZSTD_DStream *zds = ZSTD_createDStream();
+ size_t rc = 0;
+ uint8_t *uncompr = NULL;
+ size_t uncompr_len = 0;
+ bool ok = false;
+ int count = 0;
+
+ // ZSTD does not consume the last byte of the frame until it has flushed all of the decompressed data of the frame.
+ // Therefore, loop while there is more input.
+ ZSTD_outBuffer output = {g_malloc(ZSTD_DStreamOutSize()), ZSTD_DStreamOutSize(), 0};
+ while (input.pos < input.size && count < MAX_LOOP_ITERATIONS)
+ {
+ rc = ZSTD_decompressStream(zds, &output, &input);
+ if (ZSTD_isError(rc))
+ {
+ goto end;
+ }
+
+ if (output.pos > 0)
+ {
+ if (!uncompr)
+ {
+ DISSECTOR_ASSERT (uncompr_len == 0);
+ uncompr = g_malloc(output.pos);
+ } else {
+ uncompr = g_realloc(uncompr, uncompr_len + output.pos);
+ }
+ memcpy (uncompr + uncompr_len, output.dst, output.pos);
+ uncompr_len += output.pos;
+ // Reset the output buffer.
+ output.pos = 0;
+ }
+ count++;
+ DISSECTOR_ASSERT_HINT(count < MAX_LOOP_ITERATIONS, "MAX_LOOP_ITERATIONS exceeded");
+ }
+ if (rc > 0)
+ {
+ // There is extra data that was not decompressed.
+ goto end;
+ }
+
+ ok = true;
+end:
+ g_free((void *)output.dst);
+ wmem_free(NULL, (void *)input.src);
+ ZSTD_freeDStream(zds);
+ if (ok)
+ {
+ tvbuff_t *uncompr_tvb;
+ uncompr_tvb = tvb_new_real_data (uncompr, (guint)uncompr_len, (guint)uncompr_len);
+ tvb_set_free_cb (uncompr_tvb, g_free);
+ return uncompr_tvb;
+ }
+
+ if (uncompr)
+ {
+ g_free (uncompr);
+ }
+
+ return NULL;
+#endif /* HAVE_ZSTD */
+}
+
+tvbuff_t *tvb_child_uncompress_zstd(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
+{
+ tvbuff_t *uncompressed = tvb_uncompress_zstd(tvb, offset, comprlen);
+ if (!uncompressed)
+ {
+ return uncompressed;
+ }
+ tvb_add_to_chain(parent, uncompressed);
+ return uncompressed;
+}