fix(data_model): unlink cluster from endpoint on cluster::destroy

cluster::destroy() freed the cluster memory and its children (attributes,
commands, events) but never removed the cluster from the parent endpoint's
linked list, leaving a dangling pointer. This caused use-after-free crashes
when creating a new cluster on the same endpoint after destroying one.

Fix: look up the parent endpoint via the endpoint_id stored in the cluster
struct and unlink before freeing, consistent with how attribute::destroy,
command::destroy and event::destroy handle their parent lists.
This commit is contained in:
Shubham Patil
2026-03-24 23:04:00 +05:30
parent 8a6d0f4643
commit 004798130a
2 changed files with 9 additions and 4 deletions
@@ -1409,8 +1409,13 @@ esp_err_t destroy(cluster_t *cluster)
current_cluster->matter_attributes = NULL;
}
/* Free */
esp_matter_mem_free(current_cluster);
/* Remove from parent endpoint's cluster list and free */
_endpoint_t *parent_endpoint = (_endpoint_t *)endpoint::get(current_cluster->endpoint_id);
if (parent_endpoint) {
SinglyLinkedList<_cluster_t>::remove(&parent_endpoint->cluster_list, current_cluster);
} else {
esp_matter_mem_free(current_cluster);
}
return ESP_OK;
}
@@ -447,8 +447,8 @@ cluster_t *create(endpoint_t *endpoint, uint32_t cluster_id, uint8_t flags);
/** Destroy cluster
*
* This will destroy the cluster which has been created and added to the endpoint. It also destroys the associated
* attributes, commands and events.
* This will remove the cluster from the parent endpoint's cluster list, then destroy the cluster
* and free its associated attributes, commands and events.
*
* @param[in] cluster Cluster handle.
*