fix(modules): null-check packetPool/clientNotificationPool/mqttClientProxyMessagePool allocations (#10951)

* fix(modules): null-check packetPool/clientNotificationPool/mqttClientProxyMessagePool allocations

Follow-up to fix/meshpacket-alloc-null-checks (PR meshtastic/firmware#10948),
which fixed the core routing path (Router/NextHopRouter/ReliableRouter/
MeshService/RadioLibInterface) after reproducing a HardFault on STM32WL
hardware under real mesh traffic. This covers the same allocCopy()/
allocZeroed() unchecked-return pattern in lower-frequency paths that were
out of scope for that PR: SimRadio.cpp (portduino sim RX/TX), NodeInfoModule,
the Telemetry modules' power-saving-sleep notifications, MQTT (map report,
client-proxy messages, config-validation notifications), PositionModule,
SerialModule, and KeyVerificationModule.

Sites where the allocation result was already read back through an
existing null check downstream (e.g. Telemetry's lastMeasurementPacket,
SimRadio's receivingPacket, AdminModule::sendWarning) were left as-is -
verified safe, not touched.

Router::allocForSending() (and everything that funnels through it, e.g.
allocDataProtobuf()) remains unguarded and out of scope here too - it's
called from 30+ sites across the codebase and needs its own audit.

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Andrew Yong <me@ndoo.sg>

* fix(KeyVerificationModule): bound cn->message writes with snprintf

CodeRabbit flagged unbounded sprintf() writes into the fixed-size
ClientNotification.message buffer as a static-analysis nitpick while
reviewing this PR's allocation null-checks. Align these four sites with
the snprintf(dest, sizeof(dest), ...) pattern already used for the same
field elsewhere in this PR (SerialModule.cpp, MQTT.cpp).

Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Andrew Yong <me@ndoo.sg>

---------

Signed-off-by: Andrew Yong <me@ndoo.sg>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
Andrew Yong
2026-07-09 10:34:58 -05:00
committed by GitHub
co-authored by Ben Meadors
parent 515fe8b94f
commit 6768bd08df
9 changed files with 112 additions and 79 deletions
+44 -36
View File
@@ -81,14 +81,16 @@ bool KeyVerificationModule::handleReceivedProtobuf(const meshtastic_MeshPacket &
});)
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
sprintf(cn->message, "Enter Security Number for Key Verification");
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_number_request_tag;
cn->payload_variant.key_verification_number_request.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_number_request.remote_longname,
sizeof(cn->payload_variant.key_verification_number_request.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
service->sendClientNotification(cn);
if (cn) {
cn->level = meshtastic_LogRecord_Level_WARNING;
snprintf(cn->message, sizeof(cn->message), "Enter Security Number for Key Verification");
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_number_request_tag;
cn->payload_variant.key_verification_number_request.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_number_request.remote_longname,
sizeof(cn->payload_variant.key_verification_number_request.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
service->sendClientNotification(cn);
}
LOG_INFO("Received hash2");
currentState = KEY_VERIFICATION_SENDER_AWAITING_NUMBER;
return true;
@@ -114,15 +116,17 @@ bool KeyVerificationModule::handleReceivedProtobuf(const meshtastic_MeshPacket &
};
screen->showOverlayBanner(options);)
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
sprintf(cn->message, "Final confirmation for incoming manual key verification %s", message);
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_final_tag;
cn->payload_variant.key_verification_final.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_final.remote_longname,
sizeof(cn->payload_variant.key_verification_final.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
cn->payload_variant.key_verification_final.isSender = false;
service->sendClientNotification(cn);
if (cn) {
cn->level = meshtastic_LogRecord_Level_WARNING;
snprintf(cn->message, sizeof(cn->message), "Final confirmation for incoming manual key verification %s", message);
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_final_tag;
cn->payload_variant.key_verification_final.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_final.remote_longname,
sizeof(cn->payload_variant.key_verification_final.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
cn->payload_variant.key_verification_final.isSender = false;
service->sendClientNotification(cn);
}
currentState = KEY_VERIFICATION_RECEIVER_AWAITING_USER;
return true;
@@ -211,16 +215,18 @@ meshtastic_MeshPacket *KeyVerificationModule::allocReply()
IF_SCREEN(snprintf(message, 25, "Security Number \n%03u %03u", currentSecurityNumber / 1000, currentSecurityNumber % 1000);
screen->showSimpleBanner(message, 30000); LOG_WARN("%s", message);)
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
sprintf(cn->message, "Incoming Key Verification.\nSecurity Number\n%03u %03u", currentSecurityNumber / 1000,
currentSecurityNumber % 1000);
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_number_inform_tag;
cn->payload_variant.key_verification_number_inform.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_number_inform.remote_longname,
sizeof(cn->payload_variant.key_verification_number_inform.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
cn->payload_variant.key_verification_number_inform.security_number = currentSecurityNumber;
service->sendClientNotification(cn);
if (cn) {
cn->level = meshtastic_LogRecord_Level_WARNING;
snprintf(cn->message, sizeof(cn->message), "Incoming Key Verification.\nSecurity Number\n%03u %03u",
currentSecurityNumber / 1000, currentSecurityNumber % 1000);
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_number_inform_tag;
cn->payload_variant.key_verification_number_inform.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_number_inform.remote_longname,
sizeof(cn->payload_variant.key_verification_number_inform.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
cn->payload_variant.key_verification_number_inform.security_number = currentSecurityNumber;
service->sendClientNotification(cn);
}
LOG_WARN("Security Number %04u, nonce %llu", currentSecurityNumber, currentNonce);
return responsePacket;
}
@@ -275,15 +281,17 @@ void KeyVerificationModule::processSecurityNumber(uint32_t incomingNumber)
currentState = KEY_VERIFICATION_SENDER_AWAITING_USER;
IF_SCREEN(screen->requestMenu(graphics::menuHandler::KeyVerificationFinalPrompt);)
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
cn->level = meshtastic_LogRecord_Level_WARNING;
sprintf(cn->message, "Final confirmation for outgoing manual key verification %s", message);
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_final_tag;
cn->payload_variant.key_verification_final.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_final.remote_longname,
sizeof(cn->payload_variant.key_verification_final.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
cn->payload_variant.key_verification_final.isSender = true;
service->sendClientNotification(cn);
if (cn) {
cn->level = meshtastic_LogRecord_Level_WARNING;
snprintf(cn->message, sizeof(cn->message), "Final confirmation for outgoing manual key verification %s", message);
cn->which_payload_variant = meshtastic_ClientNotification_key_verification_final_tag;
cn->payload_variant.key_verification_final.nonce = currentNonce;
copyNodeLongNameOrUnknown(cn->payload_variant.key_verification_final.remote_longname,
sizeof(cn->payload_variant.key_verification_final.remote_longname),
nodeDB->getMeshNode(currentRemoteNode));
cn->payload_variant.key_verification_final.isSender = true;
service->sendClientNotification(cn);
}
LOG_INFO(message);
return;