From cb16dff992c3844936bf5829f19e5a5247458503 Mon Sep 17 00:00:00 2001 From: Guy Harris Date: Sat, 12 Apr 2014 15:26:34 -0700 Subject: Get rid of more tvb_get_nstringz* calls. Add an FT_STRINGZPAD type, for null-padded strings (typically fixed-length fields, where the string can be up to the length of the field, and is null-padded if it's shorter than that), and use it. Use IS_FT_STRING() in more cases, so that less code needs to know what types are string types. Add a tvb_get_stringzpad() routine, which gets null-padded strings. Currently, it does the same thing that tvb_get_string_enc() does, but that might change if we don't store string values as null-terminated strings. Change-Id: I46f56e130de8f419a19b56ded914e24cc7518a66 Reviewed-on: https://code.wireshark.org/review/1082 Reviewed-by: Guy Harris --- epan/dfilter/dfunctions.c | 53 ++++++++++------------------- epan/dfilter/semcheck.c | 4 +++ epan/dissectors/packet-fw1.c | 3 +- epan/dissectors/packet-hartip.c | 52 ++++++++++------------------- epan/dissectors/packet-ospf.c | 4 +-- epan/dissectors/packet-quake3.c | 18 +++++++--- epan/dissectors/packet-quakeworld.c | 20 +++++------ epan/dissectors/packet-rsync.c | 8 +++-- epan/dissectors/packet-smb-browse.c | 28 ++++++---------- epan/dissectors/packet-tacacs.c | 11 ++++--- epan/dissectors/packet-who.c | 17 ++++------ epan/ftypes/ftype-string.c | 43 ++++++++++++++++++++++++ epan/ftypes/ftypes.h | 3 +- epan/packet.c | 3 ++ epan/proto.c | 66 +++++++++++++++++++++++-------------- epan/proto.h | 13 ++++---- epan/tvbuff.c | 18 ++++++++++ epan/tvbuff.h | 23 +++++++++++++ 18 files changed, 232 insertions(+), 155 deletions(-) (limited to 'epan') diff --git a/epan/dfilter/dfunctions.c b/epan/dfilter/dfunctions.c index 81e446b500..cb59184775 100644 --- a/epan/dfilter/dfunctions.c +++ b/epan/dfilter/dfunctions.c @@ -61,26 +61,18 @@ string_walk(GList* arg1list, GList **retval, gchar(*conv_func)(gchar)) arg1 = arg1list; while (arg1) { arg_fvalue = (fvalue_t *)arg1->data; - switch (fvalue_type_ftenum(arg_fvalue)) { - case FT_STRING: - case FT_STRINGZ: - case FT_UINT_STRING: - s = (char *)ep_strdup((gchar *)fvalue_get(arg_fvalue)); - for (c = s; *c; c++) { - /**c = string_ascii_to_lower(*c);*/ - *c = conv_func(*c); - } - - new_ft_string = fvalue_new(FT_STRING); - fvalue_set_string(new_ft_string, s); - *retval = g_list_append(*retval, new_ft_string); - break; - - /* XXX - it would be nice to handle FT_TVBUFF, too */ - - default: - break; - } + /* XXX - it would be nice to handle FT_TVBUFF, too */ + if (IS_FT_STRING(fvalue_type_ftenum(arg_fvalue))) { + s = (char *)ep_strdup((gchar *)fvalue_get(arg_fvalue)); + for (c = s; *c; c++) { + /**c = string_ascii_to_lower(*c);*/ + *c = conv_func(*c); + } + + new_ft_string = fvalue_new(FT_STRING); + fvalue_set_string(new_ft_string, s); + *retval = g_list_append(*retval, new_ft_string); + } arg1 = arg1->next; } @@ -112,19 +104,11 @@ df_func_len(GList* arg1list, GList *arg2junk _U_, GList **retval) arg1 = arg1list; while (arg1) { arg_fvalue = (fvalue_t *)arg1->data; - switch (fvalue_type_ftenum(arg_fvalue)) { - case FT_STRING: - case FT_STRINGZ: - case FT_UINT_STRING: - ft_len = fvalue_new(FT_UINT32); - fvalue_set_uinteger(ft_len, (guint) strlen((char *)fvalue_get(arg_fvalue))); - *retval = g_list_append(*retval, ft_len); - break; - - /* XXX - it would be nice to handle other types */ - - default: - break; + /* XXX - it would be nice to handle other types */ + if (IS_FT_STRING(fvalue_type_ftenum(arg_fvalue))) { + ft_len = fvalue_new(FT_UINT32); + fvalue_set_uinteger(ft_len, (guint) strlen((char *)fvalue_get(arg_fvalue))); + *retval = g_list_append(*retval, ft_len); } arg1 = arg1->next; } @@ -187,8 +171,7 @@ ul_semcheck_params(int param_num, stnode_t *st_node) case STTYPE_FIELD: hfinfo = (header_field_info *)stnode_data(st_node); ftype = hfinfo->type; - if (ftype != FT_STRING && ftype != FT_STRINGZ - && ftype != FT_UINT_STRING) { + if (IS_FT_STRING(ftype)) { dfilter_fail("Only strings can be used in upper() or lower() or len()"); THROW(TypeError); } diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 501dce4e3e..c76859dc28 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -116,10 +116,12 @@ compatible_ftypes(ftenum_t a, ftenum_t b) case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: + case FT_STRINGZPAD: switch (b) { case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: + case FT_STRINGZPAD: return TRUE; default: return FALSE; @@ -186,6 +188,7 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: + case FT_STRINGZPAD: case FT_EUI64: case FT_PCRE: case FT_GUID: @@ -314,6 +317,7 @@ is_bytes_type(enum ftenum type) case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: + case FT_STRINGZPAD: case FT_BOOLEAN: case FT_FRAMENUM: case FT_UINT8: diff --git a/epan/dissectors/packet-fw1.c b/epan/dissectors/packet-fw1.c index 51ed2942a0..e4ff9e3a7d 100644 --- a/epan/dissectors/packet-fw1.c +++ b/epan/dissectors/packet-fw1.c @@ -160,8 +160,7 @@ dissect_fw1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) if (fw1_with_uuid) iface_len = 6; - interface_name=(char *)wmem_alloc(wmem_packet_scope(), iface_len+1); - tvb_get_nstringz0(tvb, 2, iface_len+1, interface_name); + interface_name=tvb_get_stringzpad(wmem_packet_scope(), tvb, 2, iface_len, ENC_ASCII|ENC_NA); /* Known interface name - if not, remember it */ found=FALSE; diff --git a/epan/dissectors/packet-hartip.c b/epan/dissectors/packet-hartip.c index c8edad2b94..6d6b0d71d3 100644 --- a/epan/dissectors/packet-hartip.c +++ b/epan/dissectors/packet-hartip.c @@ -384,26 +384,7 @@ dissect_float(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset) } static gint -dissect_string(proto_tree *tree, int hf, const char *name, int len, - tvbuff_t *tvb, gint offset) -{ - proto_item *ti; - char *str; - - str = (char *)wmem_alloc(wmem_packet_scope(), 256); - - ti = proto_tree_add_item(tree, hf, tvb, offset, len, ENC_NA); - if (len < 256) { - (void) tvb_get_nstringz0(tvb, offset, len + 1, str); - proto_item_set_text(ti, "%s: %s", name, str); - } - - return len; -} - -static gint -dissect_packAscii(proto_tree *tree, int hf, const char *name, int len, - tvbuff_t *tvb, gint offset) +dissect_packAscii(proto_tree *tree, int hf, tvbuff_t *tvb, gint offset, int len) { gushort usIdx; gushort usGroupCnt; @@ -411,19 +392,16 @@ dissect_packAscii(proto_tree *tree, int hf, const char *name, int len, gushort usMask; gint iIndex; gint i = 0; - proto_item *ti; gushort buf[4]; guint8 *tmp; char *str = NULL; - str = (char *)wmem_alloc(wmem_packet_scope(), 256+1); - - ti = proto_tree_add_item(tree, hf, tvb, offset, len, ENC_NA); - - DISSECTOR_ASSERT(len < 3 * (256/4)); tmp = (guint8 *)wmem_alloc0(wmem_packet_scope(), len); tvb_memcpy(tvb, tmp, offset, len); + /* Maximum possible unpacked length = (len / 3) * 4 */ + str = (char *)wmem_alloc(wmem_packet_scope(), ((len / 3) * 4)+1); + iIndex = 0; usMaxGroups = (gushort)(len / 3); for (usGroupCnt = 0; usGroupCnt < usMaxGroups; usGroupCnt++) { @@ -446,7 +424,8 @@ dissect_packAscii(proto_tree *tree, int hf, const char *name, int len, } } str[i] = '\0'; - proto_item_set_text(ti, "%s: %s", name, str); + + proto_tree_add_string(tree, hf, tvb, offset, len, str); return len; } @@ -630,8 +609,8 @@ static gint dissect_cmd13(proto_tree *body_tree, tvbuff_t *tvb, gint offset, gint bodylen) { if (bodylen >= 21) { - offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_tag, "Tag", 6, tvb, offset); - offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_packed_descriptor, "descriptor", 12, tvb, offset); + offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 6); + offset += dissect_packAscii(body_tree, hf_hartip_pt_rsp_packed_descriptor, tvb, offset, 12); offset += dissect_byte(body_tree, hf_hartip_pt_rsp_day, tvb, offset); offset += dissect_byte(body_tree, hf_hartip_pt_rsp_month, tvb, offset); /*offset += */dissect_byte(body_tree, hf_hartip_pt_rsp_year, tvb, offset); @@ -688,13 +667,16 @@ dissect_parse_hart_cmds(proto_tree *body_tree, tvbuff_t *tvb, guint8 cmd, return dissect_cmd9(body_tree, tvb, offset, bodylen); case 12: if (bodylen >= 24) - return dissect_packAscii(body_tree, hf_hartip_pt_rsp_message, "Message", 24, tvb, offset); + return dissect_packAscii(body_tree, hf_hartip_pt_rsp_message, tvb, offset, 24); break; case 13: return dissect_cmd13(body_tree, tvb, offset, bodylen); case 20: - if (bodylen >= 32) - return dissect_string(body_tree, hf_hartip_pt_rsp_tag, "Tag", 32, tvb, offset); + if (bodylen >= 32) { + proto_tree_add_item(body_tree, hf_hartip_pt_rsp_tag, tvb, offset, 32, + ENC_ASCII|ENC_NA); + return 32; + } break; case 48: return dissect_cmd48(body_tree, tvb, offset, bodylen); @@ -1438,7 +1420,7 @@ proto_register_hartip(void) /* command 13 */ { &hf_hartip_pt_rsp_packed_descriptor, { "Descriptor", "hart_ip.pt.rsp.descriptor", - FT_BYTES, BASE_NONE, NULL, 0x0, + FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hartip_pt_rsp_day, @@ -1460,14 +1442,14 @@ proto_register_hartip(void) /* Tag */ { &hf_hartip_pt_rsp_tag, { "Tag", "hart_ip.pt.rsp.tag", - FT_BYTES, BASE_NONE, NULL, 0x0, + FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL } }, /* Message */ { &hf_hartip_pt_rsp_message, { "Message", "hart_ip.pt.rsp.message", - FT_BYTES, BASE_NONE, NULL, 0x0, + FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL } }, diff --git a/epan/dissectors/packet-ospf.c b/epan/dissectors/packet-ospf.c index 281ba265b6..6d1a0a3b20 100644 --- a/epan/dissectors/packet-ospf.c +++ b/epan/dissectors/packet-ospf.c @@ -1042,7 +1042,7 @@ dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) guint16 cksum, computed_cksum; guint length, reported_length; guint16 auth_type; - char auth_data[8+1]; + guint8 *auth_data; int crypto_len = 0; unsigned int ospf_header_length; guint8 instance_ID; @@ -1210,7 +1210,7 @@ dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) break; case OSPF_AUTH_SIMPLE: - tvb_get_nstringz0(tvb, 16, 8+1, auth_data); + auth_data = tvb_get_string_enc(wmem_packet_scope(), tvb, 16, 8, ENC_ASCII|ENC_NA); proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data); break; diff --git a/epan/dissectors/packet-quake3.c b/epan/dissectors/packet-quake3.c index c9d5fad22d..3b8bfc328f 100644 --- a/epan/dissectors/packet-quake3.c +++ b/epan/dissectors/packet-quake3.c @@ -144,7 +144,7 @@ dissect_quake3_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *cl_tree = NULL; proto_item *text_item = NULL; proto_tree *text_tree = NULL; - guint8 text[2048]; + guint8 *text; int len; int offset; guint32 marker; @@ -165,11 +165,21 @@ dissect_quake3_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo _U_, /* all the rest of the packet is just text */ offset = 4; - len = tvb_get_nstringz0(tvb, offset, sizeof(text), text); + /* + * XXX - is there ever more than one null-terminated string in + * the packet? + * + * XXX - is the string guaranteed to be null-terminated (so + * that if there's no NUL at the end, it's an error)? + * + * XXX - are non-ASCII characters supported and, if so, what + * encoding is used for them? + */ + text = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII|ENC_NA); if (cl_tree) { text_item = proto_tree_add_string(cl_tree, hf_quake3_connectionless_text, - tvb, offset, len + 1, text); + tvb, offset, len, text); text_tree = proto_item_add_subtree(text_item, ett_quake3_connectionless_text); } @@ -321,7 +331,7 @@ dissect_quake3_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo _U_, val_to_str_const(command, names_command, "Unknown")); } - /*offset += len + 1;*/ + /*offset += len;*/ } diff --git a/epan/dissectors/packet-quakeworld.c b/epan/dissectors/packet-quakeworld.c index 16ac74a911..4ceb8a4fad 100644 --- a/epan/dissectors/packet-quakeworld.c +++ b/epan/dissectors/packet-quakeworld.c @@ -90,8 +90,8 @@ static char com_token[MAX_TEXT_SIZE+1]; static int com_token_start; static int com_token_length; -static char * -COM_Parse (char *data) +static const char * +COM_Parse (const char *data) { int c; int len; @@ -198,7 +198,7 @@ Cmd_Argv_length(int arg) static void -Cmd_TokenizeString(char* text) +Cmd_TokenizeString(const char* text) { int start; @@ -349,7 +349,7 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, { proto_tree *cl_tree = NULL; proto_tree *text_tree = NULL; - guint8 text[MAX_TEXT_SIZE+1]; + guint8 *text; int len; int offset; guint32 marker; @@ -370,13 +370,13 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, /* all the rest of the packet is just text */ offset = 4; - len = tvb_get_nstringz0(tvb, offset, sizeof(text), text); + text = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII|ENC_NA); /* actually, we should look for a eol char and stop already there */ if (cl_tree) { proto_item *text_item; text_item = proto_tree_add_string(cl_tree, hf_quakeworld_connectionless_text, - tvb, offset, len + 1, text); + tvb, offset, len, text); text_tree = proto_item_add_subtree(text_item, ett_quakeworld_connectionless_text); } @@ -469,7 +469,7 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, tvb, offset, command_len, command); argument_item = proto_tree_add_string(text_tree, hf_quakeworld_connectionless_arguments, - tvb, offset + Cmd_Argv_start(1), len + 1 - Cmd_Argv_start(1), + tvb, offset + Cmd_Argv_start(1), len - Cmd_Argv_start(1), text + Cmd_Argv_start(1)); argument_tree = proto_item_add_subtree(argument_item, ett_quakeworld_connectionless_arguments); @@ -504,7 +504,7 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, command_len = 1; } else { command = "Unknown"; - command_len = len; + command_len = len - 1; } } else { @@ -529,7 +529,7 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, /* string, atoi */ } else { command = "Unknown"; - command_len = len; + command_len = len - 1; } } @@ -539,7 +539,7 @@ dissect_quakeworld_ConnectionlessPacket(tvbuff_t *tvb, packet_info *pinfo, proto_tree_add_string(text_tree, hf_quakeworld_connectionless_command, tvb, offset, command_len, command); } - /*offset += len + 1;*/ + /*offset += len;*/ } diff --git a/epan/dissectors/packet-rsync.c b/epan/dissectors/packet-rsync.c index 95eb7f36c1..9448d70f7e 100644 --- a/epan/dissectors/packet-rsync.c +++ b/epan/dissectors/packet-rsync.c @@ -123,17 +123,19 @@ static dissector_handle_t rsync_handle; static guint glb_rsync_tcp_port = TCP_PORT_RSYNC; +#define VERSION_LEN 4 /* 2 digits for main version; '.'; 1 digit for sub version */ + static void dissect_rsync_version_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *rsync_tree, enum rsync_who me) { int offset = 0; - gchar version[5]; /* 2 digits for main version; '.'; 1 digit for sub version; NULL */ + guint8 *version; proto_tree_add_item(rsync_tree, &hfi_rsync_hdr_magic, tvb, offset, RSYNCD_MAGIC_HEADER_LEN, ENC_ASCII|ENC_NA); offset += RSYNCD_MAGIC_HEADER_LEN; offset += 1; /* skip the space */ - proto_tree_add_item(rsync_tree, &hfi_rsync_hdr_version, tvb, offset, sizeof(version)-1, ENC_ASCII|ENC_NA); - tvb_get_nstringz0(tvb, offset, sizeof(version), version); + proto_tree_add_item(rsync_tree, &hfi_rsync_hdr_version, tvb, offset, VERSION_LEN, ENC_ASCII|ENC_NA); + version = tvb_get_string_enc(wmem_packet_scope(),tvb, offset, VERSION_LEN, ENC_ASCII|ENC_NA); col_add_fstr(pinfo->cinfo, COL_INFO, "%s Initialisation (Version %s)", (me == SERVER ? "Server" : "Client"), version); } diff --git a/epan/dissectors/packet-smb-browse.c b/epan/dissectors/packet-smb-browse.c index 3c55bd1250..4c556ed0af 100644 --- a/epan/dissectors/packet-smb-browse.c +++ b/epan/dissectors/packet-smb-browse.c @@ -570,6 +570,7 @@ dissect_smb_server_type_flags(tvbuff_t *tvb, int offset, packet_info *pinfo, return offset; } +#define HOST_NAME_LEN 16 static void dissect_mailslot_browse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) @@ -579,8 +580,7 @@ dissect_mailslot_browse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tr proto_tree *tree = NULL; proto_item *item = NULL; guint32 periodicity; - gchar host_name[17]; - gchar *utf8_host_name; + guint8 *host_name; gint namelen; guint8 server_count, reset_cmd; guint8 os_major_ver, os_minor_ver; @@ -621,22 +621,16 @@ dissect_mailslot_browse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tr offset += 4; /* server name */ - tvb_get_nstringz0(tvb, offset, sizeof(host_name), host_name); - utf8_host_name = g_convert(host_name, strlen(host_name), - "UTF-8", "CP437", NULL, NULL, NULL); - if (utf8_host_name == NULL) - utf8_host_name = host_name; - col_append_fstr(pinfo->cinfo, COL_INFO, " %s", utf8_host_name); + host_name = tvb_get_stringzpad(wmem_packet_scope(), tvb, offset, HOST_NAME_LEN, ENC_CP437|ENC_NA); + col_append_fstr(pinfo->cinfo, COL_INFO, " %s", host_name); proto_tree_add_string_format(tree, hf_server_name, - tvb, offset, 16, - utf8_host_name, + tvb, offset, HOST_NAME_LEN, + host_name, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? "Domain/Workgroup: %s": "Host Name: %s", - utf8_host_name); - if (utf8_host_name != host_name) - g_free(utf8_host_name); - offset += 16; + host_name); + offset += HOST_NAME_LEN; /* Windows version (See "OSVERSIONINFO Structure" on MSDN) */ os_major_ver = tvb_get_guint8(tvb, offset); @@ -838,7 +832,6 @@ dissect_mailslot_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tr /* Put in something, and replace it later */ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown command:0x%02x")); - if (parent_tree) { item = proto_tree_add_item(parent_tree, proto_smb_browse, tvb, offset, -1, ENC_NA); @@ -853,7 +846,6 @@ dissect_mailslot_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tr case BROWSE_DOMAIN_ANNOUNCEMENT: case BROWSE_LOCAL_MASTER_ANNOUNCEMENT: case BROWSE_HOST_ANNOUNCE: - /* update count */ proto_tree_add_item(tree, hf_update_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; @@ -888,7 +880,7 @@ dissect_mailslot_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tr offset += 2; /* server name */ - host_name = tvb_get_const_stringz(tvb, offset, &namelen); + host_name = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &namelen, ENC_CP437|ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", host_name); proto_tree_add_item(tree, hf_server_name, @@ -900,7 +892,7 @@ dissect_mailslot_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tr proto_tree_add_item(tree, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? hf_mb_server_name : hf_server_comment, - tvb, offset, namelen, ENC_ASCII|ENC_NA); + tvb, offset, namelen, ENC_CP437|ENC_NA); break; } } diff --git a/epan/dissectors/packet-tacacs.c b/epan/dissectors/packet-tacacs.c index 29339e7f6e..2ea2c8105b 100644 --- a/epan/dissectors/packet-tacacs.c +++ b/epan/dissectors/packet-tacacs.c @@ -396,14 +396,15 @@ static void dissect_tacplus_args_list( tvbuff_t *tvb, proto_tree *tree, int data_off, int len_off, int arg_cnt ) { int i; - guint8 buff[257]; + int len; + guint8 *value; for(i=0;ihash_table = g_hash_table_new_full( g_str_hash, g_str_equal, &g_free, diff --git a/epan/proto.c b/epan/proto.c index f3dd81d922..5adc0497fa 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -1641,6 +1641,19 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, new_fi->length = n + length; break; + case FT_STRINGZPAD: + /* + * XXX - currently, string values are null- + * terminated, so a "zero-padded" string + * isn't special. If we represent string + * values as something that includes a counted + * array of bytes, we'll need to strip + * trailing NULs. + */ + proto_tree_set_string_tvb(new_fi, tvb, start, length, + encoding); + break; + case FT_ABSOLUTE_TIME: /* * Absolute times can be in any of a number of @@ -2665,8 +2678,8 @@ proto_tree_set_int64_tvb(field_info *fi, tvbuff_t *tvb, gint start, proto_tree_set_uint64(fi, value); } -/* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string, - * and frees it when the proto_tree is destroyed. */ +/* Add a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD to a proto_tree. Creates + * own copy of string, and frees it when the proto_tree is destroyed. */ proto_item * proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, const char* value) @@ -2676,7 +2689,7 @@ proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo); - DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ); + DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ || hfinfo->type == FT_STRINGZPAD); if (hfinfo->display == STR_UNICODE) { DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL)); @@ -2728,9 +2741,9 @@ proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, return pi; } -/* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive - * field info update instead of only updating the representation as does - * proto_item_append_text() +/* Appends string data to a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD, + * allowing progressive field info update instead of only updating the + * representation as does proto_item_append_text() */ /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM() * speed optimization. @@ -2764,7 +2777,7 @@ proto_item_append_string(proto_item *pi, const char *str) /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */ return; } - DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ); + DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ || hfinfo->type == FT_STRINGZPAD); old_str = (guint8 *)fvalue_get(&fi->value); if (old_str && old_str[0]) new_str = ep_strconcat(old_str, str, NULL); @@ -3541,9 +3554,9 @@ get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint */ if (*length == -1) { /* - * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields, - * a length of -1 means "set the length to what remains in - * the tvbuff". + * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING, and + * FT_STRINGZPAD fields, a length of -1 means "set the + * length to what remains in the tvbuff". * * The assumption is either that * @@ -3605,6 +3618,7 @@ get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint case FT_NONE: case FT_BYTES: case FT_STRING: + case FT_STRINGZPAD: *length = tvb_ensure_captured_length_remaining(tvb, start); DISSECTOR_ASSERT(*length >= 0); break; @@ -4076,6 +4090,7 @@ proto_custom_set(proto_tree* tree, const int field_id, gint occurrence, case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: + case FT_STRINGZPAD: bytes = (guint8 *)fvalue_get(&finfo->value); offset_r += protoo_strlcpy(result+offset_r, hfinfo_format_text(hfinfo, bytes), @@ -4987,22 +5002,23 @@ static const value_string hf_types[] = { { FT_DOUBLE, "FT_DOUBLE" }, { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" }, { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" }, - { FT_STRING, "FT_STRING" }, - { FT_STRINGZ, "FT_STRINGZ" }, + { FT_STRING, "FT_STRING" }, + { FT_STRINGZ, "FT_STRINGZ" }, { FT_UINT_STRING, "FT_UINT_STRING" }, - { FT_ETHER, "FT_ETHER" }, - { FT_BYTES, "FT_BYTES" }, + { FT_ETHER, "FT_ETHER" }, + { FT_BYTES, "FT_BYTES" }, { FT_UINT_BYTES, "FT_UINT_BYTES" }, - { FT_IPv4, "FT_IPv4" }, - { FT_IPv6, "FT_IPv6" }, - { FT_IPXNET, "FT_IPXNET" }, - { FT_FRAMENUM, "FT_FRAMENUM" }, - { FT_PCRE, "FT_PCR" }, - { FT_GUID, "FT_GUID" }, - { FT_OID, "FT_OID" }, - { FT_REL_OID, "FT_REL_OID" }, - { FT_SYSTEM_ID, "FT_SYSTEM_ID" }, - { 0, NULL } }; + { FT_IPv4, "FT_IPv4" }, + { FT_IPv6, "FT_IPv6" }, + { FT_IPXNET, "FT_IPXNET" }, + { FT_FRAMENUM, "FT_FRAMENUM" }, + { FT_PCRE, "FT_PCRE" }, + { FT_GUID, "FT_GUID" }, + { FT_OID, "FT_OID" }, + { FT_REL_OID, "FT_REL_OID" }, + { FT_SYSTEM_ID, "FT_SYSTEM_ID" }, + { FT_STRINGZPAD, "FT_STRINGZPAD" }, + { 0, NULL } }; static const value_string hf_display[] = { { BASE_NONE, "BASE_NONE" }, @@ -5213,6 +5229,7 @@ tmp_fld_check_assert(header_field_info *hfinfo) case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: + case FT_STRINGZPAD: switch (hfinfo->display) { case STR_ASCII: case STR_UNICODE: @@ -5671,6 +5688,7 @@ proto_item_fill_label(field_info *fi, gchar *label_str) case FT_STRING: case FT_STRINGZ: case FT_UINT_STRING: + case FT_STRINGZPAD: bytes = (guint8 *)fvalue_get(&fi->value); label_fill(label_str, 0, hfinfo, hfinfo_format_text(hfinfo, bytes)); break; diff --git a/epan/proto.h b/epan/proto.h index b34443a2c7..fdb4aaee00 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -1231,7 +1231,7 @@ extern proto_item * proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, const guint8* value_ptr, const char *format, ...) G_GNUC_PRINTF(7,8); -/** Add a FT_STRING to a proto_tree. +/** Add a FT_STRING or FT_STRINGZPAD to a proto_tree. @param tree the tree to append this item to @param hfindex field index @param tvb the tv buffer of the current data @@ -1243,9 +1243,9 @@ WS_DLL_PUBLIC proto_item * proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, const char* value); -/** Add a formatted FT_STRING to a proto_tree, with the format generating - the string for the value and with the field name being included - automatically. +/** Add a formatted FT_STRING or FT_STRINGZPAD to a proto_tree, with the + format generating the string for the value and with the field name + being included automatically. @param tree the tree to append this item to @param hfindex field index @param tvb the tv buffer of the current data @@ -1260,8 +1260,9 @@ proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, const char* value, const char *format, ...) G_GNUC_PRINTF(7,8); -/** Add a formatted FT_STRING to a proto_tree, with the format generating - the entire string for the entry, including any field name. +/** Add a formatted FT_STRING or FT_STRINGZPAD to a proto_tree, with the + format generating the entire string for the entry, including any field + name. @param tree the tree to append this item to @param hfindex field index @param tvb the tv buffer of the current data diff --git a/epan/tvbuff.c b/epan/tvbuff.c index 91e2202be2..fcdb0e22c9 100644 --- a/epan/tvbuff.c +++ b/epan/tvbuff.c @@ -2532,6 +2532,24 @@ tvb_get_string_enc(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, return strbuf; } +/* + * This is like tvb_get_string_enc(), except that it handles null-padded + * strings. + * + * Currently, string values are stored as UTF-8 null-terminated strings, + * so nothing needs to be done differently for null-padded strings; we + * could save a little memory by not storing the null padding. + * + * If we ever store string values differently, in a fashion that doesn't + * involve null termination, that might change. + */ +guint8 * +tvb_get_stringzpad(wmem_allocator_t *scope, tvbuff_t *tvb, const gint offset, + const gint length, const guint encoding) +{ + return tvb_get_string_enc(scope, tvb, offset, length, encoding); +} + /* * These routines are like the above routines, except that they handle * null-terminated strings. They find the length of that string (and diff --git a/epan/tvbuff.h b/epan/tvbuff.h index 7d51a6ac0c..896a13587f 100644 --- a/epan/tvbuff.h +++ b/epan/tvbuff.h @@ -556,6 +556,29 @@ WS_DLL_PUBLIC guint8 *tvb_get_string_enc(wmem_allocator_t *scope, WS_DLL_PUBLIC gchar *tvb_get_ts_23_038_7bits_string(wmem_allocator_t *scope, tvbuff_t *tvb, const gint bit_offset, gint no_of_chars); +/** + * Given an allocator scope, a tvbuff, a byte offset, a byte length, and + * a string encoding, with the specified offset and length referring to + * a null-padded string in the specified encoding: + * + * allocate a buffer using the specified scope; + * + * convert the string from the specified encoding to UTF-8, possibly + * mapping some characters or invalid octet sequences to the Unicode + * REPLACEMENT CHARACTER, and put the resulting UTF-8 string, plus a + * trailing '\0', into that buffer; + * + * and return a pointer to the buffer. + * + * Throws an exception if the tvbuff ends before the string does. + * + * If scope is set to NULL it is the user's responsibility to wmem_free() + * the memory allocated. Otherwise memory is automatically freed when the + * scope lifetime is reached. + */ +WS_DLL_PUBLIC guint8 *tvb_get_stringzpad(wmem_allocator_t *scope, + tvbuff_t *tvb, const gint offset, const gint length, const guint encoding); + /** * Given an allocator scope, a tvbuff, a byte offset, a pointer to a * gint, and a string encoding, with the specified offset referring to -- cgit v1.2.3