Repository navigation
Fix companion crash on a short CMD_SEND_CHANNEL_TXT_MSG frame - #3643
Open
marcelverdult wants to merge 1 commit into
Open
marcelverdult wants to merge 1 commit into
marcelverdult wants to merge 1 commit into
Conversation
Member
|
Thanks for the extra param guards. (which are correct) The unit tests, I have to say, are of negative value, though. It's a very verbose setup just to put some cases around one simple condition (the BaseChatMesh::sendGroupMessage(), text_len < 0). Remember that all of that mocking, if committed, would have to be maintained from this point on, which adds significant load on whoever is making future changes, and the tests themselves add very little value. |
CMD_SEND_CHANNEL_TXT_MSG reads txt_type, channel_idx and a 4 byte timestamp, so the frame needs 7 bytes before the text starts, and the branch had no length guard. For a shorter frame "len - i" is computed in size_t, wraps, and reaches sendGroupMessage() as a negative int. The clamp there tests "text_len + prefix_len > MAX_TEXT_LEN", which a negative value passes, and the following memcpy() converts the length back to a size_t: a 3 byte frame asks for 4294967292 bytes into a 197 byte stack buffer. Two guards, because there are two mistakes. The branch now states its minimum like most other branches of handleCmdFrame do, so a frame below 7 bytes is answered through the existing path instead of being parsed. And sendGroupMessage() refuses a negative length the way sendGroupData() in the same file already does, which protects every other caller. A frame of exactly 7 bytes keeps working and sends an empty message, as before. Evidence. On a T-Echo running dev 428a95c, built with FIRMWARE_BUILD_DATE "f1-dev" and confirmed by "ver => v1.18.0 (Build: f1-dev)": CH_TXT len=7 -> RESP_CODE_OK GET_STATS core -> uptime=78s CH_TXT len=3 -> NO REPLY DEVICE_QUERY -> NO REPLY (three times over 8 s, node never came back)
marcelverdult
force-pushed
the
upstream-candidate/companion-channel-txt-min-len
branch
from
October 22, 2026 09:33
456970d to
56b5f4e
Compare
Contributor
Author
|
removed the tests. thx for the heads up |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CMD_SEND_CHANNEL_TXT_MSGreads txt_type, channel_idx and a 4 byte timestamp, so the frame needs 7 bytes before the text, but the branch has no length guard. For a shorter framelen - iis computed insize_t, wraps, and reachessendGroupMessage()as a negativeint. The clamp there (text_len + prefix_len > MAX_TEXT_LEN) lets a negative value through, and the followingmemcpy()turns it back into asize_t: on a 32 bit target a 3 byte frame asks for 4294967292 bytes into a 197 byte stack buffer.Two guards, because there are two mistakes:
len >= 7, the way the neighbouringCMD_SEND_TXT_MSGstateslen >= 14. A shorter frame falls through to the existing finalelse;sendGroupMessage()refuses a negative length, the waysendGroupData()in the same file already does. Today the companion frame handler is its only caller, so this protects future callers and is what makes the fix testable on the host.A frame of exactly 7 bytes still sends an empty message, as before.
Error code. A too short frame is answered with
ERR_CODE_UNSUPPORTED_CMD, which is what the other branches that guard their length with&& len >= Nanswer.ERR_CODE_ILLEGAL_ARGwould describe it better, but switching only this branch would make it the odd one out, and switching all of them is a visible protocol change that does not belong in a crash fix.Evidence
On a LilyGo T-Echo, USB companion build, each image marked through
FIRMWARE_BUILD_DATEand confirmed withverbefore the run.Before, on dev 428a95c:
The node did not come back; neither a 1200 baud touch nor the reset button recovered it, only unplugging the cable.
After, on this branch:
On the host, a new
native_chatenvironment builds the realUtils,Packet,Dispatcher,Mesh,BaseChatMesh,AdvertDataHelpersandTxtDataHelpersagainst fakes for radio, clock, RNG and packet manager:The host test covers
sendGroupMessage(); the frame handler guard itself is covered only by the hardware run above, becauseMyMesh.cppcannot be built on the host without stand-ins for board, radio, sensors and store. Companion builds checked on all five toolchains that compile this file (T-Echo nRF52, Heltec V3 ESP32, RAK11310 RP2040, Wio-E5 STM32, Xiao C6).The first commit adds the tests and is red on its own; the second is the fix; the third adds
native_chatto the unit test workflow so the suite runs in CI.Related open PRs: none touches the
CMD_SEND_CHANNEL_TXT_MSGbranch or the body ofsendGroupMessage(). New callers in #3529 (strlen(text)) and #2496 (an input length only decremented while> 0) cannot pass a negative length. #3638 adds two steps to.github/workflows/run-unit-tests.ymlright below the line this PR extends, a trivial textual conflict whichever lands second.