3 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
18 #include <wsutil/glib-compat.h>
22 #define ZLIB_PREFIX(x) zng_ ## x
24 typedef zng_stream zlib_stream
;
28 #define ZLIB_PREFIX(x) x
30 typedef z_stream zlib_stream
;
31 #endif /* HAVE_ZLIB */
35 #include <wsutil/wslog.h>
37 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
39 * Uncompresses a zlib compressed packet inside a message of tvb at offset with
40 * length comprlen. Returns an uncompressed tvbuffer if uncompression
41 * succeeded or NULL if uncompression failed.
43 #define TVB_Z_MIN_BUFSIZ 32768
44 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
47 tvb_uncompress_zlib(tvbuff_t
*tvb
, const int offset
, int comprlen
)
50 unsigned bytes_out
= 0;
52 uint8_t *uncompr
= NULL
;
53 tvbuff_t
*uncompr_tvb
= NULL
;
60 unsigned inits_done
= 0;
61 int wbits
= MAX_WBITS
;
64 unsigned inflate_passes
= 0;
65 unsigned bytes_in
= tvb_captured_length_remaining(tvb
, offset
);
67 if (tvb
== NULL
|| comprlen
<= 0) {
71 compr
= (uint8_t *)tvb_memdup(NULL
, tvb
, offset
, comprlen
);
77 * Assume that the uncompressed data is at least twice as big as
78 * the compressed size.
80 bufsiz
= tvb_captured_length_remaining(tvb
, offset
) * 2;
81 bufsiz
= CLAMP(bufsiz
, TVB_Z_MIN_BUFSIZ
, TVB_Z_MAX_BUFSIZ
);
83 ws_debug("bufsiz: %u bytes\n", bufsiz
);
87 strm
= g_new0(zlib_stream
, 1);
89 strm
->avail_in
= comprlen
;
91 strmbuf
= (Bytef
*)g_malloc0(bufsiz
);
92 strm
->next_out
= strmbuf
;
93 strm
->avail_out
= bufsiz
;
95 err
= ZLIB_PREFIX(inflateInit2
)(strm
, wbits
);
98 ZLIB_PREFIX(inflateEnd
)(strm
);
100 wmem_free(NULL
, compr
);
106 memset(strmbuf
, '\0', bufsiz
);
107 strm
->next_out
= strmbuf
;
108 strm
->avail_out
= bufsiz
;
110 err
= ZLIB_PREFIX(inflate
)(strm
, Z_SYNC_FLUSH
);
112 if (err
== Z_OK
|| err
== Z_STREAM_END
) {
113 unsigned bytes_pass
= bufsiz
- strm
->avail_out
;
117 if (uncompr
== NULL
) {
119 * This is ugly workaround for bug #6480
120 * (https://gitlab.com/wireshark/wireshark/-/issues/6480)
122 * g_memdup2(..., 0) returns NULL (g_malloc(0) also)
123 * when uncompr is NULL logic below doesn't create tvb
124 * which is later interpreted as decompression failed.
126 uncompr
= (uint8_t *)((bytes_pass
|| err
!= Z_STREAM_END
) ?
127 g_memdup2(strmbuf
, bytes_pass
) :
130 uncompr
= (uint8_t *)g_realloc(uncompr
, bytes_out
+ bytes_pass
);
131 memcpy(uncompr
+ bytes_out
, strmbuf
, bytes_pass
);
134 bytes_out
+= bytes_pass
;
136 if (err
== Z_STREAM_END
) {
137 ZLIB_PREFIX(inflateEnd
)(strm
);
142 } else if (err
== Z_BUF_ERROR
) {
144 * It's possible that not enough frames were captured
145 * to decompress this fully, so return what we've done
148 ZLIB_PREFIX(inflateEnd
)(strm
);
152 if (uncompr
!= NULL
) {
155 wmem_free(NULL
, compr
);
159 } else if (err
== Z_DATA_ERROR
&& inits_done
== 1
160 && uncompr
== NULL
&& comprlen
>= 2 &&
161 (*compr
== 0x1f) && (*(compr
+ 1) == 0x8b)) {
163 * inflate() is supposed to handle both gzip and deflate
164 * streams automatically, but in reality it doesn't
165 * seem to handle either (at least not within the
166 * context of an HTTP response.) We have to try
167 * several tweaks, depending on the type of data and
168 * version of the library installed.
172 * Gzip file format. Skip past the header, since the
173 * fix to make it work (setting windowBits to 31)
174 * doesn't work with all versions of the library.
176 Bytef
*c
= compr
+ 2;
179 /* we read two bytes already (0x1f, 0x8b) and
180 need at least Z_DEFLATED, 1 byte flags, 4
181 bytes MTIME, 1 byte XFL, 1 byte OS */
182 if (comprlen
< 10 || *c
!= Z_DEFLATED
) {
183 ZLIB_PREFIX(inflateEnd
)(strm
);
185 wmem_free(NULL
, compr
);
194 /* Skip past the MTIME (4 bytes),
195 XFL, and OS fields (1 byte each). */
198 if (flags
& (1 << 2)) {
199 /* An Extra field is present. It
200 consists of 2 bytes xsize and xsize
202 Read byte-by-byte (least significant
203 byte first) to make sure we abort
204 cleanly when the xsize is truncated
205 after the first byte. */
208 if (c
-compr
< comprlen
) {
212 if (c
-compr
< comprlen
) {
220 if (flags
& (1 << 3)) {
221 /* A null terminated filename */
223 while ((c
- compr
) < comprlen
&& *c
!= '\0') {
230 if (flags
& (1 << 4)) {
231 /* A null terminated comment */
233 while ((c
- compr
) < comprlen
&& *c
!= '\0') {
241 if (c
- compr
> comprlen
) {
242 ZLIB_PREFIX(inflateEnd
)(strm
);
244 wmem_free(NULL
, compr
);
248 /* Drop gzip header */
249 comprlen
-= (int) (c
- compr
);
252 ZLIB_PREFIX(inflateReset
)(strm
);
253 strm
->next_in
= next
;
254 strm
->avail_in
= comprlen
;
256 ZLIB_PREFIX(inflateEnd
)(strm
);
257 ZLIB_PREFIX(inflateInit2
)(strm
, wbits
);
259 } else if (err
== Z_DATA_ERROR
&& uncompr
== NULL
&&
263 * Re-init the stream with a negative
264 * MAX_WBITS. This is necessary due to
265 * some servers (Apache) not sending
266 * the deflate header with the
267 * content-encoded response.
271 ZLIB_PREFIX(inflateReset
)(strm
);
273 strm
->next_in
= next
;
274 strm
->avail_in
= comprlen
;
276 ZLIB_PREFIX(inflateEnd
)(strm
);
277 memset(strmbuf
, '\0', bufsiz
);
278 strm
->next_out
= strmbuf
;
279 strm
->avail_out
= bufsiz
;
281 err
= ZLIB_PREFIX(inflateInit2
)(strm
, wbits
);
288 wmem_free(NULL
, compr
);
294 ZLIB_PREFIX(inflateEnd
)(strm
);
298 if (uncompr
== NULL
) {
299 wmem_free(NULL
, compr
);
307 ws_debug("inflate() total passes: %u\n", inflate_passes
);
308 ws_debug("bytes in: %u\nbytes out: %u\n\n", bytes_in
, bytes_out
);
310 if (uncompr
!= NULL
) {
311 uncompr_tvb
= tvb_new_real_data(uncompr
, bytes_out
, bytes_out
);
312 tvb_set_free_cb(uncompr_tvb
, g_free
);
314 wmem_free(NULL
, compr
);
319 tvb_uncompress_zlib(tvbuff_t
*tvb _U_
, const int offset _U_
, int comprlen _U_
)
326 tvb_child_uncompress_zlib(tvbuff_t
*parent
, tvbuff_t
*tvb
, const int offset
, int comprlen
)
328 tvbuff_t
*new_tvb
= tvb_uncompress_zlib(tvb
, offset
, comprlen
);
330 tvb_set_child_real_data_tvbuff (parent
, new_tvb
);
335 tvb_uncompress(tvbuff_t
*tvb
, const int offset
, int comprlen
)
337 return tvb_uncompress_zlib(tvb
, offset
, comprlen
);
341 tvb_child_uncompress(tvbuff_t
*parent
, tvbuff_t
*tvb
, const int offset
, int comprlen
)
343 return tvb_child_uncompress_zlib(parent
, tvb
, offset
, comprlen
);
347 * Editor modelines - https://www.wireshark.org/tools/modelines.html
352 * indent-tabs-mode: t
355 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
356 * :indentSize=8:tabSize=8:noTabs=false: