summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--epan/CMakeLists.txt1
-rw-r--r--epan/Makefile.common1
-rw-r--r--epan/tvbuff.c291
-rw-r--r--epan/tvbuff_zlib.c323
4 files changed, 325 insertions, 291 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt
index 6d16eb9db9..6dbec41b87 100644
--- a/epan/CMakeLists.txt
+++ b/epan/CMakeLists.txt
@@ -1534,6 +1534,7 @@ set(LIBWIRESHARK_FILES
tvbuff_composite.c
tvbuff_real.c
tvbuff_subset.c
+ tvbuff_zlib.c
uat.c
value_string.c
xdlc.c
diff --git a/epan/Makefile.common b/epan/Makefile.common
index 0cb1052e19..2accf5deaa 100644
--- a/epan/Makefile.common
+++ b/epan/Makefile.common
@@ -97,6 +97,7 @@ LIBWIRESHARK_SRC = \
tvbuff_composite.c \
tvbuff_real.c \
tvbuff_subset.c \
+ tvbuff_zlib.c \
tvbuff.c \
uat.c \
value_string.c \
diff --git a/epan/tvbuff.c b/epan/tvbuff.c
index a1db5f0a2e..26f5276ac0 100644
--- a/epan/tvbuff.c
+++ b/epan/tvbuff.c
@@ -39,10 +39,6 @@
#include <string.h>
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
#include "wsutil/pint.h"
#include "tvbuff.h"
#include "tvbuff-int.h"
@@ -2671,293 +2667,6 @@ tvb_find_tvb(tvbuff_t *haystack_tvb, tvbuff_t *needle_tvb, const gint haystack_o
return -1;
}
-#ifdef HAVE_LIBZ
-/*
- * Uncompresses a zlib compressed packet inside a message of tvb at offset with
- * length comprlen. Returns an uncompressed tvbuffer if uncompression
- * succeeded or NULL if uncompression failed.
- */
-#define TVB_Z_MIN_BUFSIZ 32768
-#define TVB_Z_MAX_BUFSIZ 1048576 * 10
-/* #define TVB_Z_DEBUG 1 */
-#undef TVB_Z_DEBUG
-
-tvbuff_t *
-tvb_uncompress(tvbuff_t *tvb, const int offset, int comprlen)
-{
- gint err = Z_OK;
- guint bytes_out = 0;
- guint8 *compr = NULL;
- guint8 *uncompr = NULL;
- tvbuff_t *uncompr_tvb = NULL;
- z_streamp strm = NULL;
- Bytef *strmbuf = NULL;
- guint inits_done = 0;
- gint wbits = MAX_WBITS;
- guint8 *next = NULL;
- guint bufsiz = TVB_Z_MIN_BUFSIZ;
-#ifdef TVB_Z_DEBUG
- guint inflate_passes = 0;
- guint bytes_in = tvb_length_remaining(tvb, offset);
-#endif
-
- if (tvb == NULL) {
- return NULL;
- }
-
- compr = (guint8 *)tvb_memdup(NULL, tvb, offset, comprlen);
-
- if (!compr)
- return NULL;
-
- /*
- * Assume that the uncompressed data is at least twice as big as
- * the compressed size.
- */
- bufsiz = tvb_length_remaining(tvb, offset) * 2;
- bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
-
-#ifdef TVB_Z_DEBUG
- printf("bufsiz: %u bytes\n", bufsiz);
-#endif
-
- next = compr;
-
- strm = g_new0(z_stream, 1);
- strm->next_in = next;
- strm->avail_in = comprlen;
-
- strmbuf = (Bytef *)g_malloc0(bufsiz);
- strm->next_out = strmbuf;
- strm->avail_out = bufsiz;
-
- err = inflateInit2(strm, wbits);
- inits_done = 1;
- if (err != Z_OK) {
- inflateEnd(strm);
- g_free(strm);
- g_free(compr);
- g_free(strmbuf);
- return NULL;
- }
-
- while (1) {
- memset(strmbuf, '\0', bufsiz);
- strm->next_out = strmbuf;
- strm->avail_out = bufsiz;
-
- err = inflate(strm, Z_SYNC_FLUSH);
-
- if (err == Z_OK || err == Z_STREAM_END) {
- guint bytes_pass = bufsiz - strm->avail_out;
-
-#ifdef TVB_Z_DEBUG
- ++inflate_passes;
-#endif
-
- if (uncompr == NULL) {
- /*
- * This is ugly workaround for bug #6480
- * (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6480)
- *
- * g_memdup(..., 0) returns NULL (g_malloc(0) also)
- * when uncompr is NULL logic below doesn't create tvb
- * which is later interpreted as decompression failed.
- */
- uncompr = (guint8 *)((bytes_pass || err != Z_STREAM_END) ?
- g_memdup(strmbuf, bytes_pass) :
- g_strdup(""));
- } else {
- guint8 *new_data = (guint8 *)g_malloc0(bytes_out + bytes_pass);
-
- memcpy(new_data, uncompr, bytes_out);
- memcpy(new_data + bytes_out, strmbuf, bytes_pass);
-
- g_free(uncompr);
- uncompr = new_data;
- }
-
- bytes_out += bytes_pass;
-
- if (err == Z_STREAM_END) {
- inflateEnd(strm);
- g_free(strm);
- g_free(strmbuf);
- break;
- }
- } else if (err == Z_BUF_ERROR) {
- /*
- * It's possible that not enough frames were captured
- * to decompress this fully, so return what we've done
- * so far, if any.
- */
- inflateEnd(strm);
- g_free(strm);
- g_free(strmbuf);
-
- if (uncompr != NULL) {
- break;
- } else {
- g_free(compr);
- return NULL;
- }
-
- } else if (err == Z_DATA_ERROR && inits_done == 1
- && uncompr == NULL && (*compr == 0x1f) &&
- (*(compr + 1) == 0x8b)) {
- /*
- * inflate() is supposed to handle both gzip and deflate
- * streams automatically, but in reality it doesn't
- * seem to handle either (at least not within the
- * context of an HTTP response.) We have to try
- * several tweaks, depending on the type of data and
- * version of the library installed.
- */
-
- /*
- * Gzip file format. Skip past the header, since the
- * fix to make it work (setting windowBits to 31)
- * doesn't work with all versions of the library.
- */
- Bytef *c = compr + 2;
- Bytef flags = 0;
-
- if (*c == Z_DEFLATED) {
- c++;
- } else {
- inflateEnd(strm);
- g_free(strm);
- g_free(compr);
- g_free(strmbuf);
- return NULL;
- }
-
- flags = *c;
-
- /* Skip past the MTIME, XFL, and OS fields. */
- c += 7;
-
- if (flags & (1 << 2)) {
- /* An Extra field is present. */
- gint xsize = (gint)(*c |
- (*(c + 1) << 8));
-
- c += xsize;
- }
-
- if (flags & (1 << 3)) {
- /* A null terminated filename */
-
- while ((c - compr) < comprlen && *c != '\0') {
- c++;
- }
-
- c++;
- }
-
- if (flags & (1 << 4)) {
- /* A null terminated comment */
-
- while ((c - compr) < comprlen && *c != '\0') {
- c++;
- }
-
- c++;
- }
-
-
- inflateReset(strm);
- next = c;
- strm->next_in = next;
- if (c - compr > comprlen) {
- inflateEnd(strm);
- g_free(strm);
- g_free(compr);
- g_free(strmbuf);
- return NULL;
- }
- comprlen -= (int) (c - compr);
-
- inflateEnd(strm);
- inflateInit2(strm, wbits);
- inits_done++;
- } else if (err == Z_DATA_ERROR && uncompr == NULL &&
- inits_done <= 3) {
-
- /*
- * Re-init the stream with a negative
- * MAX_WBITS. This is necessary due to
- * some servers (Apache) not sending
- * the deflate header with the
- * content-encoded response.
- */
- wbits = -MAX_WBITS;
-
- inflateReset(strm);
-
- strm->next_in = next;
- strm->avail_in = comprlen;
-
- inflateEnd(strm);
- memset(strmbuf, '\0', bufsiz);
- strm->next_out = strmbuf;
- strm->avail_out = bufsiz;
-
- err = inflateInit2(strm, wbits);
-
- inits_done++;
-
- if (err != Z_OK) {
- g_free(strm);
- g_free(strmbuf);
- g_free(compr);
- g_free(uncompr);
-
- return NULL;
- }
- } else {
- inflateEnd(strm);
- g_free(strm);
- g_free(strmbuf);
-
- if (uncompr == NULL) {
- g_free(compr);
- return NULL;
- }
-
- break;
- }
- }
-
-#ifdef TVB_Z_DEBUG
- printf("inflate() total passes: %u\n", inflate_passes);
- printf("bytes in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
-#endif
-
- if (uncompr != NULL) {
- uncompr_tvb = tvb_new_real_data((guint8*) uncompr, bytes_out, bytes_out);
- tvb_set_free_cb(uncompr_tvb, g_free);
- }
- g_free(compr);
- return uncompr_tvb;
-}
-#else
-tvbuff_t *
-tvb_uncompress(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
-{
- return NULL;
-}
-#endif
-
-tvbuff_t *
-tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
-{
- tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
- if (new_tvb)
- tvb_set_child_real_data_tvbuff (parent, new_tvb);
- return new_tvb;
-}
-
gint
tvb_raw_offset(tvbuff_t *tvb)
{
diff --git a/epan/tvbuff_zlib.c b/epan/tvbuff_zlib.c
new file mode 100644
index 0000000000..4f8e2e9dbe
--- /dev/null
+++ b/epan/tvbuff_zlib.c
@@ -0,0 +1,323 @@
+/* tvbuff_zlib.c
+ *
+ * $Id$
+ *
+ * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <string.h>
+
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif
+
+#include "tvbuff.h"
+
+#ifdef HAVE_LIBZ
+/*
+ * Uncompresses a zlib compressed packet inside a message of tvb at offset with
+ * length comprlen. Returns an uncompressed tvbuffer if uncompression
+ * succeeded or NULL if uncompression failed.
+ */
+#define TVB_Z_MIN_BUFSIZ 32768
+#define TVB_Z_MAX_BUFSIZ 1048576 * 10
+/* #define TVB_Z_DEBUG 1 */
+#undef TVB_Z_DEBUG
+
+tvbuff_t *
+tvb_uncompress(tvbuff_t *tvb, const int offset, int comprlen)
+{
+ gint err = Z_OK;
+ guint bytes_out = 0;
+ guint8 *compr = NULL;
+ guint8 *uncompr = NULL;
+ tvbuff_t *uncompr_tvb = NULL;
+ z_streamp strm = NULL;
+ Bytef *strmbuf = NULL;
+ guint inits_done = 0;
+ gint wbits = MAX_WBITS;
+ guint8 *next = NULL;
+ guint bufsiz = TVB_Z_MIN_BUFSIZ;
+#ifdef TVB_Z_DEBUG
+ guint inflate_passes = 0;
+ guint bytes_in = tvb_length_remaining(tvb, offset);
+#endif
+
+ if (tvb == NULL) {
+ return NULL;
+ }
+
+ compr = (guint8 *)tvb_memdup(NULL, tvb, offset, comprlen);
+
+ if (!compr)
+ return NULL;
+
+ /*
+ * Assume that the uncompressed data is at least twice as big as
+ * the compressed size.
+ */
+ bufsiz = tvb_length_remaining(tvb, offset) * 2;
+ bufsiz = CLAMP(bufsiz, TVB_Z_MIN_BUFSIZ, TVB_Z_MAX_BUFSIZ);
+
+#ifdef TVB_Z_DEBUG
+ printf("bufsiz: %u bytes\n", bufsiz);
+#endif
+
+ next = compr;
+
+ strm = g_new0(z_stream, 1);
+ strm->next_in = next;
+ strm->avail_in = comprlen;
+
+ strmbuf = (Bytef *)g_malloc0(bufsiz);
+ strm->next_out = strmbuf;
+ strm->avail_out = bufsiz;
+
+ err = inflateInit2(strm, wbits);
+ inits_done = 1;
+ if (err != Z_OK) {
+ inflateEnd(strm);
+ g_free(strm);
+ g_free(compr);
+ g_free(strmbuf);
+ return NULL;
+ }
+
+ while (1) {
+ memset(strmbuf, '\0', bufsiz);
+ strm->next_out = strmbuf;
+ strm->avail_out = bufsiz;
+
+ err = inflate(strm, Z_SYNC_FLUSH);
+
+ if (err == Z_OK || err == Z_STREAM_END) {
+ guint bytes_pass = bufsiz - strm->avail_out;
+
+#ifdef TVB_Z_DEBUG
+ ++inflate_passes;
+#endif
+
+ if (uncompr == NULL) {
+ /*
+ * This is ugly workaround for bug #6480
+ * (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6480)
+ *
+ * g_memdup(..., 0) returns NULL (g_malloc(0) also)
+ * when uncompr is NULL logic below doesn't create tvb
+ * which is later interpreted as decompression failed.
+ */
+ uncompr = (guint8 *)((bytes_pass || err != Z_STREAM_END) ?
+ g_memdup(strmbuf, bytes_pass) :
+ g_strdup(""));
+ } else {
+ guint8 *new_data = (guint8 *)g_malloc0(bytes_out + bytes_pass);
+
+ memcpy(new_data, uncompr, bytes_out);
+ memcpy(new_data + bytes_out, strmbuf, bytes_pass);
+
+ g_free(uncompr);
+ uncompr = new_data;
+ }
+
+ bytes_out += bytes_pass;
+
+ if (err == Z_STREAM_END) {
+ inflateEnd(strm);
+ g_free(strm);
+ g_free(strmbuf);
+ break;
+ }
+ } else if (err == Z_BUF_ERROR) {
+ /*
+ * It's possible that not enough frames were captured
+ * to decompress this fully, so return what we've done
+ * so far, if any.
+ */
+ inflateEnd(strm);
+ g_free(strm);
+ g_free(strmbuf);
+
+ if (uncompr != NULL) {
+ break;
+ } else {
+ g_free(compr);
+ return NULL;
+ }
+
+ } else if (err == Z_DATA_ERROR && inits_done == 1
+ && uncompr == NULL && (*compr == 0x1f) &&
+ (*(compr + 1) == 0x8b)) {
+ /*
+ * inflate() is supposed to handle both gzip and deflate
+ * streams automatically, but in reality it doesn't
+ * seem to handle either (at least not within the
+ * context of an HTTP response.) We have to try
+ * several tweaks, depending on the type of data and
+ * version of the library installed.
+ */
+
+ /*
+ * Gzip file format. Skip past the header, since the
+ * fix to make it work (setting windowBits to 31)
+ * doesn't work with all versions of the library.
+ */
+ Bytef *c = compr + 2;
+ Bytef flags = 0;
+
+ if (*c == Z_DEFLATED) {
+ c++;
+ } else {
+ inflateEnd(strm);
+ g_free(strm);
+ g_free(compr);
+ g_free(strmbuf);
+ return NULL;
+ }
+
+ flags = *c;
+
+ /* Skip past the MTIME, XFL, and OS fields. */
+ c += 7;
+
+ if (flags & (1 << 2)) {
+ /* An Extra field is present. */
+ gint xsize = (gint)(*c |
+ (*(c + 1) << 8));
+
+ c += xsize;
+ }
+
+ if (flags & (1 << 3)) {
+ /* A null terminated filename */
+
+ while ((c - compr) < comprlen && *c != '\0') {
+ c++;
+ }
+
+ c++;
+ }
+
+ if (flags & (1 << 4)) {
+ /* A null terminated comment */
+
+ while ((c - compr) < comprlen && *c != '\0') {
+ c++;
+ }
+
+ c++;
+ }
+
+
+ inflateReset(strm);
+ next = c;
+ strm->next_in = next;
+ if (c - compr > comprlen) {
+ inflateEnd(strm);
+ g_free(strm);
+ g_free(compr);
+ g_free(strmbuf);
+ return NULL;
+ }
+ comprlen -= (int) (c - compr);
+
+ inflateEnd(strm);
+ inflateInit2(strm, wbits);
+ inits_done++;
+ } else if (err == Z_DATA_ERROR && uncompr == NULL &&
+ inits_done <= 3) {
+
+ /*
+ * Re-init the stream with a negative
+ * MAX_WBITS. This is necessary due to
+ * some servers (Apache) not sending
+ * the deflate header with the
+ * content-encoded response.
+ */
+ wbits = -MAX_WBITS;
+
+ inflateReset(strm);
+
+ strm->next_in = next;
+ strm->avail_in = comprlen;
+
+ inflateEnd(strm);
+ memset(strmbuf, '\0', bufsiz);
+ strm->next_out = strmbuf;
+ strm->avail_out = bufsiz;
+
+ err = inflateInit2(strm, wbits);
+
+ inits_done++;
+
+ if (err != Z_OK) {
+ g_free(strm);
+ g_free(strmbuf);
+ g_free(compr);
+ g_free(uncompr);
+
+ return NULL;
+ }
+ } else {
+ inflateEnd(strm);
+ g_free(strm);
+ g_free(strmbuf);
+
+ if (uncompr == NULL) {
+ g_free(compr);
+ return NULL;
+ }
+
+ break;
+ }
+ }
+
+#ifdef TVB_Z_DEBUG
+ printf("inflate() total passes: %u\n", inflate_passes);
+ printf("bytes in: %u\nbytes out: %u\n\n", bytes_in, bytes_out);
+#endif
+
+ if (uncompr != NULL) {
+ uncompr_tvb = tvb_new_real_data((guint8*) uncompr, bytes_out, bytes_out);
+ tvb_set_free_cb(uncompr_tvb, g_free);
+ }
+ g_free(compr);
+ return uncompr_tvb;
+}
+#else
+tvbuff_t *
+tvb_uncompress(tvbuff_t *tvb _U_, const int offset _U_, int comprlen _U_)
+{
+ return NULL;
+}
+#endif
+
+tvbuff_t *
+tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int offset, int comprlen)
+{
+ tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
+ if (new_tvb)
+ tvb_set_child_real_data_tvbuff (parent, new_tvb);
+ return new_tvb;
+}