From 0c4e881911efcf0ddc1278a0ed2bd100d8d06c43 Mon Sep 17 00:00:00 2001 From: Jeff Morriss Date: Wed, 12 Jan 2011 02:25:08 +0000 Subject: [PATCH] Introduce, and start using, tvb_get_const_stringz(). This function returns a pointer to a NULL-terminated string in the TVB. It is no safer than dissectors which call tvb_get_strsize() and then tvb_get_ptr() but it makes it clear that this usage of tvb_get_ptr() is safe. This function is slightly more efficient than tvb_get_ephemeral_stringz()--but only as long as we're not using composite TVBs. svn path=/trunk/; revision=35493 --- doc/README.developer | 16 ++++-- epan/dissectors/packet-catapult-dct2000.c | 60 ++++++++++------------- epan/libwireshark.def | 1 + epan/tvbuff.c | 43 ++++++++++++---- epan/tvbuff.h | 10 +++- 5 files changed, 81 insertions(+), 49 deletions(-) diff --git a/doc/README.developer b/doc/README.developer index 4109f166db..56e3424466 100644 --- a/doc/README.developer +++ b/doc/README.developer @@ -1277,20 +1277,26 @@ free() this buffer, it will happen automatically once the a new capture or file is opened. guint8 *tvb_get_stringz(tvbuff_t *tvb, gint offset, gint *lengthp); +const guint8 *tvb_get_const stringz(tvbuff_t *tvb, gint offset, gint *lengthp); guint8 *tvb_get_ephemeral_stringz(tvbuff_t *tvb, gint offset, gint *lengthp); gchar *tvb_get_ephemeral_unicode_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding); guint8 *tvb_get_seasonal_stringz(tvbuff_t *tvb, gint offset, gint *lengthp); -Returns a null-terminated buffer, allocated with "g_malloc()", -containing data from the specified tvbuff, starting at the -specified offset, and containing all characters from the tvbuff up to -and including a terminating null character in the tvbuff. "*lengthp" -will be set to the length of the string, including the terminating null. +Returns a null-terminated buffer containing data from the specified tvbuff, +starting at the specified offset, and containing all characters from the +tvbuff up to and including a terminating null character in the tvbuff. +"*lengthp" will be set to the length of the string, including the terminating +null. tvb_get_stringz() returns a buffer allocated by g_malloc() so you must g_free() it when you are finished with the string. Failure to g_free() this buffer will lead to memory leaks. +tvb_get_const_stringz() returns a pointer to the (const) string in the tvbuff. +You do not need to free() this buffer, it will happen automatically once the +next packet is dissected. This function is slightly more efficient than the +others because it does not allocate memory and copy the string. + tvb_get_ephemeral_stringz() returns a buffer allocated from a special heap with a lifetime until the next packet is dissected. You do not need to free() this buffer, it will happen automatically once the next packet is diff --git a/epan/dissectors/packet-catapult-dct2000.c b/epan/dissectors/packet-catapult-dct2000.c index b442ed81a8..df20f0e398 100644 --- a/epan/dissectors/packet-catapult-dct2000.c +++ b/epan/dissectors/packet-catapult-dct2000.c @@ -206,7 +206,7 @@ static dissector_handle_t pdcp_lte_handle; void proto_register_catapult_dct2000(void); -static dissector_handle_t look_for_dissector(char *protocol_name); +static dissector_handle_t look_for_dissector(const char *protocol_name); static void parse_outhdr_string(const guchar *outhdr_string); static void attach_fp_info(packet_info *pinfo, gboolean received, const char *protocol_name, int variant); @@ -1082,7 +1082,7 @@ static void dissect_pdcp_lte(tvbuff_t *tvb, gint offset, /* Look up dissector by protocol name. Fix up known name mis-matches. This includes exact matches and prefixes (e.g. "diameter_rx" -> "diameter") */ -static dissector_handle_t look_for_dissector(char *protocol_name) +static dissector_handle_t look_for_dissector(const char *protocol_name) { /* Use known aliases and protocol name prefixes */ if (strcmp(protocol_name, "tbcp") == 0) { @@ -1714,22 +1714,22 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_item *ti = NULL; gint offset = 0; gint context_length; + const char *context_name; guint8 port_number; - gint protocol_start; gint protocol_length; - gint timestamp_start; gint timestamp_length; - gint variant_start; + const char *timestamp_string; gint variant_length; - gint outhdr_start; + const char *variant_string; gint outhdr_length; + const char *outhdr_string; guint8 direction; tvbuff_t *next_tvb; int encap; dissector_handle_t protocol_handle = 0; dissector_handle_t heur_protocol_handle = 0; int sub_dissector_result = 0; - char *protocol_name; + const char *protocol_name; gboolean is_comment; /* Set Protocol */ @@ -1749,7 +1749,7 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) /* by the wiretap module */ /* Context Name */ - context_length = tvb_strsize(tvb, offset); + context_name = tvb_get_const_stringz(tvb, offset, &context_length); if (dct2000_tree) { proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_context, tvb, offset, context_length, FALSE); @@ -1765,33 +1765,29 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset++; /* Timestamp in file */ - timestamp_start = offset; - timestamp_length = tvb_strsize(tvb, offset); + timestamp_string = tvb_get_const_stringz(tvb, offset, ×tamp_length); if (dct2000_tree) { /* TODO: this is *very* slow, but float version adds trailing digits when displayed as a custom column... */ proto_tree_add_double(dct2000_tree, hf_catapult_dct2000_timestamp, tvb, offset, timestamp_length, - atof(tvb_get_ptr(tvb, offset, timestamp_length))); + atof(timestamp_string)); } offset += timestamp_length; /* DCT2000 protocol name */ - protocol_start = offset; - protocol_length = tvb_strsize(tvb, offset); + protocol_name = tvb_get_const_stringz(tvb, offset, &protocol_length); if (dct2000_tree) { proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_protocol, tvb, offset, protocol_length, FALSE); } - protocol_name = (char*)tvb_get_ptr(tvb, protocol_start, protocol_length); is_comment = (strcmp(protocol_name, "comment") == 0); offset += protocol_length; /* Protocol Variant */ - variant_start = offset; - variant_length = tvb_strsize(tvb, offset); + variant_string = tvb_get_const_stringz(tvb, offset, &variant_length); if (!is_comment) { proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_variant, tvb, offset, variant_length, FALSE); @@ -1799,8 +1795,7 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset += variant_length; /* Outhdr (shown as string) */ - outhdr_start = offset; - outhdr_length = tvb_strsize(tvb, offset); + outhdr_string = tvb_get_const_stringz(tvb, offset, &outhdr_length); if (!is_comment && (outhdr_length > 1)) { proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_outhdr, tvb, offset, outhdr_length, FALSE); @@ -1825,12 +1820,12 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) /* Add useful details to protocol tree label */ proto_item_append_text(ti, " context=%s.%u t=%s %c prot=%s (v=%s)", - tvb_get_ptr(tvb, 0, context_length), + context_name, port_number, - tvb_get_ptr(tvb, timestamp_start, timestamp_length), + timestamp_string, (direction == 0) ? 'S' : 'R', protocol_name, - tvb_get_ptr(tvb, variant_start, variant_length)); + variant_string); @@ -1843,26 +1838,25 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) (strcmp(protocol_name, "fp_r8") == 0) || (strcmp(protocol_name, "fpiur_r5") == 0)) { - parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length)); - attach_fp_info(pinfo, direction, protocol_name, - atoi((char*)tvb_get_ptr(tvb, variant_start, variant_length))); + parse_outhdr_string(outhdr_string); + attach_fp_info(pinfo, direction, protocol_name, atoi(variant_string)); } /* LTE MAC needs info attached */ else if (strcmp(protocol_name, "mac_r8_lte") == 0) { - parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length)); + parse_outhdr_string(outhdr_string); attach_mac_lte_info(pinfo); } /* LTE RLC needs info attached */ else if (strcmp(protocol_name, "rlc_r8_lte") == 0) { - parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length)); + parse_outhdr_string(outhdr_string); attach_rlc_lte_info(pinfo); } /* LTE PDCP needs info attached */ else if (strcmp(protocol_name, "pdcp_r8_lte") == 0) { - parse_outhdr_string(tvb_get_ptr(tvb, outhdr_start, outhdr_length)); + parse_outhdr_string(outhdr_string); attach_pdcp_lte_info(pinfo); } @@ -1922,14 +1916,14 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) if (direction == 0) { col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "%s.%u", - tvb_get_ptr(tvb, 0, context_length), + context_name, port_number); } else if (direction == 1) { col_add_fstr(pinfo->cinfo, COL_DEF_DST, "%s.%u", - tvb_get_ptr(tvb, 0, context_length), + context_name, port_number); } @@ -2336,12 +2330,12 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) col_add_fstr(pinfo->cinfo, COL_INFO, "Not dissected (context=%s.%u t=%s %c prot=%s (v=%s))", - tvb_get_ptr(tvb, 0, context_length), + context_name, port_number, - tvb_get_ptr(tvb, timestamp_start, timestamp_length), + timestamp_string, (direction == 0) ? 'S' : 'R', - tvb_get_ptr(tvb, protocol_start, protocol_length), - tvb_get_ptr(tvb, variant_start, variant_length)); + protocol_name, + variant_string); } else { /* Show number of dissected bytes */ diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 5d7a33ca61..0aa0202a69 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -1041,6 +1041,7 @@ tvb_get_bits8 tvb_get_bits16 tvb_get_bits32 tvb_get_bits64 +tvb_get_const_stringz tvb_get_ephemeral_faked_unicode tvb_get_ephemeral_string tvb_get_ephemeral_stringz diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 7aabb14d62..82488c9c24 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -2257,11 +2257,11 @@ tvb_get_string(tvbuff_t *tvb, const gint offset, const gint length) /* * Unicode (UTF-16) version of tvb_get_string() - * + * * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN * * Specify length in bytes - * + * * Returns an UTF-8 string that must be freed by the caller */ gchar * @@ -2336,11 +2336,11 @@ tvb_get_ephemeral_string(tvbuff_t *tvb, const gint offset, const gint length) /* * Unicode (UTF-16) version of tvb_get_ephemeral_string() - * + * * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN * * Specify length in bytes - * + * * Returns an ep_ allocated UTF-8 string */ gchar * @@ -2432,6 +2432,31 @@ tvb_get_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp) *lengthp = size; return strptr; } +/* + * Given a tvbuff and an offset, with the offset assumed to refer to + * a null-terminated string, find the length of that string (and throw + * an exception if the tvbuff ends before we find the null), ensure that + * the TVB is flat, and return a pointer to the string (in the TVB). + * Also return the length of the string (including the terminating null) + * through a pointer. + * + * As long as we aren't using composite TVBs, this saves the cycles used + * (often unnecessariliy) in allocating a buffer and copying the string into + * it. (If we do start using composite TVBs, we may want to replace this + * function with the _ephemeral versoin.) + */ +const guint8 * +tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp) +{ + guint size; + const guint8 *strptr; + + size = tvb_strsize(tvb, offset); + strptr = tvb_get_ptr(tvb, offset, size); + if (lengthp) + *lengthp = size; + return strptr; +} /* * Given a tvbuff and an offset, with the offset assumed to refer to * a null-terminated string, find the length of that string (and throw @@ -2462,7 +2487,7 @@ tvb_get_ephemeral_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp) /* * Unicode (UTF-16) version of tvb_get_ephemeral_stringz() - * + * * Encoding paramter should be ENC_BIG_ENDIAN or ENC_LITTLE_ENDIAN * * Returns an ep_ allocated UTF-8 string and updates lengthp pointer with length of string (in bytes) @@ -3002,8 +3027,8 @@ tvb_bytes_to_str_punct(tvbuff_t *tvb, const gint offset, const gint len, const g /* * Given a tvbuff, an offset into the tvbuff, and a length that starts * at that offset (which may be -1 for "all the way to the end of the - * tvbuff"), fetch BCD encoded digits from a tvbuff starting from either - * the low or high half byte, formating the digits according to an input digit set, + * tvbuff"), fetch BCD encoded digits from a tvbuff starting from either + * the low or high half byte, formating the digits according to an input digit set, * if NUll a default digit set of 0-9 returning "?" for overdecadic digits will be used. * A pointer to the EP allocated string will be returned. * Note a tvbuff content of 0xf is considered a 'filler' and will end the conversion. @@ -3040,7 +3065,7 @@ tvb_bcd_dig_to_ep_str(tvbuff_t *tvb, const gint offset, const gint len, dgt_set_ octet = tvb_get_guint8(tvb,t_offset); if (!skip_first){ - digit_str[i] = dgt->out[octet & 0x0f]; + digit_str[i] = dgt->out[octet & 0x0f]; i++; } skip_first = FALSE; @@ -3053,7 +3078,7 @@ tvb_bcd_dig_to_ep_str(tvbuff_t *tvb, const gint offset, const gint len, dgt_set_ if (octet == 0x0f) /* odd number bytes - hit filler */ break; - digit_str[i] = dgt->out[octet & 0x0f]; + digit_str[i] = dgt->out[octet & 0x0f]; i++; t_offset++; diff --git a/epan/tvbuff.h b/epan/tvbuff.h index 62189e2228..cd9d63b659 100644 --- a/epan/tvbuff.h +++ b/epan/tvbuff.h @@ -517,6 +517,11 @@ extern guint8 *tvb_get_seasonal_string(tvbuff_t *tvb, const gint offset, const g * MUST be g_free() by the caller in order not to leak * memory. * + * tvb_get_const_stringz() returns a constant (unmodifiable) string that does + * not need to be freed, instead it will automatically be + * freed once the next packet is dissected. It is slightly + * more efficient than the other routines. + * * tvb_get_ephemeral_stringz() returns a string that does not need to be freed, * instead it will automatically be freed once the next * packet is dissected. @@ -528,6 +533,7 @@ extern guint8 *tvb_get_seasonal_string(tvbuff_t *tvb, const gint offset, const g * or file is opened. */ extern guint8 *tvb_get_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp); +extern const guint8 *tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp); extern guint8 *tvb_get_ephemeral_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp); extern gchar *tvb_get_ephemeral_unicode_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding); extern guint8 *tvb_get_seasonal_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp); @@ -659,8 +665,8 @@ extern gchar *tvb_bytes_to_str(tvbuff_t *tvb, const gint offset, const gint len) /** * Given a tvbuff, an offset into the tvbuff, and a length that starts * at that offset (which may be -1 for "all the way to the end of the - * tvbuff"), fetch BCD encoded digits from a tvbuff starting from either - * the low or high half byte, formating the digits according to an input digit set, + * tvbuff"), fetch BCD encoded digits from a tvbuff starting from either + * the low or high half byte, formating the digits according to an input digit set, * if NUll a default digit set of 0-9 returning "?" for overdecadic digits will be used. * A pointer to the EP allocated string will be returned. * Note a tvbuff content of 0xf is considered a 'filler' and will end the conversion.