/src/suricata7/libhtp/htp/htp_decompressors.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*************************************************************************** |
2 | | * Copyright (c) 2009-2010 Open Information Security Foundation |
3 | | * Copyright (c) 2010-2013 Qualys, Inc. |
4 | | * All rights reserved. |
5 | | * |
6 | | * Redistribution and use in source and binary forms, with or without |
7 | | * modification, are permitted provided that the following conditions are |
8 | | * met: |
9 | | * |
10 | | * - Redistributions of source code must retain the above copyright |
11 | | * notice, this list of conditions and the following disclaimer. |
12 | | |
13 | | * - Redistributions in binary form must reproduce the above copyright |
14 | | * notice, this list of conditions and the following disclaimer in the |
15 | | * documentation and/or other materials provided with the distribution. |
16 | | |
17 | | * - Neither the name of the Qualys, Inc. nor the names of its |
18 | | * contributors may be used to endorse or promote products derived from |
19 | | * this software without specific prior written permission. |
20 | | * |
21 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
22 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
23 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
24 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
25 | | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
31 | | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | | ***************************************************************************/ |
33 | | |
34 | | /** |
35 | | * @file |
36 | | * @author Ivan Ristic <ivanr@webkreator.com> |
37 | | */ |
38 | | |
39 | | #include "htp_config_auto.h" |
40 | | |
41 | | #include "htp_private.h" |
42 | | |
43 | | |
44 | 0 | static void *SzAlloc(ISzAllocPtr p, size_t size) { return malloc(size); } |
45 | 0 | static void SzFree(ISzAllocPtr p, void *address) { free(address); } |
46 | | const ISzAlloc lzma_Alloc = { SzAlloc, SzFree }; |
47 | | |
48 | | |
49 | | /** |
50 | | * @brief See if the header has extensions |
51 | | * @return number of bytes to skip |
52 | | */ |
53 | | static size_t htp_gzip_decompressor_probe(const unsigned char *data, |
54 | | size_t data_len) |
55 | 26.0k | { |
56 | 26.0k | if (data_len < 4) |
57 | 1.98k | return 0; |
58 | | |
59 | 24.0k | size_t consumed = 0; |
60 | | |
61 | 24.0k | if (data[0] == 0x1f && data[1] == 0x8b && data[3] != 0) { |
62 | 7.64k | if (data[3] & (1 << 3) || data[3] & (1 << 4)) { |
63 | | /* skip past |
64 | | * - FNAME extension, which is a name ended in a NUL terminator |
65 | | * or |
66 | | * - FCOMMENT extension, which is a commend ended in a NULL terminator |
67 | | */ |
68 | | |
69 | 4.44k | size_t len; |
70 | 146k | for (len = 10; len < data_len && data[len] != '\0'; len++); |
71 | 4.44k | consumed = len + 1; |
72 | | |
73 | | //printf("skipped %u bytes for FNAME/FCOMMENT header (GZIP)\n", (uint)consumed); |
74 | | |
75 | 4.44k | } else if (data[3] & (1 << 1)) { |
76 | 2.17k | consumed = 12; |
77 | | //printf("skipped %u bytes for FHCRC header (GZIP)\n", 12); |
78 | | |
79 | 2.17k | } else { |
80 | | //printf("GZIP unknown/unsupported flags %02X\n", data[3]); |
81 | 1.02k | consumed = 10; |
82 | 1.02k | } |
83 | 7.64k | } |
84 | | |
85 | 24.0k | if (consumed > data_len) |
86 | 2.64k | return 0; |
87 | | |
88 | 21.4k | return consumed; |
89 | 24.0k | } |
90 | | |
91 | | /** |
92 | | * @brief restart the decompressor |
93 | | * @return 1 if it restarted, 0 otherwise |
94 | | */ |
95 | | static int htp_gzip_decompressor_restart(htp_decompressor_gzip_t *drec, |
96 | | const unsigned char *data, |
97 | | size_t data_len, size_t *consumed_back) |
98 | 33.1k | { |
99 | 33.1k | size_t consumed = 0; |
100 | 33.1k | int rc = 0; |
101 | | |
102 | 33.1k | if (drec->restart < 3) { |
103 | | |
104 | | // first retry with the existing type, but now consider the |
105 | | // extensions |
106 | 26.0k | if (drec->restart == 0) { |
107 | 9.33k | consumed = htp_gzip_decompressor_probe(data, data_len); |
108 | | |
109 | 9.33k | if (drec->zlib_initialized == HTP_COMPRESSION_GZIP) { |
110 | | //printf("GZIP restart, consumed %u\n", (uint)consumed); |
111 | 8.35k | rc = inflateInit2(&drec->stream, 15 + 32); |
112 | 8.35k | } else { |
113 | | //printf("DEFLATE restart, consumed %u\n", (uint)consumed); |
114 | 979 | rc = inflateInit2(&drec->stream, -15); |
115 | 979 | } |
116 | 9.33k | if (rc != Z_OK) |
117 | 0 | return 0; |
118 | | |
119 | 9.33k | goto restart; |
120 | | |
121 | | // if that still fails, try the other method we support |
122 | | |
123 | 16.7k | } else if (drec->zlib_initialized == HTP_COMPRESSION_DEFLATE) { |
124 | 7.41k | rc = inflateInit2(&drec->stream, 15 + 32); |
125 | 7.41k | if (rc != Z_OK) |
126 | 0 | return 0; |
127 | | |
128 | 7.41k | drec->zlib_initialized = HTP_COMPRESSION_GZIP; |
129 | 7.41k | consumed = htp_gzip_decompressor_probe(data, data_len); |
130 | | #if 0 |
131 | | printf("DEFLATE -> GZIP consumed %u\n", (uint)consumed); |
132 | | #endif |
133 | 7.41k | goto restart; |
134 | | |
135 | 9.31k | } else if (drec->zlib_initialized == HTP_COMPRESSION_GZIP) { |
136 | 9.31k | rc = inflateInit2(&drec->stream, -15); |
137 | 9.31k | if (rc != Z_OK) |
138 | 0 | return 0; |
139 | | |
140 | 9.31k | drec->zlib_initialized = HTP_COMPRESSION_DEFLATE; |
141 | 9.31k | consumed = htp_gzip_decompressor_probe(data, data_len); |
142 | | #if 0 |
143 | | printf("GZIP -> DEFLATE consumed %u\n", (uint)consumed); |
144 | | #endif |
145 | 9.31k | goto restart; |
146 | 9.31k | } |
147 | 26.0k | } |
148 | 7.09k | return 0; |
149 | | |
150 | 26.0k | restart: |
151 | | #if 0 |
152 | | gz_header y; |
153 | | gz_headerp x = &y; |
154 | | int res = inflateGetHeader(&drec->stream, x); |
155 | | printf("HEADER res %d x.os %d x.done %d\n", res, x->os, x->done); |
156 | | #endif |
157 | 26.0k | *consumed_back = consumed; |
158 | 26.0k | drec->restart++; |
159 | 26.0k | return 1; |
160 | 33.1k | } |
161 | | |
162 | | /** |
163 | | * Ends decompressor. |
164 | | * |
165 | | * @param[in] drec |
166 | | */ |
167 | 21.4k | static void htp_gzip_decompressor_end(htp_decompressor_gzip_t *drec) { |
168 | 21.4k | if (drec->zlib_initialized == HTP_COMPRESSION_LZMA) { |
169 | 0 | LzmaDec_Free(&drec->state, &lzma_Alloc); |
170 | 0 | drec->zlib_initialized = 0; |
171 | 21.4k | } else if (drec->zlib_initialized) { |
172 | 11.7k | inflateEnd(&drec->stream); |
173 | 11.7k | drec->zlib_initialized = 0; |
174 | 11.7k | } |
175 | 21.4k | } |
176 | | |
177 | | /** |
178 | | * Decompress a chunk of gzip-compressed data. |
179 | | * If we have more than one decompressor, call this function recursively. |
180 | | * |
181 | | * @param[in] drec |
182 | | * @param[in] d |
183 | | * @return HTP_OK on success, HTP_ERROR or some other negative integer on failure. |
184 | | */ |
185 | 546k | htp_status_t htp_gzip_decompressor_decompress(htp_decompressor_t *drec1, htp_tx_data_t *d) { |
186 | 546k | size_t consumed = 0; |
187 | 546k | int rc = 0; |
188 | 546k | htp_status_t callback_rc; |
189 | 546k | htp_decompressor_gzip_t *drec = (htp_decompressor_gzip_t*) drec1; |
190 | | |
191 | | // Pass-through the NULL chunk, which indicates the end of the stream. |
192 | | |
193 | 546k | if (drec->super.passthrough) { |
194 | 339k | htp_tx_data_t d2; |
195 | 339k | d2.tx = d->tx; |
196 | 339k | d2.data = d->data; |
197 | 339k | d2.len = d->len; |
198 | 339k | d2.is_last = d->is_last; |
199 | | |
200 | 339k | callback_rc = drec->super.callback(&d2); |
201 | 339k | if (callback_rc != HTP_OK) { |
202 | 67 | return HTP_ERROR; |
203 | 67 | } |
204 | | |
205 | 339k | return HTP_OK; |
206 | 339k | } else if (drec->zlib_initialized == HTP_COMPRESSION_OVER) { |
207 | 122k | return HTP_ERROR; |
208 | 122k | } |
209 | | |
210 | 85.1k | if (d->data == NULL) { |
211 | | // Prepare data for callback. |
212 | 2.96k | htp_tx_data_t dout; |
213 | 2.96k | dout.tx = d->tx; |
214 | | // This is last call, so output uncompressed data so far |
215 | 2.96k | dout.len = GZIP_BUF_SIZE - drec->stream.avail_out; |
216 | 2.96k | if (dout.len > 0) { |
217 | 690 | dout.data = drec->buffer; |
218 | 2.27k | } else { |
219 | 2.27k | dout.data = NULL; |
220 | 2.27k | } |
221 | 2.96k | dout.is_last = d->is_last; |
222 | 2.96k | if (drec->super.next != NULL && drec->zlib_initialized) { |
223 | 613 | return htp_gzip_decompressor_decompress(drec->super.next, &dout); |
224 | 2.35k | } else { |
225 | | // Send decompressed data to the callback. |
226 | 2.35k | callback_rc = drec->super.callback(&dout); |
227 | 2.35k | if (callback_rc != HTP_OK) { |
228 | 0 | htp_gzip_decompressor_end(drec); |
229 | 0 | return callback_rc; |
230 | 0 | } |
231 | 2.35k | } |
232 | | |
233 | 2.35k | return HTP_OK; |
234 | 2.96k | } |
235 | | |
236 | 108k | restart: |
237 | 108k | if (consumed > d->len || d->len > UINT32_MAX ) { |
238 | 0 | htp_log(d->tx->connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "GZip decompressor: consumed > d->len"); |
239 | 0 | return HTP_ERROR; |
240 | 0 | } |
241 | 108k | drec->stream.next_in = (unsigned char *) (d->data + consumed); |
242 | 108k | drec->stream.avail_in = (uint32_t) (d->len - consumed); |
243 | | |
244 | 408k | while (drec->stream.avail_in != 0) { |
245 | | // If there's no more data left in the |
246 | | // buffer, send that information out. |
247 | 365k | if (drec->stream.avail_out == 0) { |
248 | 259k | drec->crc = crc32(drec->crc, drec->buffer, GZIP_BUF_SIZE); |
249 | | |
250 | | // Prepare data for callback. |
251 | 259k | htp_tx_data_t d2; |
252 | 259k | d2.tx = d->tx; |
253 | 259k | d2.data = drec->buffer; |
254 | 259k | d2.len = GZIP_BUF_SIZE; |
255 | 259k | d2.is_last = d->is_last; |
256 | | |
257 | 259k | if (drec->super.next != NULL && drec->zlib_initialized) { |
258 | 5.99k | callback_rc = htp_gzip_decompressor_decompress(drec->super.next, &d2); |
259 | 253k | } else { |
260 | | // Send decompressed data to callback. |
261 | 253k | callback_rc = drec->super.callback(&d2); |
262 | 253k | } |
263 | 259k | if (callback_rc != HTP_OK) { |
264 | 1.39k | htp_gzip_decompressor_end(drec); |
265 | 1.39k | return callback_rc; |
266 | 1.39k | } |
267 | | |
268 | 257k | drec->stream.next_out = drec->buffer; |
269 | 257k | drec->stream.avail_out = GZIP_BUF_SIZE; |
270 | 257k | } |
271 | | |
272 | 363k | if (drec->zlib_initialized == HTP_COMPRESSION_LZMA) { |
273 | 0 | if (drec->header_len < LZMA_PROPS_SIZE + 8) { |
274 | 0 | consumed = LZMA_PROPS_SIZE + 8 - drec->header_len; |
275 | 0 | if (consumed > drec->stream.avail_in) { |
276 | 0 | consumed = drec->stream.avail_in; |
277 | 0 | } |
278 | 0 | memcpy(drec->header + drec->header_len, drec->stream.next_in, consumed); |
279 | 0 | drec->stream.next_in = (unsigned char *) (d->data + consumed); |
280 | 0 | drec->stream.avail_in = (uint32_t) (d->len - consumed); |
281 | 0 | drec->header_len += consumed; |
282 | 0 | } |
283 | 0 | if (drec->header_len == LZMA_PROPS_SIZE + 8) { |
284 | 0 | rc = LzmaDec_Allocate(&drec->state, drec->header, LZMA_PROPS_SIZE, &lzma_Alloc); |
285 | 0 | if (rc != SZ_OK) |
286 | 0 | return rc; |
287 | 0 | LzmaDec_Init(&drec->state); |
288 | | // hacky to get to next step end retry allocate in case of failure |
289 | 0 | drec->header_len++; |
290 | 0 | } |
291 | 0 | if (drec->header_len > LZMA_PROPS_SIZE + 8) { |
292 | 0 | size_t inprocessed = drec->stream.avail_in; |
293 | 0 | size_t outprocessed = drec->stream.avail_out; |
294 | 0 | ELzmaStatus status; |
295 | 0 | rc = LzmaDec_DecodeToBuf(&drec->state, drec->stream.next_out, &outprocessed, |
296 | 0 | drec->stream.next_in, &inprocessed, LZMA_FINISH_ANY, &status, d->tx->cfg->lzma_memlimit); |
297 | 0 | drec->stream.avail_in -= inprocessed; |
298 | 0 | drec->stream.next_in += inprocessed; |
299 | 0 | drec->stream.avail_out -= outprocessed; |
300 | 0 | drec->stream.next_out += outprocessed; |
301 | 0 | switch (rc) { |
302 | 0 | case SZ_OK: |
303 | 0 | rc = Z_OK; |
304 | 0 | if (status == LZMA_STATUS_FINISHED_WITH_MARK) { |
305 | 0 | rc = Z_STREAM_END; |
306 | 0 | } |
307 | 0 | break; |
308 | 0 | case SZ_ERROR_MEM: |
309 | 0 | htp_log(d->tx->connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "LZMA decompressor: memory limit reached"); |
310 | | // fall through |
311 | 0 | default: |
312 | 0 | rc = Z_DATA_ERROR; |
313 | 0 | } |
314 | 0 | } |
315 | 363k | } else if (drec->zlib_initialized) { |
316 | 356k | rc = inflate(&drec->stream, Z_NO_FLUSH); |
317 | 356k | } else { |
318 | | // no initialization means previous error on stream |
319 | 7.30k | return HTP_ERROR; |
320 | 7.30k | } |
321 | 356k | int error_after_data = (rc == Z_DATA_ERROR && drec->restart == 0 && GZIP_BUF_SIZE > drec->stream.avail_out); |
322 | 356k | if (rc == Z_STREAM_END || error_after_data) { |
323 | | // How many bytes do we have? |
324 | 23.4k | size_t len = GZIP_BUF_SIZE - drec->stream.avail_out; |
325 | | |
326 | | // Update CRC |
327 | | |
328 | | // Prepare data for the callback. |
329 | 23.4k | htp_tx_data_t d2; |
330 | 23.4k | d2.tx = d->tx; |
331 | 23.4k | d2.data = drec->buffer; |
332 | 23.4k | d2.len = len; |
333 | 23.4k | d2.is_last = d->is_last; |
334 | | |
335 | 23.4k | if (drec->super.next != NULL && drec->zlib_initialized) { |
336 | 14.2k | callback_rc = htp_gzip_decompressor_decompress(drec->super.next, &d2); |
337 | 14.2k | } else { |
338 | | // Send decompressed data to the callback. |
339 | 9.21k | callback_rc = drec->super.callback(&d2); |
340 | 9.21k | } |
341 | 23.4k | if (callback_rc != HTP_OK) { |
342 | 1.13k | htp_gzip_decompressor_end(drec); |
343 | 1.13k | return callback_rc; |
344 | 1.13k | } |
345 | 22.3k | drec->stream.avail_out = GZIP_BUF_SIZE; |
346 | 22.3k | drec->stream.next_out = drec->buffer; |
347 | | // TODO Handle trailer. |
348 | | |
349 | 22.3k | if (error_after_data) { |
350 | | // There is data even if there is an error |
351 | | // So use this data and log a warning |
352 | 3.53k | htp_log(d->tx->connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "GZip decompressor: inflate failed with %d", rc); |
353 | 3.53k | if (drec->zlib_initialized == HTP_COMPRESSION_LZMA) { |
354 | 0 | LzmaDec_Free(&drec->state, &lzma_Alloc); |
355 | 0 | } |
356 | 3.53k | drec->zlib_initialized = HTP_COMPRESSION_OVER; |
357 | 3.53k | return HTP_ERROR; |
358 | 3.53k | } |
359 | 18.7k | return HTP_OK; |
360 | 22.3k | } |
361 | 333k | else if (rc != Z_OK) { |
362 | 33.1k | htp_log(d->tx->connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "GZip decompressor: inflate failed with %d", rc); |
363 | 33.1k | if (drec->zlib_initialized == HTP_COMPRESSION_LZMA) { |
364 | 0 | LzmaDec_Free(&drec->state, &lzma_Alloc); |
365 | | // so as to clean zlib ressources after restart |
366 | 0 | drec->zlib_initialized = HTP_COMPRESSION_NONE; |
367 | 33.1k | } else { |
368 | 33.1k | inflateEnd(&drec->stream); |
369 | 33.1k | } |
370 | | |
371 | | // see if we want to restart the decompressor |
372 | 33.1k | if (htp_gzip_decompressor_restart(drec, |
373 | 33.1k | d->data, d->len, &consumed) == 1) |
374 | 26.0k | { |
375 | | // we'll be restarting the compressor |
376 | 26.0k | goto restart; |
377 | 26.0k | } |
378 | | |
379 | 7.09k | drec->zlib_initialized = 0; |
380 | | |
381 | | // all our inflate attempts have failed, simply |
382 | | // pass the raw data on to the callback in case |
383 | | // it's not compressed at all |
384 | | |
385 | 7.09k | htp_tx_data_t d2; |
386 | 7.09k | d2.tx = d->tx; |
387 | 7.09k | d2.data = d->data; |
388 | 7.09k | d2.len = d->len; |
389 | 7.09k | d2.is_last = d->is_last; |
390 | | |
391 | 7.09k | callback_rc = drec->super.callback(&d2); |
392 | 7.09k | if (callback_rc != HTP_OK) { |
393 | 10 | return HTP_ERROR; |
394 | 10 | } |
395 | | |
396 | 7.08k | drec->stream.avail_out = GZIP_BUF_SIZE; |
397 | 7.08k | drec->stream.next_out = drec->buffer; |
398 | | |
399 | | /* successfully passed through, lets continue doing that */ |
400 | 7.08k | drec->super.passthrough = 1; |
401 | 7.08k | return HTP_OK; |
402 | 7.09k | } |
403 | 356k | } |
404 | | |
405 | 42.9k | return HTP_OK; |
406 | 108k | } |
407 | | |
408 | | /** |
409 | | * Shut down gzip decompressor. |
410 | | * |
411 | | * @param[in] drec |
412 | | */ |
413 | 18.8k | void htp_gzip_decompressor_destroy(htp_decompressor_t *drec1) { |
414 | 18.8k | htp_decompressor_gzip_t *drec = (htp_decompressor_gzip_t*) drec1; |
415 | 18.8k | if (drec == NULL) return; |
416 | | |
417 | 18.8k | htp_gzip_decompressor_end(drec); |
418 | | |
419 | 18.8k | free(drec->buffer); |
420 | 18.8k | free(drec); |
421 | 18.8k | } |
422 | | |
423 | | /** |
424 | | * Create a new decompressor instance. |
425 | | * |
426 | | * @param[in] connp |
427 | | * @param[in] format |
428 | | * @return New htp_decompressor_t instance on success, or NULL on failure. |
429 | | */ |
430 | 18.8k | htp_decompressor_t *htp_gzip_decompressor_create(htp_connp_t *connp, enum htp_content_encoding_t format) { |
431 | 18.8k | htp_decompressor_gzip_t *drec = calloc(1, sizeof (htp_decompressor_gzip_t)); |
432 | 18.8k | if (drec == NULL) return NULL; |
433 | | |
434 | 18.8k | drec->super.decompress = NULL; |
435 | 18.8k | drec->super.destroy = NULL; |
436 | 18.8k | drec->super.next = NULL; |
437 | | |
438 | 18.8k | drec->buffer = malloc(GZIP_BUF_SIZE); |
439 | 18.8k | if (drec->buffer == NULL) { |
440 | 0 | free(drec); |
441 | 0 | return NULL; |
442 | 0 | } |
443 | | |
444 | | // Initialize zlib. |
445 | 18.8k | int rc; |
446 | | |
447 | 18.8k | switch (format) { |
448 | 0 | case HTP_COMPRESSION_LZMA: |
449 | 0 | if (connp->cfg->lzma_memlimit > 0 && |
450 | 0 | connp->cfg->response_lzma_layer_limit > 0) { |
451 | 0 | LzmaDec_Construct(&drec->state); |
452 | 0 | } else { |
453 | 0 | htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "LZMA decompression disabled"); |
454 | 0 | drec->super.passthrough = 1; |
455 | 0 | } |
456 | 0 | rc = Z_OK; |
457 | 0 | break; |
458 | 8.19k | case HTP_COMPRESSION_DEFLATE: |
459 | | // Negative values activate raw processing, |
460 | | // which is what we need for deflate. |
461 | 8.19k | rc = inflateInit2(&drec->stream, -15); |
462 | 8.19k | break; |
463 | 10.6k | case HTP_COMPRESSION_GZIP: |
464 | | // Increased windows size activates gzip header processing. |
465 | 10.6k | rc = inflateInit2(&drec->stream, 15 + 32); |
466 | 10.6k | break; |
467 | 0 | default: |
468 | | // do nothing |
469 | 0 | rc = Z_DATA_ERROR; |
470 | 18.8k | } |
471 | | |
472 | 18.8k | if (rc != Z_OK) { |
473 | 0 | htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "GZip decompressor: inflateInit2 failed with code %d", rc); |
474 | |
|
475 | 0 | if (format == HTP_COMPRESSION_DEFLATE || format == HTP_COMPRESSION_GZIP) { |
476 | 0 | inflateEnd(&drec->stream); |
477 | 0 | } |
478 | 0 | free(drec->buffer); |
479 | 0 | free(drec); |
480 | |
|
481 | 0 | return NULL; |
482 | 0 | } |
483 | | |
484 | 18.8k | drec->zlib_initialized = format; |
485 | 18.8k | drec->stream.avail_out = GZIP_BUF_SIZE; |
486 | 18.8k | drec->stream.next_out = drec->buffer; |
487 | | |
488 | | #if 0 |
489 | | if (format == COMPRESSION_DEFLATE) { |
490 | | drec->initialized = 1; |
491 | | } |
492 | | #endif |
493 | | |
494 | 18.8k | return (htp_decompressor_t *) drec; |
495 | 18.8k | } |