From af4c366cb7a4c2897acaae9b93ed415975d2d918 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Sun, 19 Jul 2026 12:59:17 -0400 Subject: [PATCH] PlutoSDR: Guard against null buddy shared pointers | Fix #2779 Add defensive null checks before dereferencing DeviceAPI::getBuddySharedPtr() in the PlutoSDR input and output plugins. DeviceAPI initializes the buddy shared pointer to nullptr, so a buddy may exist before its shared state has been attached. This could result in null pointer dereferences during device initialization, buddy thread suspend/resume, or settings application. Changes include: - Validate buddy shared pointer in openDevice() and fail gracefully if absent. - Guard suspendBuddies() and resumeBuddies() against null shared pointers. - Skip buddies without shared state during applySettings() while logging a warning. - Prevent dereferencing null buddy shared pointers when restarting buddy threads. These changes improve robustness during PlutoSDR buddy initialization and avoid crashes caused by partially initialized buddy relationships. Signed-off-by: Robin Getz --- .../plutosdroutput/plutosdroutput.cpp | 17 ++++++++++++++--- .../plutosdrinput/plutosdrinput.cpp | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/plugins/samplesink/plutosdroutput/plutosdroutput.cpp b/plugins/samplesink/plutosdroutput/plutosdroutput.cpp index 37f47222e..fd264824b 100644 --- a/plugins/samplesink/plutosdroutput/plutosdroutput.cpp +++ b/plugins/samplesink/plutosdroutput/plutosdroutput.cpp @@ -272,6 +272,11 @@ bool PlutoSDROutput::openDevice() DeviceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0]; DevicePlutoSDRShared* buddySharedPtr = (DevicePlutoSDRShared*) sourceBuddy->getBuddySharedPtr(); + if (!buddySharedPtr) + { + qCritical("PlutoSDROutput::openDevice: Rx buddy has no shared data"); + return false; + } m_deviceShared.m_deviceParams = buddySharedPtr->m_deviceParams; if (m_deviceShared.m_deviceParams == 0) @@ -369,7 +374,7 @@ void PlutoSDROutput::suspendBuddies() DeviceAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; DevicePlutoSDRShared *buddyShared = (DevicePlutoSDRShared *) buddy->getBuddySharedPtr(); - if (buddyShared->m_thread) { + if (buddyShared && buddyShared->m_thread) { buddyShared->m_thread->stopWork(); } } @@ -384,7 +389,7 @@ void PlutoSDROutput::resumeBuddies() DeviceAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; DevicePlutoSDRShared *buddyShared = (DevicePlutoSDRShared *) buddy->getBuddySharedPtr(); - if (buddyShared->m_thread) { + if (buddyShared && buddyShared->m_thread) { buddyShared->m_thread->startWork(); } } @@ -433,6 +438,12 @@ bool PlutoSDROutput::applySettings(const PlutoSDROutputSettings& settings, const { DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSink)->getBuddySharedPtr(); + if (!buddySharedPtr) + { + qWarning("PlutoSDROutput::applySettings: source buddy has no shared data"); + continue; + } + if (buddySharedPtr->m_thread) { buddySharedPtr->m_thread->stopWork(); buddySharedPtr->m_threadWasRunning = true; @@ -571,7 +582,7 @@ bool PlutoSDROutput::applySettings(const PlutoSDROutputSettings& settings, const { DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSource)->getBuddySharedPtr(); - if (buddySharedPtr->m_threadWasRunning) { + if (buddySharedPtr && buddySharedPtr->m_threadWasRunning) { buddySharedPtr->m_thread->startWork(); } } diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp index 784dbb637..53664796f 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp @@ -282,6 +282,11 @@ bool PlutoSDRInput::openDevice() DeviceAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0]; DevicePlutoSDRShared* buddySharedPtr = (DevicePlutoSDRShared*) sinkBuddy->getBuddySharedPtr(); + if (!buddySharedPtr) + { + qCritical("PlutoSDRInput::openDevice: Tx buddy has no shared data"); + return false; + } m_deviceShared.m_deviceParams = buddySharedPtr->m_deviceParams; if (m_deviceShared.m_deviceParams == 0) @@ -379,7 +384,7 @@ void PlutoSDRInput::suspendBuddies() DeviceAPI *buddy = m_deviceAPI->getSinkBuddies()[i]; DevicePlutoSDRShared *buddyShared = (DevicePlutoSDRShared *) buddy->getBuddySharedPtr(); - if (buddyShared->m_thread) { + if (buddyShared && buddyShared->m_thread) { buddyShared->m_thread->stopWork(); } } @@ -394,7 +399,7 @@ void PlutoSDRInput::resumeBuddies() DeviceAPI *buddy = m_deviceAPI->getSinkBuddies()[i]; DevicePlutoSDRShared *buddyShared = (DevicePlutoSDRShared *) buddy->getBuddySharedPtr(); - if (buddyShared->m_thread) { + if (buddyShared && buddyShared->m_thread) { buddyShared->m_thread->startWork(); } } @@ -444,6 +449,12 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, const Q { DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSink)->getBuddySharedPtr(); + if (!buddySharedPtr) + { + qWarning("PlutoSDRInput::applySettings: sink buddy has no shared data"); + continue; + } + if (buddySharedPtr->m_thread) { buddySharedPtr->m_thread->stopWork(); buddySharedPtr->m_threadWasRunning = true; @@ -624,7 +635,7 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, const Q { DevicePlutoSDRShared *buddySharedPtr = (DevicePlutoSDRShared *) (*itSink)->getBuddySharedPtr(); - if (buddySharedPtr->m_threadWasRunning) { + if (buddySharedPtr && buddySharedPtr->m_threadWasRunning) { buddySharedPtr->m_thread->startWork(); } }