aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-wcp.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2013-02-27 22:04:40 +0000
committerGuy Harris <guy@alum.mit.edu>2013-02-27 22:04:40 +0000
commitcb2d1c52a913f563e987811b627067572e299897 (patch)
tree16fd6e7d1df25cba97d68fb7ed8ef3f08525befd /epan/dissectors/packet-wcp.c
parentb5bbd0712e4c29647ff4838bcc61669b32443331 (diff)
When decompressing, put an entry into the protocol tree that covers all
the compressed data, put the entries for particular parts of that data under that entry, and, when we have a problem decompressing, add an expert info item to that entry, rather than just adding text or using proto_malformed. Do so for *all* decompression problems; in particular, check for decompressed_entry() returning NULL, which it can do. tvb_new_child_real_data() won't throw an exception, so don't bother checking for that. If, after the first pass, we can't find the uncompressed data for a frame, report it as a dissector bug. Check whether we have room for a byte in the uncompressed data buffer *before* copying it. Other cleanups. svn path=/trunk/; revision=47922
Diffstat (limited to 'epan/dissectors/packet-wcp.c')
-rw-r--r--epan/dissectors/packet-wcp.c100
1 files changed, 52 insertions, 48 deletions
diff --git a/epan/dissectors/packet-wcp.c b/epan/dissectors/packet-wcp.c
index cd826b408e..6afca9b289 100644
--- a/epan/dissectors/packet-wcp.c
+++ b/epan/dissectors/packet-wcp.c
@@ -102,11 +102,11 @@
#include <glib.h>
#include <string.h>
#include <epan/packet.h>
-#include "packet-frame.h"
#include <epan/circuit.h>
#include <epan/emem.h>
#include <epan/etypes.h>
#include <epan/nlpid.h>
+#include <epan/expert.h>
#define MAX_WIN_BUF_LEN 0x7fff /* storage size for decompressed data */
#define MAX_WCP_BUF_LEN 2048 /* storage size for decompressed data */
@@ -154,6 +154,7 @@ static int hf_wcp_hist_size = -1;
static int hf_wcp_ppc = -1;
static int hf_wcp_pib = -1;
+static int hf_wcp_compressed_data = -1;
static int hf_wcp_comp_bits = -1;
/* static int hf_wcp_comp_marker = -1; */
static int hf_wcp_short_len = -1;
@@ -163,6 +164,7 @@ static int hf_wcp_long_run = -1;
static int hf_wcp_offset = -1;
static gint ett_wcp = -1;
+static gint ett_wcp_comp_data = -1;
static gint ett_wcp_field = -1;
static dissector_handle_t fr_uncompressed_handle;
@@ -375,8 +377,6 @@ static void dissect_wcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
next_tvb = wcp_uncompress( tvb, wcp_header_len, pinfo, wcp_tree);
if ( !next_tvb){
- proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
- "[Malformed Frame: Bad WCP compressed data]" );
return;
}
}
@@ -422,8 +422,6 @@ static guint8 *decompressed_entry( guint8 *src, guint8 *dst, int *len, guint8 *
while( data_cnt--){
*dst = *src;
if ( ++(*len) >MAX_WCP_BUF_LEN){
- printf("decomp failed, len = %d\n", *len);
-
return NULL; /* end of buffer error */
}
if ( dst++ == buf_end)
@@ -470,82 +468,93 @@ static tvbuff_t *wcp_uncompress( tvbuff_t *src_tvb, int offset, packet_info *pin
/* do the packet data uncompression and load it into the dst buffer */
- proto_tree *sub_tree;
- proto_item *ti;
+ proto_tree *cd_tree, *sub_tree;
+ proto_item *cd_item, *ti;
- int len=0, i = -1;
+ int len, i;
int cnt = tvb_reported_length( src_tvb)-1; /* don't include check byte */
guint8 *dst, *src, *buf_start, *buf_end, comp_flag_bits = 0;
guint8 src_buf[ MAX_WCP_BUF_LEN];
- tvbuff_t *volatile tvb = 0;
+ tvbuff_t *tvb;
wcp_window_t *buf_ptr = 0;
- wcp_pdata_t *volatile pdata_ptr;
- volatile gboolean bounds_error = FALSE;
+ wcp_pdata_t *pdata_ptr;
buf_ptr = get_wcp_window_ptr( pinfo);
buf_start = buf_ptr->buffer;
buf_end = buf_start + MAX_WIN_BUF_LEN;
+ cd_item = proto_tree_add_item(tree, hf_wcp_compressed_data,
+ src_tvb, offset, cnt - offset, ENC_NA);
+ cd_tree = proto_item_add_subtree(cd_item, ett_wcp_comp_data);
if (cnt - offset > MAX_WCP_BUF_LEN) {
- if (tree)
- proto_tree_add_text( tree, src_tvb, offset, -1,
- "Compressed data exceeds maximum buffer length (%d > %d)",
- cnt - offset, MAX_WCP_BUF_LEN);
+ expert_add_info_format(pinfo, cd_item, PI_MALFORMED, PI_ERROR,
+ "Compressed data exceeds maximum buffer length (%d > %d)",
+ cnt - offset, MAX_WCP_BUF_LEN);
return NULL;
}
src = tvb_memcpy(src_tvb, src_buf, offset, cnt - offset);
dst = buf_ptr->buf_cur;
+ len = 0;
+ i = -1;
- while( offset++ < cnt){
+ while( offset < cnt){
if ( --i >= 0){
if ( comp_flag_bits & 0x80){ /* if this is a compressed entry */
if ( !pinfo->fd->flags.visited){ /* if first pass */
dst = decompressed_entry( src, dst, &len, buf_start, buf_end);
+ if (dst == NULL){
+ expert_add_info_format(pinfo, cd_item, PI_MALFORMED, PI_ERROR,
+ "Uncompressed data exceeds maximum buffer length (%d > %d)",
+ len, MAX_WCP_BUF_LEN);
+ return NULL;
+ }
}
if ((*src & 0xf0) == 0x10){
if ( tree) {
- ti = proto_tree_add_item( tree, hf_wcp_long_run, src_tvb,
- offset-1, 3, ENC_NA);
+ ti = proto_tree_add_item( cd_tree, hf_wcp_long_run, src_tvb,
+ offset, 3, ENC_NA);
sub_tree = proto_item_add_subtree(ti, ett_wcp_field);
proto_tree_add_uint(sub_tree, hf_wcp_offset, src_tvb,
- offset-1, 2, pntohs(src));
+ offset, 2, pntohs(src));
proto_tree_add_item( sub_tree, hf_wcp_long_len, src_tvb,
- offset+1, 1, ENC_BIG_ENDIAN);
+ offset+2, 1, ENC_BIG_ENDIAN);
}
src += 3;
- offset += 2;
+ offset += 3;
}else{
if ( tree) {
- ti = proto_tree_add_item( tree, hf_wcp_short_run, src_tvb,
- offset - 1, 2, ENC_NA);
+ ti = proto_tree_add_item( cd_tree, hf_wcp_short_run, src_tvb,
+ offset, 2, ENC_NA);
sub_tree = proto_item_add_subtree(ti, ett_wcp_field);
proto_tree_add_uint( sub_tree, hf_wcp_short_len, src_tvb,
- offset-1, 1, *src);
+ offset, 1, *src);
proto_tree_add_uint(sub_tree, hf_wcp_offset, src_tvb,
- offset-1, 2, pntohs(src));
+ offset, 2, pntohs(src));
}
src += 2;
- offset += 1;
+ offset += 2;
}
}else {
+ if ( ++len >MAX_WCP_BUF_LEN){
+ expert_add_info_format(pinfo, cd_item, PI_MALFORMED, PI_ERROR,
+ "Uncompressed data exceeds maximum buffer length (%d > %d)",
+ len, MAX_WCP_BUF_LEN);
+ return NULL;
+ }
+
if ( !pinfo->fd->flags.visited){ /* if first pass */
*dst = *src;
if ( dst++ == buf_end)
dst = buf_start;
}
++src;
- ++len;
-
- }
-
- if ( len >MAX_WCP_BUF_LEN){
- return NULL;
+ ++offset;
}
comp_flag_bits <<= 1;
@@ -553,9 +562,10 @@ static tvbuff_t *wcp_uncompress( tvbuff_t *src_tvb, int offset, packet_info *pin
}else { /* compressed data flag */
comp_flag_bits = *src++;
- if (tree)
- proto_tree_add_uint( tree, hf_wcp_comp_bits, src_tvb, offset-1, 1,
+ if (cd_tree)
+ proto_tree_add_uint(cd_tree, hf_wcp_comp_bits, src_tvb, offset, 1,
comp_flag_bits);
+ offset++;
i = 8;
}
@@ -565,8 +575,10 @@ static tvbuff_t *wcp_uncompress( tvbuff_t *src_tvb, int offset, packet_info *pin
/* get uncompressed data */
pdata_ptr = p_get_proto_data( pinfo->fd, proto_wcp);
- if ( !pdata_ptr) /* exit if no data */
+ if ( !pdata_ptr) { /* exit if no data */
+ REPORT_DISSECTOR_BUG("Can't find uncompressed data");
return NULL;
+ }
len = pdata_ptr->len;
} else {
@@ -580,19 +592,7 @@ static tvbuff_t *wcp_uncompress( tvbuff_t *src_tvb, int offset, packet_info *pin
buf_ptr->buf_cur = dst;
}
-
- TRY {
- tvb = tvb_new_child_real_data(src_tvb, pdata_ptr->buffer, pdata_ptr->len, pdata_ptr->len);
- }
- CATCH(BoundsError) {
- DISSECTOR_ASSERT_NOT_REACHED();
- }
- CATCH(ReportedBoundsError) {
- bounds_error = TRUE;
- }
- ENDTRY;
-
- if (bounds_error) return NULL;
+ tvb = tvb_new_child_real_data(src_tvb, pdata_ptr->buffer, pdata_ptr->len, pdata_ptr->len);
/* Add new data to the data source list */
add_new_data_source( pinfo, tvb, "Uncompressed WCP");
@@ -661,6 +661,9 @@ proto_register_wcp(void)
{ &hf_wcp_pib,
{ "PIB", "wcp.pib", FT_UINT8, BASE_DEC, NULL, 0,
NULL, HFILL }},
+ { &hf_wcp_compressed_data,
+ { "Compressed Data", "wcp.compressed_data", FT_NONE, BASE_NONE, NULL, 0,
+ "Raw compressed data", HFILL }},
{ &hf_wcp_comp_bits,
{ "Compress Flag", "wcp.flag", FT_UINT8, BASE_HEX, NULL, 0,
"Compressed byte flag", HFILL }},
@@ -690,6 +693,7 @@ proto_register_wcp(void)
static gint *ett[] = {
&ett_wcp,
+ &ett_wcp_comp_data,
&ett_wcp_field,
};