Repository navigation
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #763 +/- ##
=======================================
Coverage 99.58% 99.58%
=======================================
Files 64 64
Lines 4331 4332 +1
=======================================
+ Hits 4313 4314 +1
Misses 18 18 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
zigpy-review-bot
left a comment
There was a problem hiding this comment.
Looks good: the right fix, at the right layer. It's a direct replacement for the assert, and the new test pins the 256/257 boundary.
One correction to the impact described in #762, so nobody overrates this: on the real receive path, the uncaught AssertionError could not disrupt anything. AshProtocol.data_received() wraps _unstuff_bytes() + parse_frame() in except Exception, which already caught the AssertionError, logged it at debug level and called _reject_frame(). I checked this against dev by feeding a CRC-valid 257-byte DATA frame through data_received(): it is rejected the same way before and after this PR. The change that matters in practice is the python -O case. On dev under -O, a 300-byte payload parses "successfully" as a truncated 256-byte ezsp_frame and gets passed up the stack. With this PR it is rejected. That alone makes the PR worth merging, along with the clearer exception type.
Optional:
_randomize()is also used byDataFrame.to_bytes(), so encoding an oversized outgoing frame now raisesParsingErrorinstead ofAssertionError. The name is a bit odd on the send side, but nothing catches either one there, real EZSP frames are far below 256 bytes, and the message ("Frame payload is too long") reads fine in both directions. No change needed, just noting it.- The commit subject/PR title was cut off at GitHub's limit ("…oversized frame …"). It's worth fixing when squash-merging; recent bellows titles use plain sentence case, e.g. "Raise
ParsingErrorinstead of asserting on oversized ASH frame payloads".
Verified (3 checks)
- Full test suite at f6dcf8e: 706 passed. CI is green on 3.11–3.14.
data_received()with a stuffed, CRC-valid 257-byte DATA frame:_reject_frame()is called andframe_received()is not, on bothdevand this PR.- On
devwithpython -O,DataFrame.from_bytes()on a 300-byte payload returns a 256-byteezsp_frame(silent truncation). On this PR it raisesParsingError.
| seq_len = len(ash.PSEUDO_RANDOM_DATA_SEQUENCE) | ||
|
|
||
| # A payload of exactly the sequence length still parses. | ||
| ash.DataFrame.from_bytes(ash.AshFrame.append_crc(bytes([0x00]) + bytes(seq_len))) |
There was a problem hiding this comment.
Optional: this line only checks that no exception is raised. Asserting on the result would also pin that the derandomized payload isn't truncated at the boundary, e.g. assert len(ash.DataFrame.from_bytes(...).ezsp_frame) == seq_len.
|
I don't think this is actually reachable in practice: #define EZSP_MAX_FRAME_LENGTH (218 + 1 + 1)
...
#define ASH_MAX_DATA_FIELD_LEN EZSP_MAX_FRAME_LENGTH ///< ash max data field len
...
#define ASH_MAX_FRAME_LEN (ASH_MAX_DATA_FIELD_LEN + 1) ///< ash max frame lenThat being said, it doesn't hurt. |
ParsingError instead of asserting on oversized frame payload
…payload DataFrame.from_bytes() derandomizes the payload via _randomize(), which asserted len(data) <= len(PSEUDO_RANDOM_DATA_SEQUENCE) (256 bytes). A CRC-valid frame with a payload longer than 256 bytes therefore escaped with an uncaught AssertionError instead of ParsingError, and under `python -O` (assertions stripped) the payload was silently truncated to 256 bytes. Raise ParsingError on oversized payloads so malformed input is rejected consistently. Fixes zigpy#762 Co-Authored-By: hw1186 <ro49165703@gmail.com>
f6dcf8e to
3dc3976
Compare
…payload
DataFrame.from_bytes() derandomizes the payload via _randomize(), which asserted len(data) <= len(PSEUDO_RANDOM_DATA_SEQUENCE) (256 bytes). A CRC-valid frame with a payload longer than 256 bytes therefore escaped with an uncaught AssertionError instead of ParsingError, and under
python -O(assertions stripped) the payload was silently truncated to 256 bytes. Raise ParsingError on oversized payloads so malformed input is rejected consistently.Fixes #762