fix(router): null-check packetPool/clientNotificationPool allocations (#10948)

On platforms where these pools are heap-backed (MemoryDynamic - used
whenever there isn't enough static RAM for a fixed pool, e.g.
ARCH_STM32WL or BOARD_HAS_PSRAM), allocCopy()/allocZeroed() return
nullptr on allocation failure and already log a warning, but most
callers dereferenced the result unconditionally. Under real heap
pressure this reliably produced a HardFault - reproduced on STM32WL
hardware under sustained mesh traffic, including the RX entry point
(RadioLibInterface::handleReceiveInterrupt) where every received
packet is allocated.

Adds null checks at all call sites that were missing one, mirroring
the guard pattern already used correctly elsewhere in the same files
(e.g. RadioInterface.cpp's sendErrorNotification). On allocation
failure, callers now skip the send/retransmission/notification and
log nothing further (the allocator already did) rather than crash.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>

Signed-off-by: Andrew Yong <me@ndoo.sg>
This commit is contained in:
Andrew Yong
2026-07-09 04:36:36 -05:00
committed by GitHub
co-authored by GitHub
parent b4b1ece8f1
commit 0ae44d7017
7 changed files with 48 additions and 22 deletions
+8 -3
View File
@@ -111,7 +111,8 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp)
}
printPacket("Forwarding to phone", mp);
sendToPhone(packetPool.allocCopy(*mp));
if (auto *toPhone = packetPool.allocCopy(*mp))
sendToPhone(toPhone);
return 0;
}
@@ -206,7 +207,8 @@ void MeshService::handleToRadio(meshtastic_MeshPacket &p)
DEBUG_HEAP_BEFORE;
auto a = packetPool.allocCopy(p);
DEBUG_HEAP_AFTER("MeshService::handleToRadio", a);
sendToMesh(a, RX_SRC_USER);
if (a)
sendToMesh(a, RX_SRC_USER);
bool loopback = false; // if true send any packet the phone sends back itself (for testing)
if (loopback) {
@@ -226,6 +228,8 @@ bool MeshService::cancelSending(PacketId id)
ErrorCode MeshService::sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id)
{
meshtastic_QueueStatus *copied = queueStatusPool.allocCopy(qs);
if (!copied)
return ERRNO_UNKNOWN;
copied->res = res;
copied->mesh_packet_id = mesh_packet_id;
@@ -266,7 +270,8 @@ void MeshService::sendToMesh(meshtastic_MeshPacket *p, RxSource src, bool ccToPh
auto a = packetPool.allocCopy(*p);
DEBUG_HEAP_AFTER("MeshService::sendToMesh", a);
sendToPhone(a);
if (a)
sendToPhone(a);
}
// Router may ask us to release the packet if it wasn't sent