From 9ad2dd11adae02037f6500eecdbdb28d423f5f30 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Tue, 30 Dec 2025 11:53:40 +0800 Subject: [PATCH] fix(ble/hci): Fix OOB read in ble_adv_scan_combined example (cherry picked from commit c76283260003781735618a827418dfed9f481cba) Co-authored-by: zhanghaipeng --- .../hci/ble_adv_scan_combined/main/app_bt.c | 64 ++++++++++++++----- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c b/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c index 1f2a6a8399..c8fc988fcb 100644 --- a/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c +++ b/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c @@ -1,7 +1,7 @@ /* * BLE Combined Advertising and Scanning Example. * - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -18,8 +18,10 @@ static const char *TAG = "BLE_ADV_SCAN"; +#define SCAN_LOCAL_NAME_MAX_LEN 32 + typedef struct { - char scan_local_name[32]; + char scan_local_name[SCAN_LOCAL_NAME_MAX_LEN]; uint8_t name_len; } ble_scan_local_name_t; @@ -187,28 +189,58 @@ static void hci_cmd_send_ble_set_adv_data(void) ESP_LOGI(TAG, "Starting BLE advertising with name \"%s\"", adv_name); } -static esp_err_t get_local_name (uint8_t *data_msg, uint8_t data_len, ble_scan_local_name_t *scanned_packet) +static esp_err_t get_local_name(uint8_t *data_msg, uint8_t data_len, ble_scan_local_name_t *scanned_packet) { - uint8_t curr_ptr = 0, curr_len, curr_type; + uint8_t curr_ptr = 0; + + /* Initialize output structure */ + scanned_packet->name_len = 0; + scanned_packet->scan_local_name[0] = '\0'; + while (curr_ptr < data_len) { - curr_len = data_msg[curr_ptr++]; - curr_type = data_msg[curr_ptr++]; + /* Ensure there is at least 1 byte for length field */ + if (curr_ptr >= data_len) { + return ESP_FAIL; + } + uint8_t curr_len = data_msg[curr_ptr++]; + + /* Length of 0 indicates end of AD structures or invalid data */ if (curr_len == 0) { return ESP_FAIL; } - /* Search for current data type and see if it contains name as data (0x08 or 0x09). */ - if (curr_type == 0x08 || curr_type == 0x09) { - for (uint8_t i = 0; i < curr_len - 1; i += 1) { - scanned_packet->scan_local_name[i] = data_msg[curr_ptr + i]; - } - scanned_packet->name_len = curr_len - 1; - return ESP_OK; - } else { - /* Search for next data. Current length includes 1 octate for AD Type (2nd octate). */ - curr_ptr += curr_len - 1; + /* Ensure there is at least 1 byte for type field */ + if (curr_ptr >= data_len) { + return ESP_FAIL; } + uint8_t curr_type = data_msg[curr_ptr++]; + + /* Calculate data field length (curr_len includes type byte) */ + uint8_t data_field_len = curr_len - 1; + + /* Verify remaining buffer has enough data */ + if (curr_ptr + data_field_len > data_len) { + return ESP_FAIL; + } + + /* Check for Local Name type (0x08: Shortened, 0x09: Complete) */ + if (curr_type == 0x08 || curr_type == 0x09) { + /* Limit copy length to prevent buffer overflow */ + uint8_t copy_len = data_field_len; + if (copy_len > SCAN_LOCAL_NAME_MAX_LEN - 1) { + copy_len = SCAN_LOCAL_NAME_MAX_LEN - 1; + } + + memcpy(scanned_packet->scan_local_name, &data_msg[curr_ptr], copy_len); + scanned_packet->scan_local_name[copy_len] = '\0'; /* Ensure null termination */ + scanned_packet->name_len = copy_len; + return ESP_OK; + } + + /* Move to next AD structure */ + curr_ptr += data_field_len; } + return ESP_FAIL; }