From b9eaab2dce9d79d6603bd9d6b60bf0efaa3eb640 Mon Sep 17 00:00:00 2001 From: Zhi Wei Jian Date: Wed, 10 Jun 2026 19:53:36 +0800 Subject: [PATCH] fix(ble/bluedroid): fix GATT client API parameter validation (cherry picked from commit 653477c3e94ba133be97070421922e2896d51ec2) Co-authored-by: zhiweijian --- .../bt/host/bluedroid/api/esp_gattc_api.c | 93 ++++++++++++++----- .../bluedroid/api/include/api/esp_gattc_api.h | 79 +++++++++++----- 2 files changed, 126 insertions(+), 46 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_gattc_api.c b/components/bt/host/bluedroid/api/esp_gattc_api.c index 2a61abeb053..ff4a0684e76 100644 --- a/components/bt/host/bluedroid/api/esp_gattc_api.c +++ b/components/bt/host/bluedroid/api/esp_gattc_api.c @@ -397,7 +397,9 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *svc_uuid, esp_gattc_service_elem_t *result, uint16_t *count, uint16_t offset) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (result == NULL || count == NULL || *count == 0) { return ESP_GATT_INVALID_PDU; @@ -415,14 +417,16 @@ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if, esp_gattc_char_elem_t *result, uint16_t *count, uint16_t offset) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (result == NULL || count == NULL || *count == 0) { return ESP_GATT_INVALID_PDU; } - if ((start_handle == 0) && (end_handle == 0)) { + if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) { *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -437,7 +441,9 @@ esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if, esp_gattc_descr_elem_t *result, uint16_t *count, uint16_t offset) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (char_handle == 0) { return ESP_GATT_INVALID_HANDLE; @@ -459,13 +465,15 @@ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if, esp_gattc_char_elem_t *result, uint16_t *count) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (result == NULL || count == NULL || *count == 0) { return ESP_GATT_INVALID_PDU; } - if (start_handle == 0 && end_handle == 0) { + if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) { *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -484,12 +492,19 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if, esp_gattc_descr_elem_t *result, uint16_t *count) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (result == NULL || count == NULL || *count == 0) { return ESP_GATT_INVALID_PDU; } + if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) { + *count = 0; + return ESP_GATT_INVALID_HANDLE; + } + uint16_t conn_hdl = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id); return btc_ble_gattc_get_descr_by_uuid(conn_hdl, start_handle, end_handle, char_uuid, descr_uuid, result, count); } @@ -501,7 +516,9 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if, esp_gattc_descr_elem_t *result, uint16_t *count) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (result == NULL || count == NULL || *count == 0) { return ESP_GATT_INVALID_PDU; @@ -524,13 +541,15 @@ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if, esp_gattc_incl_svc_elem_t *result, uint16_t *count) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (result == NULL || count == NULL || *count == 0) { return ESP_GATT_INVALID_PDU; } - if (start_handle == 0 && end_handle == 0) { + if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) { *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -547,13 +566,17 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if, uint16_t char_handle, uint16_t *count) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (count == NULL) { return ESP_GATT_INVALID_PDU; } - if ((start_handle == 0 && end_handle == 0) && (type != ESP_GATT_DB_DESCRIPTOR)) { + /* start_handle/end_handle are ignored for ESP_GATT_DB_DESCRIPTOR (see esp_gattc_api.h). */ + if (type != ESP_GATT_DB_DESCRIPTOR && + ((start_handle == 0 && end_handle == 0) || start_handle > end_handle)) { *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -565,14 +588,16 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if, esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, esp_gattc_db_elem_t *db, uint16_t *count) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_GATT_WRONG_STATE; + } if (db == NULL || count == NULL || *count == 0) { return ESP_GATT_INVALID_PDU; } - if (start_handle == 0 && end_handle == 0) { + if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) { *count = 0; return ESP_GATT_INVALID_HANDLE; } @@ -644,10 +669,14 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if, return ESP_FAIL; } - if (start_handle == 0 || end_handle == 0) { + if ((start_handle == 0 && end_handle == 0) || start_handle > end_handle) { return ESP_GATT_INVALID_HANDLE; } + if (start_handle == 0) { + start_handle = 1; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_BY_TYPE; @@ -670,7 +699,12 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - if ((read_multi == NULL) || (read_multi->num_attr == 0) || (read_multi->num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) { + if (read_multi == NULL) { + return ESP_ERR_INVALID_ARG; + } + uint8_t num_attr = read_multi->num_attr; + + if ((num_attr == 0) || (num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) { return ESP_ERR_INVALID_ARG; } @@ -689,10 +723,10 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if, msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_MULTIPLE_CHAR; arg.read_multiple.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id); - arg.read_multiple.num_attr = read_multi->num_attr; + arg.read_multiple.num_attr = num_attr; arg.read_multiple.auth_req = auth_req; - memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t)*read_multi->num_attr); + memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t) * num_attr); return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } @@ -707,7 +741,12 @@ esp_err_t esp_ble_gattc_read_multiple_variable(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - if ((read_multi == NULL) || (read_multi->num_attr == 0) || (read_multi->num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) { + if (read_multi == NULL) { + return ESP_ERR_INVALID_ARG; + } + uint8_t num_attr = read_multi->num_attr; + + if ((num_attr == 0) || (num_attr > ESP_GATT_MAX_READ_MULTI_HANDLES)) { return ESP_ERR_INVALID_ARG; } @@ -726,9 +765,9 @@ esp_err_t esp_ble_gattc_read_multiple_variable(esp_gatt_if_t gattc_if, msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_MULTIPLE_VARIABLE_CHAR; arg.read_multiple.conn_id = BTC_GATT_CREATE_CONN_ID(gattc_if, conn_id); - arg.read_multiple.num_attr = read_multi->num_attr; + arg.read_multiple.num_attr = num_attr; arg.read_multiple.auth_req = auth_req; - memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t)*read_multi->num_attr); + memcpy(arg.read_multiple.handles, read_multi->handles, sizeof(uint16_t) * num_attr); return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } @@ -829,6 +868,10 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if ((value_len > 0) && (value == NULL)) { + return ESP_ERR_INVALID_ARG; + } + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); if (!gatt_check_connection_state_by_tcb(p_tcb)) { LOG_WARN("%s, The connection not created.", __func__); @@ -873,6 +916,10 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if ((value_len > 0) && (value == NULL)) { + return ESP_ERR_INVALID_ARG; + } + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); if (!gatt_check_connection_state_by_tcb(p_tcb)) { LOG_WARN("%s, The connection not created.", __func__); @@ -915,6 +962,10 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if ((value_len > 0) && (value == NULL)) { + return ESP_ERR_INVALID_ARG; + } + tGATT_TCB *p_tcb = gatt_get_tcb_by_idx(conn_id); if (!gatt_check_connection_state_by_tcb(p_tcb)) { LOG_WARN("%s, The connection not created.", __func__); diff --git a/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h b/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h index 65979ba4abf..800bcf5c768 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gattc_api.h @@ -519,8 +519,12 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, * 2. `esp_ble_gattc_cache_refresh` can be used to discover services again. * * @return - * - ESP_OK: Success - * - ESP_FAIL: Failure + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled + * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 + * - ESP_GATT_NOT_FOUND: No matching service was found in the local cache + * - ESP_GATT_INVALID_OFFSET: `offset` is out of range of the matched services + * - ESP_GATT_NO_RESOURCES: Failed to allocate memory for the UUID lookup */ esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *svc_uuid, esp_gattc_service_elem_t *result, uint16_t *count, uint16_t offset); @@ -538,13 +542,17 @@ esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t con * * @note * 1. This API does not trigger any event. - * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. + * 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and + * `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches + * cached attributes from the beginning of the handle range. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 - * - ESP_FAIL: Failure due to other reasons + * - ESP_GATT_NOT_FOUND: No characteristic found in the given handle range + * - ESP_GATT_INVALID_OFFSET: `offset` is out of range of the matched characteristics */ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -568,10 +576,12 @@ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if, * 2. `char_handle` must be greater than 0. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled * - ESP_GATT_INVALID_HANDLE: Invalid GATT `char_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 - * - ESP_FAIL: Failure due to other reasons + * - ESP_GATT_NOT_FOUND: No descriptor found under the given characteristic + * - ESP_GATT_INVALID_OFFSET: `offset` is out of range of the matched descriptors */ esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -592,13 +602,16 @@ esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if, * * @note * 1. This API does not trigger any event. - * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. + * 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and + * `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches + * cached attributes from the beginning of the handle range. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 - * - ESP_FAIL: Failure due to other reasons + * - ESP_GATT_NOT_FOUND: No characteristic matching `char_uuid` found in the handle range */ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -622,12 +635,16 @@ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if, * * @note * 1. This API does not trigger any event. - * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. + * 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and + * `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches + * cached attributes from the beginning of the handle range. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 - * - ESP_FAIL: Failure due to other reasons + * - ESP_GATT_NOT_FOUND: No descriptor matching the given UUIDs found in the handle range */ esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -653,10 +670,11 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if, * 2. `char_handle` must be greater than 0. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled * - ESP_GATT_INVALID_HANDLE: Invalid GATT `char_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 - * - ESP_FAIL: Failure due to other reasons + * - ESP_GATT_NOT_FOUND: No descriptor matching `descr_uuid` found under `char_handle` */ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -678,12 +696,16 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if, * * @note * 1. This API does not trigger any event. - * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. + * 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and + * `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches + * cached attributes from the beginning of the handle range. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 - * - ESP_FAIL: Failure due to other reasons + * - ESP_GATT_NOT_FOUND: No included service matching `incl_uuid` found in the handle range */ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -707,13 +729,15 @@ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if, * * @note * 1. This API does not trigger any event. - * 2. `start_handle` must be greater than 0, and smaller than `end_handle` if the `type` is not `ESP_GATT_DB_DESCRIPTOR`. + * 2. If the `type` is not `ESP_GATT_DB_DESCRIPTOR`, `start_handle` must not be greater than + * `end_handle`, and `start_handle` and `end_handle` must not both be 0. 0 is allowed for + * `start_handle` alone and matches cached attributes from the beginning of the handle range. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle`, `end_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `count` - * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -735,13 +759,16 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if, * * @note * 1. This API does not trigger any event. - * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. + * 2. `start_handle` must not be greater than `end_handle`, and `start_handle` and + * `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and matches + * cached attributes from the beginning of the handle range. * * @return - * - ESP_OK: Success + * - ESP_GATT_OK: Success + * - ESP_GATT_WRONG_STATE: Bluedroid stack is not enabled * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle`, `end_handle` * - ESP_GATT_INVALID_PDU: NULL pointer to `db` or NULL pointer to `count` or the count value is 0 - * - ESP_FAIL: Failure due to other reasons + * - ESP_GATT_NOT_FOUND: No GATT database element found in the given handle range * */ esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, @@ -784,7 +811,9 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, * @note * 1. This function triggers `ESP_GATTC_READ_CHAR_EVT`. * 2. This function should be called only after the connection has been established. - * 3. `start_handle` must be greater than 0, and smaller than `end_handle`. + * 3. `start_handle` must not be greater than `end_handle`, and `start_handle` and + * `end_handle` must not both be 0. 0 is allowed for `start_handle` alone and is + * treated as 1 on air. * * @return * - ESP_OK: Success