Bluetooth: Host: Fix unsafe ccc cast
Changes the implementation of `bt_gatt_is_subscribed` to use the attribute read method instead of casting the user data pointer when extracting the CCC Attribute Value. Signed-off-by: Håvard Reierstad <haavard.reierstad@nordicsemi.no>
This commit is contained in:
parent
43149c1056
commit
68361eacfa
|
@ -3473,7 +3473,9 @@ static uint8_t disconnected_cb(const struct bt_gatt_attr *attr, uint16_t handle,
|
||||||
bool bt_gatt_is_subscribed(struct bt_conn *conn,
|
bool bt_gatt_is_subscribed(struct bt_conn *conn,
|
||||||
const struct bt_gatt_attr *attr, uint16_t ccc_type)
|
const struct bt_gatt_attr *attr, uint16_t ccc_type)
|
||||||
{
|
{
|
||||||
const struct _bt_gatt_ccc *ccc;
|
uint16_t ccc_bits;
|
||||||
|
uint8_t ccc_bits_encoded[sizeof(ccc_bits)];
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
__ASSERT(conn, "invalid parameter\n");
|
__ASSERT(conn, "invalid parameter\n");
|
||||||
__ASSERT(attr, "invalid parameter\n");
|
__ASSERT(attr, "invalid parameter\n");
|
||||||
|
@ -3484,8 +3486,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
|
||||||
|
|
||||||
/* Check if attribute is a characteristic declaration */
|
/* Check if attribute is a characteristic declaration */
|
||||||
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
|
if (!bt_uuid_cmp(attr->uuid, BT_UUID_GATT_CHRC)) {
|
||||||
uint8_t properties = 0;
|
uint8_t properties;
|
||||||
ssize_t len;
|
|
||||||
|
|
||||||
if (!attr->read) {
|
if (!attr->read) {
|
||||||
LOG_ERR("Read method not set");
|
LOG_ERR("Read method not set");
|
||||||
|
@ -3494,7 +3495,7 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
|
||||||
/* The charactestic properties is the first byte of the attribute value */
|
/* The charactestic properties is the first byte of the attribute value */
|
||||||
len = attr->read(NULL, attr, &properties, sizeof(properties), 0);
|
len = attr->read(NULL, attr, &properties, sizeof(properties), 0);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
LOG_ERR("Failed to read attribute (err %zd)", len);
|
LOG_ERR("Failed to read attribute %p (err %zd)", attr, len);
|
||||||
return false;
|
return false;
|
||||||
} else if (len != sizeof(properties)) {
|
} else if (len != sizeof(properties)) {
|
||||||
LOG_ERR("Invalid read length: %zd", len);
|
LOG_ERR("Invalid read length: %zd", len);
|
||||||
|
@ -3532,16 +3533,25 @@ bool bt_gatt_is_subscribed(struct bt_conn *conn,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ccc = attr->user_data;
|
if (!attr->read) {
|
||||||
|
LOG_ERR("Read method not set");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the connection is subscribed */
|
len = attr->read(conn, attr, ccc_bits_encoded, sizeof(ccc_bits_encoded), 0);
|
||||||
for (size_t i = 0; i < BT_GATT_CCC_MAX; i++) {
|
if (len < 0) {
|
||||||
const struct bt_gatt_ccc_cfg *cfg = &ccc->cfg[i];
|
LOG_ERR("Failed to read attribute %p (err %zd)", attr, len);
|
||||||
|
return false;
|
||||||
|
} else if (len != sizeof(ccc_bits_encoded)) {
|
||||||
|
LOG_ERR("Invalid read length: %zd", len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (bt_conn_is_peer_addr_le(conn, cfg->id, &cfg->peer) &&
|
ccc_bits = sys_get_le16(ccc_bits_encoded);
|
||||||
(ccc_type & ccc->cfg[i].value)) {
|
|
||||||
return true;
|
/* Check if the CCC bits match the subscription type */
|
||||||
}
|
if (ccc_bits & ccc_type) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue