ISO14443: Fix Dead Store (Dead assignement/Dead increment) Warning found by Clang
[metze/wireshark/wip.git] / epan / tvbuff_zlib.c
1 /* tvbuff_zlib.c
2  *
3  * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "config.h"
25
26 #include <glib.h>
27
28 #include <string.h>
29
30 #ifdef HAVE_LIBZ
31 #include <zlib.h>
32 #endif
33
34 #include "tvbuff.h"
35
36 #ifdef HAVE_LIBZ
37 /*
38  * Uncompresses a zlib compressed packet inside a message of tvb at offset with
39  * length comprlen.  Returns an uncompressed tvbuffer if uncompression
40  * succeeded or NULL if uncompression failed.
41  */
42 #define TVB_Z_MIN_BUFSIZ 32768
43 #define TVB_Z_MAX_BUFSIZ 1048576 * 10
44 /* #define TVB_Z_DEBUG 1 */
45 #undef TVB_Z_DEBUG
46
47 tvbuff_t *
48 tvb_uncompress(tvbuff_t *tvb, const int offset, int comprlen)
49 {
50         gint       err;
51         guint      bytes_out      = 0;
52         guint8    *compr;
53         guint8    *uncompr        = NULL;
54         tvbuff_t  *uncompr_tvb    = NULL;
55         z_streamp  strm;
56         Bytef     *strmbuf;
57         guint      inits_done     = 0;
58         gint       wbits          = MAX_WBITS;
59         guint8    *next;
60         guint      bufsiz;
61 #ifdef TVB_Z_DEBUG
62         guint      inflate_passes = 0;
63         guint      bytes_in       = tvb_captured_length_remaining(tvb, offset);
64 #endif
65
66         if (tvb == NULL) {
67                 return NULL;
68         }
69
70         compr = (guint8 *)tvb_memdup(NULL, tvb, offset, comprlen);
71
72         if (!compr)
73                 return NULL;
74
75         /*
76          * Assume that the uncompressed data is at least twice as big as
77          * the compressed size.
78          */
79         bufsiz = tvb_captured_length_remaining(tvb, offset) * 2;
80         bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
81
82 #ifdef TVB_Z_DEBUG
83         printf("bufsiz: %u bytes\n", bufsiz);
84 #endif
85
86         next = compr;
87
88         strm            = g_new0(z_stream, 1);
89         strm->next_in   = next;
90         strm->avail_in  = comprlen;
91
92         strmbuf         = (Bytef *)g_malloc0(bufsiz);
93         strm->next_out  = strmbuf;
94         strm->avail_out = bufsiz;
95
96         err = inflateInit2(strm, wbits);
97         inits_done = 1;
98         if (err != Z_OK) {
99                 inflateEnd(strm);
100                 g_free(strm);
101                 g_free(compr);
102                 g_free(strmbuf);
103                 return NULL;
104         }
105
106         while (1) {
107                 memset(strmbuf, '\0', bufsiz);
108                 strm->next_out  = strmbuf;
109                 strm->avail_out = bufsiz;
110
111                 err = inflate(strm, Z_SYNC_FLUSH);
112
113                 if (err == Z_OK || err == Z_STREAM_END) {
114                         guint bytes_pass = bufsiz - strm->avail_out;
115
116 #ifdef TVB_Z_DEBUG
117                         ++inflate_passes;
118 #endif
119
120                         if (uncompr == NULL) {
121                                 /*
122                                  * This is ugly workaround for bug #6480
123                                  * (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6480)
124                                  *
125                                  * g_memdup(..., 0) returns NULL (g_malloc(0) also)
126                                  * when uncompr is NULL logic below doesn't create tvb
127                                  * which is later interpreted as decompression failed.
128                                  */
129                                 uncompr = (guint8 *)((bytes_pass || err != Z_STREAM_END) ?
130                                                 g_memdup(strmbuf, bytes_pass) :
131                                                 g_strdup(""));
132                         } else {
133                                 guint8 *new_data = (guint8 *)g_malloc0(bytes_out + bytes_pass);
134
135                                 memcpy(new_data, uncompr, bytes_out);
136                                 memcpy(new_data + bytes_out, strmbuf, bytes_pass);
137
138                                 g_free(uncompr);
139                                 uncompr = new_data;
140                         }
141
142                         bytes_out += bytes_pass;
143
144                         if (err == Z_STREAM_END) {
145                                 inflateEnd(strm);
146                                 g_free(strm);
147                                 g_free(strmbuf);
148                                 break;
149                         }
150                 } else if (err == Z_BUF_ERROR) {
151                         /*
152                          * It's possible that not enough frames were captured
153                          * to decompress this fully, so return what we've done
154                          * so far, if any.
155                          */
156                         inflateEnd(strm);
157                         g_free(strm);
158                         g_free(strmbuf);
159
160                         if (uncompr != NULL) {
161                                 break;
162                         } else {
163                                 g_free(compr);
164                                 return NULL;
165                         }
166
167                 } else if (err == Z_DATA_ERROR && inits_done == 1
168                         && uncompr == NULL && comprlen >= 2 &&
169                         (*compr  == 0x1f) && (*(compr + 1) == 0x8b)) {
170                         /*
171                          * inflate() is supposed to handle both gzip and deflate
172                          * streams automatically, but in reality it doesn't
173                          * seem to handle either (at least not within the
174                          * context of an HTTP response.)  We have to try
175                          * several tweaks, depending on the type of data and
176                          * version of the library installed.
177                          */
178
179                         /*
180                          * Gzip file format.  Skip past the header, since the
181                          * fix to make it work (setting windowBits to 31)
182                          * doesn't work with all versions of the library.
183                          */
184                         Bytef *c = compr + 2;
185                         Bytef  flags = 0;
186
187                         /* we read two bytes already (0x1f, 0x8b) and
188                            need at least Z_DEFLATED, 1 byte flags, 4
189                            bytes MTIME, 1 byte XFL, 1 byte OS */
190                         if (comprlen < 10 || *c != Z_DEFLATED) {
191                                 inflateEnd(strm);
192                                 g_free(strm);
193                                 g_free(compr);
194                                 g_free(strmbuf);
195                                 return NULL;
196                         }
197
198                         c++;
199                         flags = *c;
200                         c++;
201
202                         /* Skip past the MTIME (4 bytes),
203                            XFL, and OS fields (1 byte each). */
204                         c += 6;
205
206                         if (flags & (1 << 2)) {
207                                 /* An Extra field is present. It
208                                    consists of 2 bytes xsize and xsize
209                                    bytes of data.
210                                    Read byte-by-byte (least significant
211                                    byte first) to make sure we abort
212                                    cleanly when the xsize is truncated
213                                    after the first byte. */
214                                 guint16 xsize = 0;
215
216                                 if (c-compr < comprlen) {
217                                         xsize += *c;
218                                         c++;
219                                 }
220                                 if (c-compr < comprlen) {
221                                         xsize += *c << 8;
222                                         c++;
223                                 }
224
225                                 c += xsize;
226                         }
227
228                         if (flags & (1 << 3)) {
229                                 /* A null terminated filename */
230
231                                 while ((c - compr) < comprlen && *c != '\0') {
232                                         c++;
233                                 }
234
235                                 c++;
236                         }
237
238                         if (flags & (1 << 4)) {
239                                 /* A null terminated comment */
240
241                                 while ((c - compr) < comprlen && *c != '\0') {
242                                         c++;
243                                 }
244
245                                 c++;
246                         }
247
248
249                         inflateReset(strm);
250                         next = c;
251                         strm->next_in = next;
252                         if (c - compr > comprlen) {
253                                 inflateEnd(strm);
254                                 g_free(strm);
255                                 g_free(compr);
256                                 g_free(strmbuf);
257                                 return NULL;
258                         }
259                         comprlen -= (int) (c - compr);
260
261                         inflateEnd(strm);
262                         inflateInit2(strm, wbits);
263                         inits_done++;
264                 } else if (err == Z_DATA_ERROR && uncompr == NULL &&
265                         inits_done <= 3) {
266
267                         /*
268                          * Re-init the stream with a negative
269                          * MAX_WBITS. This is necessary due to
270                          * some servers (Apache) not sending
271                          * the deflate header with the
272                          * content-encoded response.
273                          */
274                         wbits = -MAX_WBITS;
275
276                         inflateReset(strm);
277
278                         strm->next_in   = next;
279                         strm->avail_in  = comprlen;
280
281                         inflateEnd(strm);
282                         memset(strmbuf, '\0', bufsiz);
283                         strm->next_out  = strmbuf;
284                         strm->avail_out = bufsiz;
285
286                         err = inflateInit2(strm, wbits);
287
288                         inits_done++;
289
290                         if (err != Z_OK) {
291                                 g_free(strm);
292                                 g_free(strmbuf);
293                                 g_free(compr);
294                                 g_free(uncompr);
295
296                                 return NULL;
297                         }
298                 } else {
299                         inflateEnd(strm);
300                         g_free(strm);
301                         g_free(strmbuf);
302
303                         if (uncompr == NULL) {
304                                 g_free(compr);
305                                 return NULL;
306                         }
307
308                         break;
309                 }
310         }
311
312 #ifdef TVB_Z_DEBUG
313         printf("inflate() total passes: %u\n", inflate_passes);
314         printf("bytes  in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
315 #endif
316
317         if (uncompr != NULL) {
318                 uncompr_tvb =  tvb_new_real_data((guint8*) uncompr, bytes_out, bytes_out);
319                 tvb_set_free_cb(uncompr_tvb, g_free);
320         }
321         g_free(compr);
322         return uncompr_tvb;
323 }
324 #else
325 tvbuff_t *
326 tvb_uncompress(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
327 {
328         return NULL;
329 }
330 #endif
331
332 tvbuff_t *
333 tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
334 {
335         tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
336         if (new_tvb)
337                 tvb_set_child_real_data_tvbuff (parent, new_tvb);
338         return new_tvb;
339 }
340
341 /*
342  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
343  *
344  * Local variables:
345  * c-basic-offset: 8
346  * tab-width: 8
347  * indent-tabs-mode: t
348  * End:
349  *
350  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
351  * :indentSize=8:tabSize=8:noTabs=false:
352  */