aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2016-01-08 18:25:26 -0800
committerGuy Harris <guy@alum.mit.edu>2016-01-09 02:26:06 +0000
commitc67c6e8f30b02450de2d9fb02b91026c5f954448 (patch)
treeb2fc637a2e893fe3daaec25718603d529f41e6dc
parent628c068a94fd8c4ebb36670637ed83f6dad80223 (diff)
Add routines to add an item and return the item's real length.
proto_item_get_len() is *not* guaranteed to return a correct value. Even if there's a non-null tree item, it might be pointing to a "faked" item; it really shouldn't be used. So add proto_tree_add_item_ret_length() and proto_tree_add_item_new_ret_length(), which calculate the real length themselves and return it through a pointer. Fix as many places as we straightforwardly can to use them rather than to use proto_item_get_len(). (There's a Lua API for proto_item_get_len(), so we keep it around, but we should add Lua APIs for the new routines, and deprecate the old API.) Fix ptvcursor_add() to do the same thing that proto_tree_add_item_ret_length() and proto_tree_add_item_new_ret_length() do. Split the TRY_TO_FAKE_THIS_ITEM macros into a macro to check for the tree being null and to try to fake the item. We don't always use the former macro, as we might need to do more than just return NULL if the incoming tree is null (for example, calculating the item's real length and using it...). new_field_info() never returns NULL; remove checks for it. The check for a null tree is done before the calls to new_field_info(). Change-Id: I002a218d1f810c73e0de837e0ac6ebcde21bacec Reviewed-on: https://code.wireshark.org/review/13139 Reviewed-by: Guy Harris <guy@alum.mit.edu>
-rw-r--r--debian/libwireshark0.symbols2
-rw-r--r--epan/dissectors/packet-lat.c5
-rw-r--r--epan/dissectors/packet-quake.c48
-rw-r--r--epan/dissectors/packet-sccp.c3
-rw-r--r--epan/proto.c322
-rw-r--r--epan/proto.h26
-rw-r--r--epan/wslua/wslua_tree.c1
7 files changed, 348 insertions, 59 deletions
diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols
index a55dfdd0cc..7ced7b4469 100644
--- a/debian/libwireshark0.symbols
+++ b/debian/libwireshark0.symbols
@@ -1055,7 +1055,9 @@ libwireshark.so.0 libwireshark0 #MINVER#
proto_tree_add_ipxnet_format_value@Base 1.9.1
proto_tree_add_item@Base 1.9.1
proto_tree_add_item_new@Base 1.12.0~rc1
+ proto_tree_add_item_new_ret_length@Base 2.1.0
proto_tree_add_item_ret_int@Base 1.99.6
+ proto_tree_add_item_ret_length@Base 2.1.0
proto_tree_add_item_ret_uint@Base 1.99.6
proto_tree_add_none_format@Base 1.9.1
proto_tree_add_protocol_format@Base 1.9.1
diff --git a/epan/dissectors/packet-lat.c b/epan/dissectors/packet-lat.c
index 37f1d6e7da..c812954075 100644
--- a/epan/dissectors/packet-lat.c
+++ b/epan/dissectors/packet-lat.c
@@ -333,9 +333,10 @@ static int
dissect_lat_string(tvbuff_t *tvb, int offset, int hf, proto_tree *tree)
{
proto_item *ti;
+ gint item_length;
- ti = proto_tree_add_item(tree, hf, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- return offset + proto_item_get_len(ti);
+ ti = proto_tree_add_item_ret_length(tree, hf, tvb, offset, 1, ENC_LITTLE_ENDIAN, &item_length);
+ return offset + item_length;
}
static guint
diff --git a/epan/dissectors/packet-quake.c b/epan/dissectors/packet-quake.c
index 448cda4e3f..a7bdc2c33f 100644
--- a/epan/dissectors/packet-quake.c
+++ b/epan/dissectors/packet-quake.c
@@ -153,13 +153,14 @@ dissect_quake_CCREQ_CONNECT
{
gint offset;
proto_item *ti;
+ gint item_len;
offset = 0;
if (tree) {
- ti = proto_tree_add_item(tree, hf_quake_CCREQ_CONNECT_game,
- tvb, offset, -1, ENC_ASCII|ENC_NA);
- offset += proto_item_get_len(ti);
+ ti = proto_tree_add_item_ret_length(tree, hf_quake_CCREQ_CONNECT_game,
+ tvb, offset, -1, ENC_ASCII|ENC_NA, &item_len);
+ offset += item_len;
proto_tree_add_item(tree, hf_quake_CCREQ_CONNECT_version,
tvb, offset, 1, ENC_LITTLE_ENDIAN);
@@ -173,13 +174,14 @@ dissect_quake_CCREQ_SERVER_INFO
{
gint offset;
proto_item *ti;
+ gint item_len;
offset = 0;
if (tree) {
- ti = proto_tree_add_item(tree, hf_quake_CCREQ_SERVER_INFO_game,
- tvb, offset, -1, ENC_ASCII|ENC_NA);
- offset += proto_item_get_len(ti);
+ ti = proto_tree_add_item_ret_length(tree, hf_quake_CCREQ_SERVER_INFO_game,
+ tvb, offset, -1, ENC_ASCII|ENC_NA, &item_len);
+ offset += item_len;
proto_tree_add_item(tree, hf_quake_CCREQ_SERVER_INFO_version,
tvb, offset, 1, ENC_LITTLE_ENDIAN);
}
@@ -243,23 +245,25 @@ dissect_quake_CCREP_SERVER_INFO
{
gint offset;
proto_item *ti;
+ gint item_len;
offset = 0;
if (tree) {
- ti = proto_tree_add_item(tree,
+ ti = proto_tree_add_item_ret_length(tree,
hf_quake_CCREP_SERVER_INFO_address, tvb, offset, -1,
- ENC_ASCII|ENC_NA);
- offset += proto_item_get_len(ti);
+ ENC_ASCII|ENC_NA, &item_len);
+ offset += item_len;
- ti = proto_tree_add_item(tree,
+ ti = proto_tree_add_item_ret_length(tree,
hf_quake_CCREP_SERVER_INFO_server, tvb, offset, -1,
- ENC_ASCII|ENC_NA);
- offset += proto_item_get_len(ti);
+ ENC_ASCII|ENC_NA, &item_len);
+ offset += item_len;
- ti = proto_tree_add_item(tree, hf_quake_CCREP_SERVER_INFO_map,
- tvb, offset, -1, ENC_ASCII|ENC_NA);
- offset += proto_item_get_len(ti);
+ ti = proto_tree_add_item_ret_length(tree,
+ hf_quake_CCREP_SERVER_INFO_map, tvb, offset, -1,
+ ENC_ASCII|ENC_NA, &item_len);
+ offset += item_len;
proto_tree_add_item(tree, hf_quake_CCREP_SERVER_INFO_num_player,
tvb, offset, 1, ENC_LITTLE_ENDIAN);
@@ -284,6 +288,7 @@ dissect_quake_CCREP_PLAYER_INFO
guint32 color_pants;
proto_item *colors_item;
proto_tree *colors_tree;
+ gint item_len;
offset = 0;
@@ -292,9 +297,9 @@ dissect_quake_CCREP_PLAYER_INFO
tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset += 1;
- ti = proto_tree_add_item(tree, hf_quake_CCREP_PLAYER_INFO_name,
- tvb, offset, -1, ENC_ASCII|ENC_NA);
- offset += proto_item_get_len(ti);
+ ti = proto_tree_add_item_ret_length(tree, hf_quake_CCREP_PLAYER_INFO_name,
+ tvb, offset, -1, ENC_ASCII|ENC_NA, &item_len);
+ offset += item_len;
colors = tvb_get_letohl(tvb, offset + 0);
color_shirt = (colors >> 4) & 0x0f;
@@ -331,15 +336,16 @@ dissect_quake_CCREP_RULE_INFO
{
gint offset;
proto_item *ti;
+ gint item_len;
if (tvb_reported_length(tvb) == 0) return;
offset = 0;
if (tree) {
- ti = proto_tree_add_item(tree, hf_quake_CCREP_RULE_INFO_rule,
- tvb, offset, -1, ENC_ASCII|ENC_NA);
- offset += proto_item_get_len(ti);
+ ti = proto_tree_add_item_ret_length(tree, hf_quake_CCREP_RULE_INFO_rule,
+ tvb, offset, -1, ENC_ASCII|ENC_NA, &item_len);
+ offset += item_len;
proto_tree_add_item(tree, hf_quake_CCREP_RULE_INFO_value,
tvb, offset, -1, ENC_ASCII|ENC_NA);
diff --git a/epan/dissectors/packet-sccp.c b/epan/dissectors/packet-sccp.c
index c1a8567985..6fc8b3e3e2 100644
--- a/epan/dissectors/packet-sccp.c
+++ b/epan/dissectors/packet-sccp.c
@@ -2562,6 +2562,9 @@ dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree,
/* sccp_length = proto_item_get_len(sccp_item);
* sccp_length -= parameter_length;
* proto_item_set_len(sccp_item, sccp_length);
+ *
+ * except that proto_item_get_len() is *NOT* guaranteed to return
+ * a correct value - if the item has been "faked", it will be wrong
*/
break;
diff --git a/epan/proto.c b/epan/proto.c
index be54c4b84c..3a9566a9ba 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -82,6 +82,23 @@ struct ptvcursor {
/** See inlined comments.
@param tree the tree to append this item to
+ @param free_block a code block to call to free resources if this returns
+ @return NULL if 'tree' is null */
+#define CHECK_FOR_NULL_TREE_AND_FREE(tree, free_block) \
+ if (!tree) { \
+ free_block; \
+ return NULL; \
+ }
+
+/** See inlined comments.
+ @param tree the tree to append this item to
+ @param free_block a code block to call to free resources if this returns
+ @return NULL if 'tree' is null */
+#define CHECK_FOR_NULL_TREE(tree) \
+ CHECK_FOR_NULL_TREE_AND_FREE(tree, ((void)0))
+
+/** See inlined comments.
+ @param tree the tree to append this item to
@param hfindex field index
@param hfinfo header_field
@param free_block a code block to call to free resources if this returns
@@ -98,10 +115,6 @@ struct ptvcursor {
We fake FT_PROTOCOL unless some clients have requested us \
not to do so. \
*/ \
- if (!tree) { \
- free_block; \
- return NULL; \
- } \
PTREE_DATA(tree)->count++; \
if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
free_block; \
@@ -181,6 +194,10 @@ static void
get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
gint *item_length);
+static gint
+get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
+ gint length, guint item_length, const gint encoding);
+
static field_info *
new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
const gint start, const gint item_length);
@@ -1118,6 +1135,8 @@ ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
tree = ptvcursor_tree(ptvc);
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
@@ -1155,6 +1174,8 @@ proto_tree_add_text_internal(proto_tree *tree, tvbuff_t *tvb, gint start, gint l
va_list ap;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
pi = proto_tree_add_text_node(tree, tvb, start, length);
@@ -1176,6 +1197,8 @@ proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
pi = proto_tree_add_text_node(tree, tvb, start, length);
@@ -1246,6 +1269,8 @@ proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint len
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
pi = proto_tree_add_text_node(tree, tvb, start, length);
@@ -1263,6 +1288,8 @@ proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
pi = proto_tree_add_text_node(tree, tvb, start, length);
@@ -1982,7 +2009,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree,
break;
case FT_STRINGZ:
- if (length < -1 ) {
+ if (length < -1) {
report_type_length_mismatch(tree, "a string", length, TRUE);
}
/* Instead of calling proto_item_set_len(),
@@ -2209,13 +2236,12 @@ gint32 *retval)
if (retval)
*retval = value;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
new_fi = new_field_info(tree, hfinfo, tvb, start, length);
- if (new_fi == NULL)
- return NULL;
-
proto_tree_set_int(new_fi, value);
FI_SET_FLAG(new_fi,
@@ -2226,8 +2252,8 @@ gint32 *retval)
proto_item *
proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
-const gint start, gint length, const guint encoding,
-guint32 *retval)
+ const gint start, gint length,
+ const guint encoding, guint32 *retval)
{
header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
field_info *new_fi;
@@ -2261,13 +2287,12 @@ guint32 *retval)
if (retval)
*retval = value;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
new_fi = new_field_info(tree, hfinfo, tvb, start, length);
- if (new_fi == NULL)
- return NULL;
-
proto_tree_set_uint(new_fi, value);
FI_SET_FLAG(new_fi,
@@ -2310,25 +2335,24 @@ ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
field_info *new_fi;
header_field_info *hfinfo;
gint item_length;
- guint32 n;
int offset;
- /* We can't fake it just yet. We have to advance the cursor
- TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
-
offset = ptvc->offset;
PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
- ptvc->offset += length;
- if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
- /*
- * The length of the rest of the item is in the first N
- * bytes of the item.
- */
- n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
- ptvc->offset += n;
+
+ if (!ptvc->tree) {
+ ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset,
+ length, item_length, encoding);
+ return NULL;
}
+ offset = ptvc->offset;
+ PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+ get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
+ ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
+ item_length, encoding);
+
test_length(hfinfo, ptvc->tvb, offset, item_length);
/* Coast clear. Try and fake it */
@@ -2344,7 +2368,7 @@ ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
the item is extracted from the tvbuff handed to it. */
proto_item *
proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
- const gint start, gint length, const guint encoding)
+ const gint start, gint length, const guint encoding)
{
field_info *new_fi;
gint item_length;
@@ -2354,13 +2378,12 @@ proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *t
get_hfi_length(hfinfo, tvb, start, &length, &item_length);
test_length(hfinfo, tvb, start, item_length);
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
- if (new_fi == NULL)
- return NULL;
-
return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
}
@@ -2374,6 +2397,56 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
}
+/* Add an item to a proto_tree, using the text label registered to that item;
+ the item is extracted from the tvbuff handed to it.
+
+ Return the length of the item through the pointer. */
+proto_item *
+proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo,
+ tvbuff_t *tvb, const gint start,
+ gint length, const guint encoding,
+ gint *retval)
+{
+ field_info *new_fi;
+ gint item_length;
+ proto_item *item;
+
+ DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
+
+ get_hfi_length(hfinfo, tvb, start, &length, &item_length);
+ test_length(hfinfo, tvb, start, item_length);
+
+ if (!tree) {
+ /*
+ * We need to get the correct item length here.
+ * That's normally done by proto_tree_new_item(),
+ * but we won't be calling it.
+ */
+ *retval = get_full_length(hfinfo, tvb, start, length,
+ item_length, encoding);
+ return NULL;
+ }
+
+ TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
+
+ new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
+
+ item = proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
+ *retval = new_fi->length;
+ return item;
+}
+
+proto_item *
+proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ const gint start, gint length,
+ const guint encoding, gint *retval)
+{
+ register header_field_info *hfinfo;
+
+ PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
+ return proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, retval);
+}
+
/* which FT_ types can use proto_tree_add_bytes_item() */
static inline gboolean
validate_proto_tree_add_bytes_ftype(const enum ftenum type)
@@ -2465,6 +2538,14 @@ proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
if (err) *err = saved_err;
+ CHECK_FOR_NULL_TREE_AND_FREE(tree,
+ {
+ if (created_bytes)
+ g_byte_array_free(created_bytes, TRUE);
+ created_bytes = NULL;
+ bytes = NULL;
+ } );
+
TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
{
if (created_bytes)
@@ -2476,9 +2557,6 @@ proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
/* n will be zero except when it's a FT_UINT_BYTES */
new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
- if (new_fi == NULL)
- return NULL;
-
if (encoding & ENC_STRING) {
if (saved_err == ERANGE)
expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
@@ -2558,13 +2636,12 @@ proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
retval->nsecs = time_stamp.nsecs;
}
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
new_fi = new_field_info(tree, hfinfo, tvb, start, length);
- if (new_fi == NULL)
- return NULL;
-
proto_tree_set_time(new_fi, &time_stamp);
if (encoding & ENC_STRING) {
@@ -2591,6 +2668,8 @@ proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
va_list ap;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);
@@ -2645,6 +2724,8 @@ proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
va_list ap;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL);
@@ -2675,6 +2756,8 @@ proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
get_hfi_length(hfinfo, tvb, start, &length, &item_length);
test_length(hfinfo, tvb, start, item_length);
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
@@ -2698,6 +2781,8 @@ proto_tree_add_bytes_with_length(proto_tree *tree, int hfindex, tvbuff_t *tvb, g
get_hfi_length(hfinfo, tvb, start, &tvbuff_length, &item_length);
test_length(hfinfo, tvb, start, item_length);
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
@@ -2723,6 +2808,8 @@ proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
get_hfi_length(hfinfo, tvb, start, &length, &item_length);
test_length(hfinfo, tvb, start, item_length);
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
if (start_ptr)
@@ -2753,6 +2840,8 @@ proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
get_hfi_length(hfinfo, tvb, start, &length, &item_length);
test_length(hfinfo, tvb, start, item_length);
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
if (start_ptr)
@@ -2812,6 +2901,8 @@ proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
@@ -2877,6 +2968,8 @@ proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);
@@ -2940,6 +3033,8 @@ proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv4);
@@ -3003,6 +3098,8 @@ proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);
@@ -3089,6 +3186,8 @@ proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_GUID);
@@ -3164,6 +3263,8 @@ proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);
@@ -3264,6 +3365,8 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo);
@@ -3421,6 +3524,8 @@ proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ETHER);
@@ -3490,6 +3595,8 @@ proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
@@ -3545,6 +3652,8 @@ proto_tree_add_boolean64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint star
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
@@ -3616,6 +3725,8 @@ proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_FLOAT);
@@ -3679,6 +3790,8 @@ proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_DOUBLE);
@@ -3742,6 +3855,8 @@ proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi = NULL;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
switch (hfinfo->type) {
@@ -3828,6 +3943,8 @@ proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi = NULL;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
switch (hfinfo->type) {
@@ -3918,6 +4035,8 @@ proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi = NULL;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
switch (hfinfo->type) {
@@ -4007,6 +4126,8 @@ proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi = NULL;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
switch (hfinfo->type) {
@@ -4096,6 +4217,8 @@ proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
proto_item *pi;
header_field_info *hfinfo;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);
@@ -4352,6 +4475,113 @@ get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint
}
}
+static gint
+get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
+ gint length, guint item_length, const gint encoding)
+{
+ guint32 n;
+
+ /*
+ * We need to get the correct item length here.
+ * That's normally done by proto_tree_new_item(),
+ * but we won't be calling it.
+ */
+ switch (hfinfo->type) {
+
+ case FT_NONE:
+ case FT_PROTOCOL:
+ case FT_BYTES:
+ /*
+ * The length is the specified length.
+ */
+ break;
+
+ case FT_UINT_BYTES:
+ /*
+ * Map all non-zero values to little-endian for
+ * backwards compatibility.
+ */
+ n = get_uint_value(NULL, tvb, start, length,
+ encoding ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN);
+ item_length += n;
+ break;
+
+ case FT_BOOLEAN:
+ /* XXX - make these just FT_UINT? */
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ case FT_UINT40:
+ case FT_UINT48:
+ case FT_UINT56:
+ case FT_UINT64:
+ /* XXX - make these just FT_INT? */
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ case FT_INT40:
+ case FT_INT48:
+ case FT_INT56:
+ case FT_INT64:
+ case FT_IPv4:
+ case FT_IPXNET:
+ case FT_IPv6:
+ case FT_FCWWN:
+ case FT_AX25:
+ case FT_VINES:
+ case FT_ETHER:
+ case FT_EUI64:
+ case FT_GUID:
+ case FT_OID:
+ case FT_REL_OID:
+ case FT_SYSTEM_ID:
+ case FT_FLOAT:
+ case FT_DOUBLE:
+ case FT_STRING:
+ /*
+ * The length is the specified length.
+ */
+ break;
+
+ case FT_STRINGZ:
+ if (length < -1) {
+ report_type_length_mismatch(NULL, "a string", length, TRUE);
+ }
+ if (length == -1) {
+ /* This can throw an exception */
+ /* XXX - do this without fetching the string? */
+ tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
+ }
+ item_length = length;
+ break;
+
+ case FT_UINT_STRING:
+ n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
+ item_length += n;
+ break;
+
+ case FT_STRINGZPAD:
+ case FT_ABSOLUTE_TIME:
+ case FT_RELATIVE_TIME:
+ case FT_IEEE_11073_SFLOAT:
+ case FT_IEEE_11073_FLOAT:
+ /*
+ * The length is the specified length.
+ */
+ break;
+
+ default:
+ g_error("hfinfo->type %d (%s) not handled\n",
+ hfinfo->type,
+ ftype_name(hfinfo->type));
+ DISSECTOR_ASSERT_NOT_REACHED();
+ break;
+ }
+ return item_length;
+}
+
static field_info *
new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
const gint start, const gint item_length)
@@ -8890,6 +9120,7 @@ proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
* but only after doing a bunch more work (which we can, in the common
* case, shortcut here).
*/
+ CHECK_FOR_NULL_TREE(tree);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
@@ -8968,6 +9199,7 @@ _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
}
/* Coast clear. Try and fake it */
+ CHECK_FOR_NULL_TREE(tree);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
@@ -9120,6 +9352,7 @@ proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbu
}
/* Coast clear. Try and fake it */
+ CHECK_FOR_NULL_TREE(tree);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
/* initialise the format string */
@@ -9244,6 +9477,7 @@ _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
header_field_info *hf_field;
/* We do not have to return a value, try to fake it as soon as possible */
+ CHECK_FOR_NULL_TREE(tree);
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
if (hf_field->bitmask != 0) {
@@ -9368,6 +9602,8 @@ proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
gchar *dst;
header_field_info *hf_field;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
switch (hf_field->type) {
@@ -9398,6 +9634,8 @@ proto_tree_add_uint64_bits_format_value(proto_tree *tree, const int hfindex,
gchar *dst;
header_field_info *hf_field;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
switch (hf_field->type) {
@@ -9428,6 +9666,8 @@ proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
gchar *dst;
header_field_info *hf_field;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);
@@ -9447,6 +9687,8 @@ proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
gchar *dst;
header_field_info *hf_field;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
switch (hf_field->type) {
@@ -9477,6 +9719,8 @@ proto_tree_add_int64_bits_format_value(proto_tree *tree, const int hfindex,
gchar *dst;
header_field_info *hf_field;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
switch (hf_field->type) {
@@ -9507,6 +9751,8 @@ proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
gchar *dst;
header_field_info *hf_field;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
@@ -9526,6 +9772,8 @@ proto_tree_add_boolean_bits_format_value64(proto_tree *tree, const int hfindex,
gchar *dst;
header_field_info *hf_field;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
@@ -9545,6 +9793,8 @@ proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_
gint byte_offset;
gchar *string;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
@@ -9575,6 +9825,8 @@ proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *t
gint byte_offset;
gchar *string;
+ CHECK_FOR_NULL_TREE(tree);
+
TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
diff --git a/epan/proto.h b/epan/proto.h
index 51e4dc0bac..0b35a9ce54 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -1003,6 +1003,27 @@ proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
const gint start, gint length, const guint encoding);
/** Add an item to a proto_tree, using the text label registered to that item.
+ The item is extracted from the tvbuff handed to it.
+
+ Return the length of the item through the pointer.
+ @param tree the tree to append this item to
+ @param hfinfo field
+ @param tvb the tv buffer of the current data
+ @param start start of data in tvb
+ @param length length of data in tvb
+ @param encoding data encoding
+ @param retval pointer to variable to set to the item length
+ @return the newly created item */
+WS_DLL_PUBLIC proto_item *
+proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
+ const gint start, gint length, const guint encoding, gint *retval);
+
+WS_DLL_PUBLIC proto_item *
+proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
+ const gint start, gint length,
+ const guint encoding, gint *retval);
+
+/** Add an item to a proto_tree, using the text label registered to that item.
The item is extracted from the tvbuff handed to it, and the retrieved
value is also set to *retval so the caller gets it back for other uses.
@@ -1019,7 +1040,7 @@ encoding in the tvbuff
The length argument must
be set to the appropriate size of the native type as in other proto_add routines.
-Integers of 8, 16, 24 and 32 bits can be retreived with these functions.
+Integers of 8, 16, 24 and 32 bits can be retrieved with these functions.
@param tree the tree to append this item to
@param hfindex field
@@ -2735,6 +2756,9 @@ proto_custom_set(proto_tree* tree, GSList *field_id,
#define proto_tree_add_item(tree, hfinfo, tvb, start, length, encoding) \
proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding)
+#define proto_tree_add_item_ret_length(tree, hfinfo, tvb, start, length, encoding, retval) \
+ proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, retval)
+
#define proto_tree_add_boolean(tree, hfinfo, tvb, start, length, value) \
proto_tree_add_boolean(tree, (hfinfo)->id, tvb, start, length, value)
diff --git a/epan/wslua/wslua_tree.c b/epan/wslua/wslua_tree.c
index a002d2708e..66ae4869ef 100644
--- a/epan/wslua/wslua_tree.c
+++ b/epan/wslua/wslua_tree.c
@@ -801,6 +801,7 @@ static int TreeItem_get_len(lua_State* L) {
TreeItem ti = checkTreeItem(L,1);
int len = 0;
+ /* XXX - this is *NOT* guaranteed to return a correct value! */
len = proto_item_get_len(ti->item);
lua_pushinteger(L, len > 0 ? len : 0);