diff --git a/components/esp_hid/src/esp_hid_common.c b/components/esp_hid/src/esp_hid_common.c index 364073ed9cb..d30b0f2d4d7 100644 --- a/components/esp_hid/src/esp_hid_common.c +++ b/components/esp_hid/src/esp_hid_common.c @@ -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 +#include #include #include #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) {