hidclass.sys: Handle failures when parsing descriptor.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-06-07 11:06:57 +02:00 committed by Alexandre Julliard
parent 573e8bada9
commit 4c6c8c5456
1 changed files with 29 additions and 10 deletions

View File

@ -464,7 +464,7 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
{ {
int usages_top = 0; int usages_top = 0;
USAGE usages[256]; USAGE usages[256];
unsigned int i; int i;
for (i = index; i < length;) for (i = index; i < length;)
{ {
@ -479,6 +479,7 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
{ {
/* Long data items: Should be unused */ /* Long data items: Should be unused */
ERR("Long Data Item, should be unused\n"); ERR("Long Data Item, should be unused\n");
return -1;
} }
else else
{ {
@ -506,7 +507,7 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
case TAG_MAIN_FEATURE: case TAG_MAIN_FEATURE:
for (j = 0; j < caps->ReportCount; j++) for (j = 0; j < caps->ReportCount; j++)
{ {
feature = calloc(1, sizeof(*feature)); if (!(feature = calloc(1, sizeof(*feature)))) return -1;
list_add_tail(&collection->features, &feature->entry); list_add_tail(&collection->features, &feature->entry);
if (bTag == TAG_MAIN_INPUT) if (bTag == TAG_MAIN_INPUT)
feature->type = HidP_Input; feature->type = HidP_Input;
@ -531,7 +532,8 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
break; break;
case TAG_MAIN_COLLECTION: case TAG_MAIN_COLLECTION:
{ {
struct collection *subcollection = calloc(1, sizeof(struct collection)); struct collection *subcollection;
if (!(subcollection = calloc(1, sizeof(struct collection)))) return -1;
list_add_tail(&collection->collections, &subcollection->entry); list_add_tail(&collection->collections, &subcollection->entry);
subcollection->parent = collection; subcollection->parent = collection;
/* Only set our collection once... /* Only set our collection once...
@ -552,13 +554,14 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
parse_collection(bSize, itemVal, subcollection); parse_collection(bSize, itemVal, subcollection);
i = parse_descriptor(descriptor, i+1, length, feature_index, collection_index, subcollection, caps, stack); if ((i = parse_descriptor(descriptor, i+1, length, feature_index, collection_index, subcollection, caps, stack)) < 0) return i;
continue; continue;
} }
case TAG_MAIN_END_COLLECTION: case TAG_MAIN_END_COLLECTION:
return i; return i;
default: default:
ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType); ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
return -1;
} }
} }
else if (bType == TAG_TYPE_GLOBAL) else if (bType == TAG_TYPE_GLOBAL)
@ -597,7 +600,8 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
break; break;
case TAG_GLOBAL_PUSH: case TAG_GLOBAL_PUSH:
{ {
struct caps_stack *saved = malloc(sizeof(*saved)); struct caps_stack *saved;
if (!(saved = malloc(sizeof(*saved)))) return -1;
saved->caps = *caps; saved->caps = *caps;
TRACE("Push\n"); TRACE("Push\n");
list_add_tail(stack, &saved->entry); list_add_tail(stack, &saved->entry);
@ -617,11 +621,15 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
free(saved); free(saved);
} }
else else
{
ERR("Pop but no stack!\n"); ERR("Pop but no stack!\n");
return -1;
}
break; break;
} }
default: default:
ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType); ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
return -1;
} }
} }
else if (bType == TAG_TYPE_LOCAL) else if (bType == TAG_TYPE_LOCAL)
@ -630,7 +638,10 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
{ {
case TAG_LOCAL_USAGE: case TAG_LOCAL_USAGE:
if (usages_top == sizeof(usages)) if (usages_top == sizeof(usages))
{
ERR("More than 256 individual usages defined\n"); ERR("More than 256 individual usages defined\n");
return -1;
}
else else
{ {
usages[usages_top++] = getValue(bSize, itemVal, FALSE); usages[usages_top++] = getValue(bSize, itemVal, FALSE);
@ -674,10 +685,14 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
break; break;
default: default:
ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType); ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
return -1;
} }
} }
else else
{
ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType); ERR("Unknown (bTag: 0x%x, bType: 0x%x)\n", bTag, bType);
return -1;
}
i += bSize; i += bSize;
} }
@ -927,7 +942,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_coll
nodes_offset = size; nodes_offset = size;
size += node_count * sizeof(WINE_HID_LINK_COLLECTION_NODE); size += node_count * sizeof(WINE_HID_LINK_COLLECTION_NODE);
data = calloc(1, size); if (!(data = calloc(1, size))) return NULL;
data->magic = HID_MAGIC; data->magic = HID_MAGIC;
data->dwSize = size; data->dwSize = size;
data->caps.Usage = base_collection->caps.NotRange.Usage; data->caps.Usage = base_collection->caps.NotRange.Usage;
@ -982,14 +997,18 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
list_init(&caps_stack); list_init(&caps_stack);
base = calloc(1, sizeof(*base)); if (!(base = calloc(1, sizeof(*base)))) return NULL;
base->index = 1; base->index = 1;
list_init(&base->features); list_init(&base->features);
list_init(&base->collections); list_init(&base->collections);
memset(&caps, 0, sizeof(caps)); memset(&caps, 0, sizeof(caps));
cidx = 0; cidx = 0;
parse_descriptor(descriptor, 0, length, &feature_count, &cidx, base, &caps, &caps_stack); if (parse_descriptor(descriptor, 0, length, &feature_count, &cidx, base, &caps, &caps_stack) < 0)
{
free_collection(base);
return NULL;
}
debug_collection(base); debug_collection(base);
@ -1004,8 +1023,8 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
} }
} }
data = build_PreparseData(base, cidx); if ((data = build_PreparseData(base, cidx)))
debug_print_preparsed(data); debug_print_preparsed(data);
free_collection(base); free_collection(base);
return data; return data;