Skip to content

fix(serial): drop blank and line-noise text messages in TEXTMSG mode - #11380

Open
samirbhattarai135 wants to merge 2 commits into
meshtastic:developfrom
samirbhattarai135:fix/serial-textmsg-blank-and-noise
Open

fix(serial): drop blank and line-noise text messages in TEXTMSG mode#11380
samirbhattarai135 wants to merge 2 commits into
meshtastic:developfrom
samirbhattarai135:fix/serial-textmsg-blank-and-noise

Conversation

@samirbhattarai135

@samirbhattarai135 samirbhattarai135 commented Aug 9, 2026

Copy link
Copy Markdown

Fixes #6444.

What was wrong

In TEXTMSG mode the read loop in SerialModule::runOnce() forwarded whatever readBytes() returned straight into a mesh packet, with no check on length or content:

while (serialInstance->available()) {
    serialPayloadSize = serialInstance->readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
    serialModuleRadio->sendPayload();
}

Both symptoms in the issue follow from that directly:

  • pressing ENTER in a terminal sends a message whose entire content is CR/LF;
  • a node powering up with a floating RX pin - the "KNOWN PROBLEMS" note at the top of the same file - sends a byte of line noise as a text message.

What changed

  • sanitizeTextMessagePayload() (src/modules/SerialModule.cpp) compacts a TEXTMSG payload in place and returns the length worth sending. Control characters other than \n and \t are dropped, so are bytes that are not valid UTF-8, then surrounding whitespace is trimmed. Nothing left means nothing is sent. It sits outside the architecture guard next to serialConfigIsValid() for the same reason given there: it touches no serial hardware, so it can be tested on the native target.
  • The read loop sanitizes only in TEXTMSG mode, so DEFAULT and SIMPLE stay byte-transparent for binary bridging. The length check applies to every mode - a zero-length read was never worth a packet either.
  • utf8SequenceLength() (src/meshUtils.cpp) is the UTF-8 validity check sanitizeUtf8() already performed inline, extracted so both callers share one implementation. sanitizeUtf8() behaviour is unchanged: the existing test_utf8 cases (truncated sequences, overlong encodings, surrogate halves, 5-byte forms, buffer-end truncation) all pass unmodified.

One deviation from the report

The issue asks for non-ASCII characters to be rejected. This implements "must be valid UTF-8" instead, because a hard ASCII filter would stop people sending text in their own language over serial. Random line noise essentially never forms a valid UTF-8 sequence, so the reported symptom is still covered. Happy to tighten it to ASCII-only if you would rather follow the report literally.

Known limit either way: a noise byte that happens to land in printable ASCII is indistinguishable from a one-character message, so that one still goes out.

Testing

  • test_serial gains 10 cases for the new helper: CR/LF only, whitespace only, a lone 0xFF, surrounding-whitespace trimming, control characters mid-message, interior newline/tab kept, valid multi-byte UTF-8 preserved, invalid UTF-8 dropped, plain text untouched, empty read.
  • test_utf8 gains 8 cases for the extracted primitive.
  • Each new case was watched failing first against a stub helper, then passing against the implementation, with the pre-existing cases green throughout.
  • test_serial 20/20 and test_utf8 30/30 under the sanitized coverage env.
  • Full native suite in Docker on a macOS host: 862 cases, 858 passed. The two failures are test_packet_signing test_B11_normal_unicast_still_uses_pki and test_B12_licensed_receiver_does_not_decrypt_pki, which fail identically on an unmodified export of the parent commit, so they are pre-existing and unrelated. One suite (test_traceroute_nexthop) errored on an out-of-memory cc1plus kill inside my 2 GB container and passes 3/3 when run on its own.
  • Cross-compiled heltec-v3 to check the arch-guarded call site: SUCCESS.

🤝 Attestations

  • I have tested that my proposed changes behave as described.
  • I have tested that my proposed changes do not cause any obvious regressions on the following devices:
    • Heltec (Lora32) V3
    • LilyGo T-Deck
    • LilyGo T-Beam
    • RAK WisBlock 4631
    • Seeed Studio T-1000E tracker card
    • Other (please specify below)

I do not have a Meshtastic device, so the hardware boxes are deliberately unchecked: the behaviour is verified by the native unit tests and the heltec-v3 build only, and the real UART path has not been exercised. A check from anyone with a TEXTMSG-configured node and a serial adapter would be very welcome - pressing ENTER should now send nothing, and a cold boot should no longer emit a stray message.

Summary by CodeRabbit

  • New Features

    • Serial text messages now remove invalid UTF-8, unsupported control characters, and surrounding whitespace before transmission.
    • Empty messages created after sanitization are no longer sent.
    • Tabs, newlines, interior spacing, and valid UTF-8 content are preserved.
  • Bug Fixes

    • Improved handling of truncated, malformed, overlong, and invalid Unicode sequences.
  • Tests

    • Added coverage for UTF-8 validation and serial message sanitization.

TEXTMSG mode forwarded whatever readBytes() returned straight into a mesh packet,
so pressing ENTER in a terminal sent a message whose entire content was CR/LF,
and a node booting with a floating RX pin sent a byte of line noise as a text
message.

