fix(l1): cap snappy-decompressed length before allocating#6956
fix(l1): cap snappy-decompressed length before allocating#6956ElFantasma wants to merge 4 commits into
Conversation
|
🤖 Kimi Code ReviewThis is a solid security fix addressing a DoS vulnerability in RLPx snappy decompression. The implementation correctly prevents memory exhaustion attacks where a malicious peer declares an oversized decompressed length in a small compressed frame. Summary of changes:
Minor suggestions:
Verdict: LGTM. The fix correctly addresses the allocation-of-doom vulnerability (CVE-2023-XXX style attack vector) and maintains backward compatibility for valid frames. Automated review by Kimi (Moonshot AI) · kimi-k2.5 · custom prompt |
🤖 Codex Code ReviewFindings No findings. The change in utils.rs looks correct: it bounds the peer-controlled Snappy decoded length before I could not run the new tests locally: Automated review by OpenAI Codex · gpt-5.4 · custom prompt |
Lines of code reportTotal lines added: Detailed view |
🤖 Claude Code Reviewsnap 1.1.1 does export Review: fix(l1): cap snappy-decompressed length before allocatingSummary: This closes a real DoS vector — Correctness:
Minor / non-blocking:
Overall: correct, well-targeted security fix with good test coverage (oversized-header rejection + a round-trip regression check). No consensus, gas-accounting, or RLP-encoding implications since this sits purely in the transport/compression layer. Automated review by Claude (Anthropic) · sonnet · custom prompt |
|
Thanks — all non-blocking; notes on each:
|
Motivation
The RLPx codec caps the compressed frame size (
MAX_MESSAGE_SIZE=0xFFFFFF), butsnappy_decompressplaces no bound on the decompressed length. A snappy stream begins with a peer-controlled varint of the decompressed length, andsnap'sdecompress_vecallocates a buffer of that size before validating the body — so a tiny frame can declare a very large length (up to ~4 GiB) and force a correspondingly large allocation. go-ethereum boundssnappy.DecodedLenagainst the message-size cap before allocating; ethrex did not.Description
snappy_decompressnow reads the declared decompressed length viasnap::raw::decompress_lenand rejects it if it exceedsMAX_SNAPPY_DECOMPRESSED_LEN(0xFFFFFF, matching the compressed-frame cap and geth's maxUint24 bound) before allocating. Normal messages are unaffected.Adds unit tests: a crafted oversized declared-length header is rejected up front, and a normal round-trip still succeeds.
Checklist
cargo test -p ethrex-p2p(snappy tests) andcargo clippy -p ethrex-p2ppass.