drsuapi_SupportedExtensionsExt
[wireshark-sm.git] / epan / tvbuff_brotli.c
blobc01f6f5bbe74e47574fef763980dfc9462b5139e
1 /* tvbuff_brotli.c
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 #include <config.h>
12 #include <glib.h>
14 #include <string.h>
16 #ifdef HAVE_BROTLI
17 #include <brotli/decode.h>
18 #endif
20 #include "tvbuff.h"
22 #ifdef HAVE_BROTLI
25 * 512KiB is the buffer size used by the brotli tool, so we
26 * use that too.
28 #define TVB_BROTLI_BUFSIZ (1 << 19)
30 static void*
31 brotli_g_malloc_wrapper(void *opaque _U_, size_t size)
33 return g_malloc(size);
36 static void
37 brotli_g_free_wrapper(void *opaque _U_, void *address)
39 g_free(address);
43 * Uncompresses a brotli compressed packet inside a message of tvb at offset with
44 * length comprlen. Returns an uncompressed tvbuffer if uncompression
45 * succeeded or NULL if uncompression failed.
48 tvbuff_t *
49 tvb_uncompress_brotli(tvbuff_t *tvb, const int offset, int comprlen)
51 uint8_t *compr;
52 uint8_t *uncompr = NULL;
53 tvbuff_t *uncompr_tvb;
54 BrotliDecoderState *decoder;
55 uint8_t *strmbuf;
56 const size_t bufsiz = TVB_BROTLI_BUFSIZ;
57 size_t available_in;
58 const uint8_t *next_in;
59 size_t available_out;
60 uint8_t *next_out;
61 size_t total_out;
62 unsigned needs_more_output;
63 unsigned finished;
65 if (tvb == NULL || comprlen <= 0) {
66 return NULL;
69 compr = (uint8_t *)tvb_memdup(NULL, tvb, offset, comprlen);
70 if (compr == NULL) {
71 return NULL;
74 decoder = BrotliDecoderCreateInstance(
75 &brotli_g_malloc_wrapper /*alloc_func*/,
76 &brotli_g_free_wrapper /*free_func*/,
77 NULL /*opaque*/);
78 if (decoder == NULL) {
79 wmem_free(NULL, compr);
80 return NULL;
82 strmbuf = (uint8_t *)g_malloc(bufsiz);
84 available_in = comprlen;
85 next_in = compr;
86 total_out = 0;
87 needs_more_output = 0;
88 finished = 0;
89 while (available_in > 0 || needs_more_output) {
90 needs_more_output = 0;
91 available_out = bufsiz;
92 next_out = strmbuf;
94 BrotliDecoderResult result = BrotliDecoderDecompressStream(
95 decoder, &available_in, &next_in, &available_out, &next_out, &total_out);
96 switch (result) {
97 case BROTLI_DECODER_RESULT_SUCCESS:
98 if (available_in > 0) {
99 goto cleanup;
101 finished = 1;
102 break;
103 case BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT:
104 needs_more_output = 1;
105 break;
106 case BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT:
108 * It's possible that not enough frames were captured
109 * to decompress this fully, so return what we've done
110 * so far, if any.
112 break;
113 case BROTLI_DECODER_RESULT_ERROR:
114 default:
115 goto cleanup;
119 * Check if decompressed size is too large.
121 if (total_out > INT_MAX) {
122 goto cleanup;
126 * BrotliDecoderDecompressStream sets available_out to the number of bytes
127 * left unused from the buffer. But we are interested in the bytes it wrote
128 * to the buffer in this pass, so we calculate pass_out.
130 size_t pass_out = bufsiz - available_out;
131 if (pass_out > 0) {
132 uncompr = (uint8_t *)g_realloc(uncompr, total_out);
133 memcpy(uncompr + (total_out - pass_out), strmbuf, pass_out);
137 if (uncompr == NULL) {
139 * This is for the case when the validly decompressed
140 * length is 0.
142 if (finished) {
143 uncompr = (uint8_t *)g_strdup("");
144 } else {
145 goto cleanup;
149 uncompr_tvb = tvb_new_real_data((uint8_t *)uncompr, (unsigned)total_out, (int)total_out);
150 tvb_set_free_cb(uncompr_tvb, g_free);
152 g_free(strmbuf);
153 wmem_free(NULL, compr);
154 BrotliDecoderDestroyInstance(decoder);
155 return uncompr_tvb;
157 cleanup:
158 g_free(strmbuf);
159 g_free(uncompr);
160 wmem_free(NULL, compr);
161 BrotliDecoderDestroyInstance(decoder);
162 return NULL;
164 #else
165 tvbuff_t *
166 tvb_uncompress_brotli(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
168 return NULL;
170 #endif
172 tvbuff_t *
173 tvb_child_uncompress_brotli(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
175 tvbuff_t *new_tvb = tvb_uncompress_brotli(tvb, offset, comprlen);
176 if (new_tvb)
177 tvb_set_child_real_data_tvbuff(parent, new_tvb);
178 return new_tvb;
182 * Editor modelines - https://www.wireshark.org/tools/modelines.html
184 * Local variables:
185 * c-basic-offset: 4
186 * tab-width: 8
187 * indent-tabs-mode: nil
188 * End:
190 * vi: set shiftwidth=4 tabstop=8 expandtab:
191 * :indentSize=4:tabSize=8:noTabs=true: