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_brotli.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 epan/tvbuff_brotli.c (limited to 'epan/tvbuff_brotli.c') diff --git a/epan/tvbuff_brotli.c b/epan/tvbuff_brotli.c new file mode 100644 index 0000000..3e38c65 --- /dev/null +++ b/epan/tvbuff_brotli.c @@ -0,0 +1,192 @@ +/* tvbuff_brotli.c + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include + +#include + +#include + +#ifdef HAVE_BROTLI +#include +#endif + +#include "tvbuff.h" + +#ifdef HAVE_BROTLI + +/* + * 512KiB is the buffer size used by the brotli tool, so we + * use that too. + */ +#define TVB_BROTLI_BUFSIZ (1 << 19) + +static void* +brotli_g_malloc_wrapper(void *opaque _U_, size_t size) +{ + return g_malloc(size); +} + +static void +brotli_g_free_wrapper(void *opaque _U_, void *address) +{ + g_free(address); +} + +/* + * Uncompresses a brotli compressed packet inside a message of tvb at offset with + * length comprlen. Returns an uncompressed tvbuffer if uncompression + * succeeded or NULL if uncompression failed. + */ + +tvbuff_t * +tvb_uncompress_brotli(tvbuff_t *tvb, const int offset, int comprlen) +{ + guint8 *compr; + guint8 *uncompr = NULL; + tvbuff_t *uncompr_tvb; + BrotliDecoderState *decoder; + guint8 *strmbuf; + const size_t bufsiz = TVB_BROTLI_BUFSIZ; + size_t available_in; + const guint8 *next_in; + size_t available_out; + guint8 *next_out; + size_t total_out; + guint needs_more_output; + guint finished; + + if (tvb == NULL || comprlen <= 0) { + return NULL; + } + + compr = (guint8 *)tvb_memdup(NULL, tvb, offset, comprlen); + if (compr == NULL) { + return NULL; + } + + decoder = BrotliDecoderCreateInstance( + &brotli_g_malloc_wrapper /*alloc_func*/, + &brotli_g_free_wrapper /*free_func*/, + NULL /*opaque*/); + if (decoder == NULL) { + wmem_free(NULL, compr); + return NULL; + } + strmbuf = (guint8 *)g_malloc(bufsiz); + + available_in = comprlen; + next_in = compr; + total_out = 0; + needs_more_output = 0; + finished = 0; + while (available_in > 0 || needs_more_output) { + needs_more_output = 0; + available_out = bufsiz; + next_out = strmbuf; + + BrotliDecoderResult result = BrotliDecoderDecompressStream( + decoder, &available_in, &next_in, &available_out, &next_out, &total_out); + switch (result) { + case BROTLI_DECODER_RESULT_SUCCESS: + if (available_in > 0) { + goto cleanup; + } + finished = 1; + break; + case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: + needs_more_output = 1; + break; + case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: + /* + * It's possible that not enough frames were captured + * to decompress this fully, so return what we've done + * so far, if any. + */ + break; + case BROTLI_DECODER_RESULT_ERROR: + default: + goto cleanup; + } + + /* + * Check if decompressed size is too large. + */ + if (total_out > G_MAXINT) { + goto cleanup; + } + + /* + * BrotliDecoderDecompressStream sets available_out to the number of bytes + * left unused from the buffer. But we are interested in the bytes it wrote + * to the buffer in this pass, so we calculate pass_out. + */ + size_t pass_out = bufsiz - available_out; + if (pass_out > 0) { + uncompr = (guint8 *)g_realloc(uncompr, total_out); + memcpy(uncompr + (total_out - pass_out), strmbuf, pass_out); + } + } + + if (uncompr == NULL) { + /* + * This is for the case when the validly decompressed + * length is 0. + */ + if (finished) { + uncompr = (guint8 *)g_strdup(""); + } else { + goto cleanup; + } + } + + uncompr_tvb = tvb_new_real_data((guint8 *)uncompr, (guint)total_out, (gint)total_out); + tvb_set_free_cb(uncompr_tvb, g_free); + + g_free(strmbuf); + wmem_free(NULL, compr); + BrotliDecoderDestroyInstance(decoder); + return uncompr_tvb; + +cleanup: + g_free(strmbuf); + g_free(uncompr); + wmem_free(NULL, compr); + BrotliDecoderDestroyInstance(decoder); + return NULL; +} +#else +tvbuff_t * +tvb_uncompress_brotli(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_) +{ + return NULL; +} +#endif + +tvbuff_t * +tvb_child_uncompress_brotli(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen) +{ + tvbuff_t *new_tvb = tvb_uncompress_brotli(tvb, offset, comprlen); + if (new_tvb) + tvb_set_child_real_data_tvbuff(parent, new_tvb); + return new_tvb; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ -- cgit v1.2.3