Use proto_tree_add_item() for UTF-16 strings when dissecting string

descriptors.

Make sure the length in string descriptors is at least 2, so that we
have a valid string or string-list length.

svn path=/trunk/; revision=54084
This commit is contained in:
Guy Harris 2013-12-14 03:44:12 +00:00
parent e57d150ec9
commit 5dd7b7388b
2 changed files with 23 additions and 24 deletions

View File

@ -188,6 +188,7 @@ static gint ett_endpoint_bmAttributes = -1;
static gint ett_endpoint_wMaxPacketSize = -1;
static expert_field ei_usb_bLength_even = EI_INIT;
static expert_field ei_usb_bLength_too_short = EI_INIT;
static expert_field ei_usb_desc_length_invalid = EI_INIT;
static const int *usb_endpoint_fields[] = {
@ -1271,15 +1272,16 @@ dissect_usb_setup_get_configuration_response(packet_info *pinfo _U_, proto_tree
* for URB_CONTROL_INPUT / GET DESCRIPTOR
*/
void dissect_usb_descriptor_header(proto_tree *tree,
tvbuff_t *tvb, int offset,
value_string_ext *type_val_str)
proto_item * dissect_usb_descriptor_header(proto_tree *tree,
tvbuff_t *tvb, int offset,
value_string_ext *type_val_str)
{
guint8 desc_type;
proto_item *type_item = NULL;
proto_item *length_item;
proto_item *type_item;
proto_tree_add_item(tree, hf_usb_bLength,
length_item = proto_tree_add_item(tree, hf_usb_bLength,
tvb, offset, 1, ENC_LITTLE_ENDIAN);
offset++;
@ -1292,6 +1294,8 @@ void dissect_usb_descriptor_header(proto_tree *tree,
type_val_str = &std_descriptor_type_vals_ext;
proto_item_append_text(type_item, " (%s)",
val_to_str_ext(desc_type, type_val_str, "unknown"));
return length_item;
}
/* 9.6.2 */
@ -1533,6 +1537,7 @@ dissect_usb_string_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree,
proto_tree *tree = NULL;
int old_offset = offset;
guint8 len;
proto_item *len_item;
if (parent_tree) {
item = proto_tree_add_text(parent_tree, tvb, offset, -1, "STRING DESCRIPTOR");
@ -1543,8 +1548,6 @@ dissect_usb_string_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree,
/* The USB spec says that the languages / the string are UTF16 and not
0-terminated, i.e. the length field must contain an even number */
if (len & 0x1) {
proto_item *len_item;
/* bLength */
len_item = proto_tree_add_item(tree, hf_usb_bLength, tvb, offset, 1, ENC_LITTLE_ENDIAN);
expert_add_info(pinfo, len_item, &ei_usb_bLength_even);
@ -1553,10 +1556,15 @@ dissect_usb_string_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree,
proto_tree_add_item(tree, hf_usb_bDescriptorType, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
}
else
dissect_usb_descriptor_header(tree, tvb, offset, NULL);
len_item = dissect_usb_descriptor_header(tree, tvb, offset, NULL);
offset += 2;
/* Report an error, and give up, if the length is < 2 */
if (len < 2) {
expert_add_info(pinfo, len_item, &ei_usb_bLength_too_short);
return offset;
}
if (!usb_trans_info->u.get_descriptor.index) {
/* list of languanges */
while(len>(offset-old_offset)) {
@ -1565,18 +1573,8 @@ dissect_usb_string_descriptor(packet_info *pinfo _U_, proto_tree *parent_tree,
offset+=2;
}
} else {
char *str;
guint8 str_len;
/* Make sure that tvb_get_unicode_string() gets an even
string length even if the length field contains an (invalid)
odd number.
*/
str_len = (len-2) & ~0x1;
/* unicode string */
str = tvb_get_unicode_string(wmem_packet_scope(), tvb, offset, str_len, ENC_LITTLE_ENDIAN);
proto_tree_add_string(tree, hf_usb_bString, tvb, offset, len-2, str);
/* UTF-16 string */
proto_tree_add_item(tree, hf_usb_bString, tvb, offset, len-2, ENC_UTF_16 | ENC_LITTLE_ENDIAN);
offset += len-2;
}
@ -4122,6 +4120,7 @@ proto_register_usb(void)
static ei_register_info ei[] = {
{ &ei_usb_bLength_even, { "usb.bLength.even", PI_PROTOCOL, PI_WARN, "Invalid STRING DESCRIPTOR Length (must be even)", EXPFILL }},
{ &ei_usb_bLength_too_short, { "usb.bLength.too_short", PI_MALFORMED, PI_ERROR, "Invalid STRING DESCRIPTOR Length (must be 2 or larger)", EXPFILL }},
{ &ei_usb_desc_length_invalid, { "usb.desc_length.invalid", PI_MALFORMED, PI_ERROR, "Invalid descriptor length", EXPFILL }},
};

View File

@ -188,9 +188,9 @@ typedef struct _usb_tap_data_t {
usb_conv_info_t *get_usb_iface_conv_info(packet_info *pinfo, guint8 interface_num);
void dissect_usb_descriptor_header(proto_tree *tree,
tvbuff_t *tvb, int offset,
value_string_ext *type_val_str);
proto_item * dissect_usb_descriptor_header(proto_tree *tree,
tvbuff_t *tvb, int offset,
value_string_ext *type_val_str);
void dissect_usb_endpoint_address(proto_tree *tree, tvbuff_t *tvb, int offset);
#endif