sanitizeTextMessagePayload() compacts the payload in place to what is worth
sending: control characters other than newline and tab are dropped, as are bytes
that are not valid UTF-8, and surrounding whitespace is trimmed. Nothing left
means nothing is sent. Only TEXTMSG mode is sanitized, so DEFAULT and SIMPLE stay
byte-transparent; the length check applies to every mode, since a zero-length
read was never worth a packet either.

The UTF-8 validity check sanitizeUtf8() performed inline is extracted as
utf8SequenceLength() so both callers share one implementation.
@CLAassistant

CLAassistant commented Aug 9, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

@samirbhattarai135, 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

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 13be3301-2752-4a6e-a39f-bf9e7f435a73

📥 Commits

Reviewing files that changed from the base of the PR and between b594a8a and 5688f9e.

📒 Files selected for processing (3)
  • src/meshUtils.h
  • src/modules/SerialModule.h
  • test/test_serial/SerialModule.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/meshUtils.h
  • src/modules/SerialModule.h
  • test/test_serial/SerialModule.cpp

📝 Walkthrough

Walkthrough

Adds shared UTF-8 validation and uses it to sanitize serial text-message payloads. Invalid bytes, disallowed controls, and surrounding whitespace are removed. Empty sanitized payloads are not transmitted. Tests cover validation and sanitization behavior.

Changes

UTF-8 and serial text sanitization

Layer / File(s) Summary
UTF-8 validation and reuse
src/meshUtils.h, src/meshUtils.cpp, test/test_utf8/test_main.cpp
Adds utf8SequenceLength for validating UTF-8 length, continuation bytes, encoding bounds, and truncation. sanitizeUtf8 uses the helper and replaces invalid bytes individually. Tests cover valid and malformed sequences.
Serial payload sanitization
src/modules/SerialModule.h, src/modules/SerialModule.cpp, test/test_serial/SerialModule.cpp
Adds in-place text payload sanitization, removes invalid UTF-8 and disallowed controls, trims surrounding whitespace, preserves permitted whitespace, and skips empty payloads before transmission. Tests cover these cases.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR fixes blank messages and trims whitespace, but it does not reject valid non-ASCII characters requested by issue #6444. Add an ASCII-only filter, or obtain explicit approval for the documented valid-UTF-8 deviation from issue #6444.
Docstring Coverage ⚠️ Warning Docstring coverage is 46.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: suppressing blank and line-noise text messages in TEXTMSG mode.
Description check ✅ Passed The description is detailed, follows the template, documents the implementation and testing, and explains the unavailable hardware validation.
Out of Scope Changes check ✅ Passed The UTF-8 helper extraction and added tests directly support payload sanitization and remain within the linked issue scope.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/meshUtils.h (1)

73-75: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Conform new comments to the project comment policy.

These comments exceed two lines or repeat information that the code already states.

  • src/meshUtils.h#L73-L75: reduce the API comment to two lines or less.
  • src/modules/SerialModule.h#L16-L19: reduce the API comment to two lines or less.
  • test/test_serial/SerialModule.cpp#L122-L206: remove comments that only restate each test name or assertion. Keep byte-sequence rationale where needed.

As per coding guidelines, “Keep code comments minimal—one or two lines maximum—and comment only when the reason is not obvious.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/meshUtils.h` around lines 73 - 75, Shorten the API comment in
src/meshUtils.h lines 73-75 to no more than two lines while retaining only
non-obvious behavior. Similarly reduce the API comment in
src/modules/SerialModule.h lines 16-19 to two lines or less. In
test/test_serial/SerialModule.cpp lines 122-206, remove comments that merely
repeat test names or assertions, preserving only comments explaining necessary
byte-sequence rationale.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/meshUtils.h`:
- Around line 73-75: Shorten the API comment in src/meshUtils.h lines 73-75 to
no more than two lines while retaining only non-obvious behavior. Similarly
reduce the API comment in src/modules/SerialModule.h lines 16-19 to two lines or
less. In test/test_serial/SerialModule.cpp lines 122-206, remove comments that
merely repeat test names or assertions, preserving only comments explaining
necessary byte-sequence rationale.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: de082574-f158-4bda-965f-cda2f18c20a9

📥 Commits

Reviewing files that changed from the base of the PR and between 5692518 and b594a8a.

📒 Files selected for processing (6)
  • src/meshUtils.cpp
  • src/meshUtils.h
  • src/modules/SerialModule.cpp
  • src/modules/SerialModule.h
  • test/test_serial/SerialModule.cpp
  • test/test_utf8/test_main.cpp

Drop the comments that only restated a test name, and shorten the two API
comments. What is left is the byte-sequence rationale and the reason a case
exists at all.
@caveman99 caveman99 added the bugfix Pull request that fixes bugs label Aug 10, 2026 — with Claude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Pull request that fixes bugs first-contribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Serial Module TEXTMSG mode allows the sending of blank messages and non-ASCII chars

3 participants