Skip to content

fix: null-check NodeDB pointers and harden RX path to prevent heap-pressure crashes - #11377

Open
clawoneloke wants to merge 1 commit into
meshtastic:masterfrom
clawoneloke:fix/heap-null-crashes-v2
Open

fix: null-check NodeDB pointers and harden RX path to prevent heap-pressure crashes#11377
clawoneloke wants to merge 1 commit into
meshtastic:masterfrom
clawoneloke:fix/heap-null-crashes-v2

Conversation

@clawoneloke

Copy link
Copy Markdown

Summary

Three related fixes that address the T-Lora T3 reboot on HTTP connect reported in meshtastic/firmware#10040. Root cause: heap exhaustion during config dump triggers null derefs and packet pool exhaustion.

Changes

1. src/mesh/MeshService.cpp — Null-check getMeshNode(mp->from) before dereferencing

Cache the NodeDB lookup in a local pointer before dereferencing ->has_user in handleFromRadio(). This closes the TOCTOU window where a concurrent task could evict the node between the lookup and the dereference, and reduces two linear NodeDB scans per RX packet to one.

Before:

} else if (... && !nodeDB->getMeshNode(mp->from)->has_user && ...)

After:

meshtastic_NodeInfoLite *fromNode = nodeDB->getMeshNode(mp->from);
if (fromNode != nullptr && !fromNode->has_user) {

2. src/mesh/Router.cpp — Cache NodeDB lookups in PKI decode path

Cache getMeshNode(p->from) and getMeshNode(p->to) before dereferencing ->user.public_key.size. Eliminates duplicate linear scans and closes the TOCTOU hazard.

3. src/mesh/RadioLibInterface.cpp — Four hardening fixes

  • randomBytes(): Fix half-open range — random(0, 255) can never produce byte value 255. Changed to random(0, 256) per RadioLib semantics.
  • CRC mismatch log level: Downgrade RADIOLIB_ERR_CRC_MISMATCH from LOG_ERROR to LOG_INFO — CRC mismatches are routine in RF-congested areas and not an error condition.
  • rxGood placement: Move rxGood++ to always count CRC-valid OTA receptions before short/from-null packet rejection, so valid airtime is not silently lost from stats.
  • Pool exhaustion guard: Add null-check after packetPool.allocZeroed() to prevent NULL deref when heap pressure is high during config dumps.

Testing

These fixes address the crash pattern observed in #10040:

[WiFiClient.cpp:67] fillBuffer(): Not enough memory to allocate buffer
abort() was called at PC 0x4020f20f on core 1

Compiles successfully on ESP32 (T-Lora T3 target). Please test on SX126x devices with active mesh and phone connections.

Related

…essure crashes

Three related fixes that address the T-Lora T3 reboot on HTTP connect
(root cause: heap exhaustion during config dump triggering null derefs
and pool exhaustion):

1. MeshService.cpp: Cache getMeshNode(mp->from) before dereferencing
   has_user. Avoids two linear NodeDB scans per RX packet and closes
   the TOCTOU window where a concurrent task could evict the node.

2. Router.cpp: Cache getMeshNode(p->from) and getMeshNode(p->to)
   before dereferencing user.public_key.size in the PKI decode path.
   Also closes TOCTOU and avoids duplicate linear scans.

3. RadioLibInterface.cpp:
   - Fix randomByte() half-open range: random(0,255) never yields 255,
     changed to random(0,256) per RadioLib semantics.
   - Downgrade RADIOLIB_ERR_CRC_MISMATCH from LOG_ERROR to LOG_INFO
     (routine in RF-congested areas, not an error).
   - Move rxGood++ to always count CRC-valid OTA receptions before
     short/from-null packet rejection.
   - Add null-check after packetPool.allocZeroed() to prevent NULL
     deref under pool exhaustion.

Fixes: meshtastic#10040
@CLAassistant

CLAassistant commented Aug 9, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

@clawoneloke, Welcome to Meshtastic!

Thanks for opening your first pull request. We really appreciate it.

We discuss work as a team in discord, please join us in the #firmware channel.
There's a big backlog of patches at the moment. If you have time,
please help us with some code review and testing of other PRs!

Welcome to the team 😄

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a3d5c306-4d6c-4110-968d-31682de90b23

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants