From 0928de3b7becb2c03c3e57464a33ab640efbc7fe Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sat, 1 Aug 2026 17:06:39 -0400 Subject: [PATCH] deviceapi: Avoid iterator invalidation when clearing buddy lists Fix cppcheck warning: Using iterator to member container 'm_sinkBuddies' that may be invalid clearBuddiesLists() was iterating directly over m_sourceBuddies and m_sinkBuddies while calling removeBuddy(), which modifies the buddy relationship lists. This could invalidate the active iterator and result in undefined behavior. The issue could lead to intermittent failures during buddy cleanup operations, such as device removal, device reload, or application shutdown, depending on container state and timing. Iterate over copies of the buddy lists so that removing relationships does not affect the iterators used for traversal. Signed-off-by: Robin Getz --- sdrbase/device/deviceapi.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sdrbase/device/deviceapi.cpp b/sdrbase/device/deviceapi.cpp index d969272ba..9f6cd2921 100644 --- a/sdrbase/device/deviceapi.cpp +++ b/sdrbase/device/deviceapi.cpp @@ -801,32 +801,35 @@ void DeviceAPI::removeBuddy(DeviceAPI* buddy) void DeviceAPI::clearBuddiesLists() { - auto itSource = m_sourceBuddies.begin(); - auto itSink = m_sinkBuddies.begin(); + // Make copies before iterating because removeBuddy() modifies the buddy + // relationship lists. Iterating directly over m_sourceBuddies/m_sinkBuddies + // could invalidate iterators while the relationships are being removed. + auto sourceCopy = m_sourceBuddies; + auto sinkCopy = m_sinkBuddies; bool leaderElected = false; - for (;itSource != m_sourceBuddies.end(); ++itSource) + for (auto* buddy : sourceCopy) { if (isBuddyLeader() && !leaderElected) { - (*itSource)->setBuddyLeader(true); + buddy->setBuddyLeader(true); leaderElected = true; } - (*itSource)->removeBuddy(this); + buddy->removeBuddy(this); } m_sourceBuddies.clear(); - for (;itSink != m_sinkBuddies.end(); ++itSink) + for (auto* buddy : sinkCopy) { if (isBuddyLeader() && !leaderElected) { - (*itSink)->setBuddyLeader(true); + buddy->setBuddyLeader(true); leaderElected = true; } - (*itSink)->removeBuddy(this); + buddy->removeBuddy(this); } m_sinkBuddies.clear();