Skip to content

fix: validate optData length in FCP_Get_OptData to prevent buffer overflow#7

Open
steps-re wants to merge 1 commit into
FOSSASystems:masterfrom
steps-re:fix/getoptdata-length-validation
Open

fix: validate optData length in FCP_Get_OptData to prevent buffer overflow#7
steps-re wants to merge 1 commit into
FOSSASystems:masterfrom
steps-re:fix/getoptdata-length-validation

Conversation

@steps-re

@steps-re steps-re commented Jul 7, 2026

Copy link
Copy Markdown

Summary

FCP_Get_OptData() can overflow the caller's optData buffer when parsing a malformed frame.

Details

The function reads the optional-data length byte from a received frame and memcpys that many bytes into the caller's buffer with no bounds check. On the unencrypted path that length byte is unauthenticated (attacker- or noise-controlled), so a corrupted RF frame can declare up to 255 bytes and overrun optData while parsing an incoming frame. The sibling FCP_Get_OptData_Length() already validates exactly this condition and returns ERR_LENGTH_MISMATCH; FCP_Get_OptData() did not.

Fix

Add the same length check before the memcpy, returning ERR_LENGTH_MISMATCH on mismatch. Valid frames (declared length == bytes present) are unaffected.

Verification

  • Host harness compiling the real FOSSA-Comms.cpp against minimal Arduino/AES stubs, built with g++ -fsanitize=address.
  • Before: a frame with length byte 200 into an 8-byte buffer triggers an ASan memcpy overflow at FOSSA-Comms.cpp:188.
  • After: encrypted and unencrypted encode→decode round-trips still decode correctly; the malformed frame returns ERR_LENGTH_MISMATCH with ASan clean.

Scope note: the encrypted path has an analogous copy behind the AES password check (authenticated, much lower risk); I kept this PR tight to the clearly-exploitable unauthenticated path.

…rflow

FCP_Get_OptData() read the optional-data length byte straight from the
received frame and memcpy'd that many bytes into the caller's optData
buffer without checking it against the actual frame length. A malformed
or corrupted unencrypted frame (the length byte is attacker/noise
controlled and unauthenticated) could therefore declare up to 255 bytes
and overrun the caller's buffer while parsing an incoming RF frame.

FCP_Get_OptData_Length() already guards this exact case and returns
ERR_LENGTH_MISMATCH. Apply the same check in FCP_Get_OptData() before the
memcpy. Valid frames are unaffected (the declared length equals the bytes
present); malformed frames now return ERR_LENGTH_MISMATCH instead of
overflowing.

Verified on a host build (identity-AES stub) under AddressSanitizer:
encrypted and unencrypted round-trips still decode correctly, and a frame
with a length byte of 200 into an 8-byte buffer now returns -4 instead of
triggering an overflow.

Signed-off-by: Mike German <mike@stepsventures.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant