From dad25dc5b5bd4e774d0657d2da9481451566c217 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 11 Mar 2026 11:08:49 -0700 Subject: [PATCH] [energy-scan] protect server state on allocation failure (#12664) This commit updates `EnergyScanServer::HandleTmf()` to use a local `OwnedPtr` when allocating and preparing the initial energy report message. Previously, the method directly modified `mReportMessage`, potentially leaving the object in an inconsistent state or leaking memory if subsequent `Append()` operations failed and exited early. By building the message in a local `newMessage` first and only taking ownership using `PassOwnership()` after all operations succeed, we ensure the server's internal state remains consistent. --- src/core/thread/energy_scan_server.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp index 7c3702a81..acfbb8d74 100644 --- a/src/core/thread/energy_scan_server.cpp +++ b/src/core/thread/energy_scan_server.cpp @@ -52,11 +52,12 @@ EnergyScanServer::EnergyScanServer(Instance &aInstance) template <> void EnergyScanServer::HandleTmf(Coap::Msg &aMsg) { - uint8_t count; - uint16_t period; - uint16_t scanDuration; - uint32_t mask; - MeshCoP::Tlv tlv; + OwnedPtr newMessage; + uint8_t count; + uint16_t period; + uint16_t scanDuration; + uint32_t mask; + MeshCoP::Tlv tlv; SuccessOrExit(Tlv::Find(aMsg.mMessage, count)); count = Clamp(count, kMinCount, kMaxCount); @@ -67,13 +68,13 @@ template <> void EnergyScanServer::HandleTmf(Coap::Msg &aMsg) SuccessOrExit(MeshCoP::ChannelMaskTlv::FindIn(aMsg.mMessage, mask)); VerifyOrExit(mask != 0); - mReportMessage.Reset(Get().AllocateAndInitPriorityConfirmablePostMessage(kUriEnergyReport)); - VerifyOrExit(mReportMessage != nullptr); + newMessage.Reset(Get().AllocateAndInitPriorityConfirmablePostMessage(kUriEnergyReport)); + VerifyOrExit(newMessage != nullptr); - SuccessOrExit(MeshCoP::ChannelMaskTlv::AppendTo(*mReportMessage, mask)); + SuccessOrExit(MeshCoP::ChannelMaskTlv::AppendTo(*newMessage, mask)); tlv.SetType(MeshCoP::Tlv::kEnergyList); - SuccessOrExit(mReportMessage->Append(tlv)); + SuccessOrExit(newMessage->Append(tlv)); mNumScanResults = 0; mChannelMask = mask; @@ -81,14 +82,16 @@ template <> void EnergyScanServer::HandleTmf(Coap::Msg &aMsg) mCount = count; mPeriod = period; mScanDuration = scanDuration; + mCommissioner = aMsg.mMessageInfo.GetPeerAddr(); + + mReportMessage = newMessage.PassOwnership(); mTimer.Start(kScanDelay); - mCommissioner = aMsg.mMessageInfo.GetPeerAddr(); + LogInfo("Received %s", UriToString()); if (aMsg.IsConfirmable() && !aMsg.mMessageInfo.GetSockAddr().IsMulticast()) { SuccessOrExit(Get().SendAckResponse(aMsg)); - LogInfo("Sent %s ack", UriToString()); } exit: