From e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 22:34:10 +0200 Subject: Adding upstream version 4.2.2. Signed-off-by: Daniel Baumann --- epan/tvbuff_zstd.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 epan/tvbuff_zstd.c (limited to 'epan/tvbuff_zstd.c') 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 + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * 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 +#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; +} -- cgit v1.2.3