Merge branch 'bugfix/fix_ble_reg_notify_no_fail' into 'master'

validate handle in esp_ble_gattc_register_for_notify

Closes BLERP-2717

See merge request espressif/esp-idf!47793
This commit is contained in:
Island
2026-05-18 17:22:49 +08:00
3 changed files with 50 additions and 4 deletions

View File

@@ -997,6 +997,22 @@ esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id,
* 1. This function triggers `ESP_GATTC_REG_FOR_NOTIFY_EVT`.
* 2. You should call `esp_ble_gattc_write_char_descr()` after this API to write Client Characteristic Configuration (CCC) descriptor to the value of 1 (Enable Notification) or 2 (Enable Indication).
* 3. `handle` must be greater than 0.
* 4. This API should be invoked only after service discovery for the target
* peer has completed (i.e. after `ESP_GATTC_SEARCH_CMPL_EVT` has been
* received, or after a previously persisted cache has been loaded). The
* recommended way to obtain `handle` is via the cache accessor APIs such
* as `esp_ble_gattc_get_all_char` or `esp_ble_gattc_get_char_by_uuid`.
* 5. When the GATT cache for `server_bda` is ready, the stack will validate
* `handle` against the cache: it must refer to a characteristic value
* whose properties include Notify or Indicate. If this validation fails,
* `ESP_GATTC_REG_FOR_NOTIFY_EVT` reports `ESP_GATT_ILLEGAL_PARAMETER`
* and the registration is rejected. If the cache is not yet ready (for
* example the API is called before service discovery completes), the
* stack skips this validation for backward compatibility, but in that
* case any incoming notification whose handle does not match a prior
* registration will be silently dropped by the host. Calling the API
* with an invalid handle in that window is therefore strongly
* discouraged.
*
* @return
* - ESP_OK: Success

View File

@@ -2208,10 +2208,16 @@ void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPL
if (p_clcb != NULL) {
bta_gattc_proc_other_indication(p_clcb, op, p_data, &notify);
}
} else if (op == GATTC_OPTYPE_INDICATION) {
/* no one interested and need ack? */
APPL_TRACE_DEBUG("%s no one interested, ack now", __func__);
GATTC_SendHandleValueConfirm(conn_id, handle);
} else {
/* No app registered for this handle: drop the PDU, but log it
* so the common "registered a wrong handle" bug is visible
* instead of silently failing. */
APPL_TRACE_WARNING("drop %s, handle 0x%04x not registered",
(op == GATTC_OPTYPE_INDICATION) ? "ind" : "notif",
handle);
if (op == GATTC_OPTYPE_INDICATION) {
GATTC_SendHandleValueConfirm(conn_id, handle);
}
}
}
}

View File

@@ -917,6 +917,7 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
BD_ADDR bda, UINT16 handle)
{
tBTA_GATTC_RCB *p_clreg;
tBTA_GATTC_SERV *p_srcb;
tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
UINT8 i;
@@ -926,6 +927,29 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
return status;
}
/* If cache is ready, validate handle is a notify/indicate-capable
* characteristic value handle; otherwise skip (legacy behaviour). */
p_srcb = bta_gattc_find_srcb(bda);
if (p_srcb != NULL && p_srcb->p_srvc_cache != NULL &&
p_srcb->state == BTA_GATTC_SERV_IDLE) {
tBTA_GATTC_CHARACTERISTIC *p_char =
bta_gattc_get_characteristic_srcb(p_srcb, handle);
if (p_char == NULL) {
APPL_TRACE_ERROR("reg notif: bad handle 0x%04x", handle);
return BTA_GATT_ILLEGAL_PARAMETER;
}
if ((p_char->properties & (BTA_GATT_CHAR_PROP_BIT_NOTIFY |
BTA_GATT_CHAR_PROP_BIT_INDICATE)) == 0) {
APPL_TRACE_ERROR("reg notif: handle 0x%04x prop 0x%02x not notif/ind",
handle, p_char->properties);
return BTA_GATT_ILLEGAL_PARAMETER;
}
} else {
APPL_TRACE_WARNING("reg notif: cache not ready, skip check");
}
if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL) {
for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++) {
if ( p_clreg->notif_reg[i].in_use &&