From a891f3e70b9efa4980feb830fba3b96e0bbaf39d Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Thu, 3 Oct 2013 01:54:02 +0000 Subject: [PATCH] Make expert items used in "low level" proto functions filterable (and ensure they are called even with a NULL tree). I don't really like the Type Length Mismatch "protocol", but it doesn't seem that much different than the exception "protocols". svn path=/trunk/; revision=52341 --- epan/dissectors/packet-usb-video.c | 26 ++++----- epan/expert.h | 2 +- epan/proto.c | 91 ++++++++++++++++++++---------- epan/proto.h | 5 +- 4 files changed, 79 insertions(+), 45 deletions(-) diff --git a/epan/dissectors/packet-usb-video.c b/epan/dissectors/packet-usb-video.c index 0ea99dd3bf..49117a6509 100644 --- a/epan/dissectors/packet-usb-video.c +++ b/epan/dissectors/packet-usb-video.c @@ -348,6 +348,7 @@ static gint ett_video_standards = -1; static gint ett_control_capabilities = -1; static expert_field ei_usb_vid_subtype_unknown = EI_INIT; +static expert_field ei_usb_vid_bitmask_len = EI_INIT; /* Lookup tables */ static const value_string vc_ep_descriptor_subtypes[] = { @@ -690,7 +691,7 @@ dissect_bmControl(proto_tree *tree, tvbuff_t *tvb, int offset, if (bm_size > 0) { proto_tree_add_bitmask_len(tree, tvb, offset, bm_size, hf_usb_vid_bmControl, - ett_subtree, bm_items, ENC_LITTLE_ENDIAN); + ett_subtree, bm_items, &ei_usb_vid_bitmask_len, ENC_LITTLE_ENDIAN); offset += bm_size; } @@ -1120,7 +1121,7 @@ dissect_usb_video_streaming_input_header(proto_tree *tree, tvbuff_t *tvb, int of for (i=0; ifi_tmp; + tree_data = PTREE_DATA(tree); + fi_save = tree_data->fi_tmp; /* Keep the current item from getting freed by proto_tree_new_item. */ tree_data->fi_tmp = NULL; + } - expert_add_info_format_internal(NULL, tree, PI_MALFORMED, is_error ? PI_ERROR : PI_WARN, "Trying to fetch %s with length %d", descr, length); + if (is_error) { + expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length); + } else { + expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length); + } + if (tree) { tree_data->fi_tmp = fi_save; } @@ -4997,6 +5009,26 @@ tmp_fld_check_assert(header_field_info *hfinfo) } } +static void +register_type_length_mismatch(void) +{ + static ei_register_info ei[] = { + { &ei_type_length_mismatch_error, { "type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }}, + { &ei_type_length_mismatch_warn, { "type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }}, + }; + + expert_module_t* expert_type_length_mismatch; + + proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "type_length"); + + expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch); + expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei)); + + /* "Type Length Mismatch" isn't really a protocol, it's an error indication; + disabling them makes no sense. */ + proto_set_cant_toggle(proto_type_length_mismatch); +} + #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (120000+PRE_ALLOC_EXPERT_FIELDS_MEM) static int proto_register_field_init(header_field_info *hfinfo, const int parent) @@ -6908,44 +6940,45 @@ proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb, proto_item * proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset, const guint len, const int hf_hdr, - const gint ett, const int **fields, + const gint ett, const int **fields, struct expert_field* exp, const guint encoding) { proto_item *item = NULL; header_field_info *hf; + guint decodable_len; + guint decodable_offset; + guint32 decodable_value; hf = proto_registrar_get_nth(hf_hdr); DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type)); + decodable_offset = offset; + decodable_len = MIN(len, (guint) ftype_length(hf->type)); + + /* If we are ftype_length-limited, + * make sure we decode as many LSBs as possible. + */ + if (encoding == ENC_BIG_ENDIAN) { + decodable_offset += (len - decodable_len); + } + if (parent_tree) { - guint decodable_len; - guint decodable_offset; - guint32 decodable_value; - - decodable_offset = offset; - decodable_len = MIN(len, (guint) ftype_length(hf->type)); - - /* If we are ftype_length-limited, - * make sure we decode as many LSBs as possible. - */ - if (encoding == ENC_BIG_ENDIAN) { - decodable_offset += (len - decodable_len); - } - decodable_value = get_uint_value(parent_tree, tvb, decodable_offset, decodable_len, encoding); /* The root item covers all the bytes even if we can't decode them all */ item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len, decodable_value); + } - if (decodable_len < len) { - /* Dissector likely requires updating for new protocol revision */ - expert_add_info_format_internal(NULL, item, PI_UNDECODED, PI_WARN, - "Only least-significant %d of %d bytes decoded", - decodable_len, len); - } + if (decodable_len < len) { + /* Dissector likely requires updating for new protocol revision */ + expert_add_info_format(NULL, item, exp, + "Only least-significant %d of %d bytes decoded", + decodable_len, len); + } + if (item) { proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE); } diff --git a/epan/proto.h b/epan/proto.h index 1fbee97be5..5083db6100 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -76,6 +76,7 @@ WS_DLL_PUBLIC int hf_text_only; #define ITEM_LABEL_LENGTH 240 struct _value_string; +struct expert_field; /** Make a const value_string[] look like a _value_string pointer, used to set header_field_info.strings */ #define VALS(x) (const struct _value_string*)(x) @@ -1936,11 +1937,13 @@ proto_tree_add_bitmask(proto_tree *tree, tvbuff_t *tvb, const guint offset, FT_BOOLEAN bits that are set to 1 will have the name added to the expansion. FT_integer fields that have a value_string attached will have the matched string displayed on the expansion line. + @param exp expert info field used when decodable_len < len. This also means this function + should be called even when tree == NULL @param encoding big or little endian byte representation (ENC_BIG_ENDIAN/ENC_LITTLE_ENDIAN) @return the newly created item */ WS_DLL_PUBLIC proto_item * proto_tree_add_bitmask_len(proto_tree *tree, tvbuff_t *tvb, const guint offset, const guint len, - const int hf_hdr, const gint ett, const int **fields, const guint encoding); + const int hf_hdr, const gint ett, const int **fields, struct expert_field* exp, const guint encoding); /** Add a text with a subtree of bitfields. @param tree the tree to append this item to