mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
fix(bt/bluedroid): fixed integer overflow in HID report descriptor parser
Closes SEC-084
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2017-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_log.h"
|
||||
@@ -65,6 +67,19 @@ static int add_report(temp_hid_report_map_t *map, esp_hid_report_item_t *item)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_report_len_bits_to(uint16_t *len_bits, uint16_t size, uint16_t count)
|
||||
{
|
||||
uint32_t add = (uint32_t)size * (uint32_t)count;
|
||||
uint32_t new_len = (uint32_t)(*len_bits) + add;
|
||||
|
||||
if (new_len > UINT16_MAX) {
|
||||
ESP_LOGE(TAG, "report length overflow: %u + %u * %u", *len_bits, size, count);
|
||||
return -1;
|
||||
}
|
||||
*len_bits = (uint16_t)new_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_report(hid_report_params_t *report, bool first)
|
||||
{
|
||||
if (s_temp_hid_report_map == NULL) {
|
||||
@@ -290,15 +305,34 @@ static int handle_cmd(hid_report_cmd_t *cmd)
|
||||
} else if (cmd->cmd == HID_RM_USAGE) {
|
||||
s_report_params.inner_usage = cmd->value;
|
||||
} else if (cmd->cmd == HID_RM_REPORT_SIZE) {
|
||||
s_report_size = cmd->value;
|
||||
if (cmd->value > UINT16_MAX) {
|
||||
ESP_LOGE(TAG, "REPORT_SIZE too large: %" PRIu32, cmd->value);
|
||||
s_parse_step = PARSE_WAIT_USAGE_PAGE;
|
||||
return -1;
|
||||
}
|
||||
s_report_size = (uint16_t)cmd->value;
|
||||
} else if (cmd->cmd == HID_RM_REPORT_COUNT) {
|
||||
s_report_count = cmd->value;
|
||||
if (cmd->value > UINT16_MAX) {
|
||||
ESP_LOGE(TAG, "REPORT_COUNT too large: %" PRIu32, cmd->value);
|
||||
s_parse_step = PARSE_WAIT_USAGE_PAGE;
|
||||
return -1;
|
||||
}
|
||||
s_report_count = (uint16_t)cmd->value;
|
||||
} else if (cmd->cmd == HID_RM_INPUT) {
|
||||
s_report_params.input_len += (s_report_size * s_report_count);
|
||||
if (add_report_len_bits_to(&s_report_params.input_len, s_report_size, s_report_count) != 0) {
|
||||
s_parse_step = PARSE_WAIT_USAGE_PAGE;
|
||||
return -1;
|
||||
}
|
||||
} else if (cmd->cmd == HID_RM_OUTPUT) {
|
||||
s_report_params.output_len += (s_report_size * s_report_count);
|
||||
if (add_report_len_bits_to(&s_report_params.output_len, s_report_size, s_report_count) != 0) {
|
||||
s_parse_step = PARSE_WAIT_USAGE_PAGE;
|
||||
return -1;
|
||||
}
|
||||
} else if (cmd->cmd == HID_RM_FEATURE) {
|
||||
s_report_params.feature_len += (s_report_size * s_report_count);
|
||||
if (add_report_len_bits_to(&s_report_params.feature_len, s_report_size, s_report_count) != 0) {
|
||||
s_parse_step = PARSE_WAIT_USAGE_PAGE;
|
||||
return -1;
|
||||
}
|
||||
} else if (cmd->cmd == HID_RM_COLLECTION) {
|
||||
s_collection_depth += 1;
|
||||
} else if (cmd->cmd == HID_RM_END_COLLECTION) {
|
||||
|
||||
Reference in New Issue
Block a user