mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[dns-client] fix double-free of mSavedResponse on duplicate response (#13060)
Fix a double-free of `mSavedResponse` in `Dns::Client` when processing duplicate DNS responses matching an active query. When an SRV/TXT query needs to resolve a host address (AAAA), the DNS client allocates a chained `newQuery` to handle it. If duplicate responses are processed before the query chain is finalized, they trigger multiple AAAA resolution allocations for the same parent query. Because the new query inherits `mSavedResponse` from the parent query's `QueryInfo`, multiple chained queries end up aliasing/sharing the same cloned `mSavedResponse` message. During finalization, `FreeQuery` walks the chain and frees `mSavedResponse` for each query, leading to a double-free of the shared `Message` and free-list/heap corruption. This commit resolves the issue by: 1. Rejecting duplicate responses early in `ParseResponse` if a response has already been received and saved for the query (`info.mSavedResponse != nullptr`), returning `kErrorDrop`. 2. Initializing the `mSavedResponse` field of the `QueryInfo` struct to `nullptr` before allocating the host resolution query (`newQuery`) to prevent it from inheriting a potentially non-null saved response from its parent.
This commit is contained in:
@@ -1497,6 +1497,7 @@ Error Client::ParseResponse(const Message &aResponseMessage, Query *&aQuery, Err
|
||||
VerifyOrExit(aQuery != nullptr, error = kErrorNotFound);
|
||||
|
||||
info.ReadFrom(*aQuery);
|
||||
VerifyOrExit(info.mSavedResponse == nullptr, error = kErrorDrop);
|
||||
|
||||
queryName.SetFromMessage(*aQuery, kNameOffsetInQuery);
|
||||
|
||||
@@ -1872,6 +1873,7 @@ void Client::ResolveHostAddressIfNeeded(Query &aQuery, const Message &aResponseM
|
||||
info.mMessageId = 0;
|
||||
info.mTransmissionCount = 0;
|
||||
info.mMainQuery = &FindMainQuery(aQuery);
|
||||
info.mSavedResponse = nullptr;
|
||||
|
||||
SuccessOrExit(AllocateQuery(info, nullptr, hostName, newQuery));
|
||||
IgnoreError(SendQuery(*newQuery, info, /* aUpdateTimer */ true));
|
||||
|
||||
Reference in New Issue
Block a user