eth/protocols/eth, eth/protocols/snap: delayed p2p message decoding#33835
Merged
Conversation
rjl493456442
previously approved these changes
Feb 13, 2026
86aae79 to
f9f0e90
Compare
This changes the p2p protocol handlers to delay message decoding. It's the first part of a larger change that will delay decoding all the way through message processing. For responses, we delay the decoding until it is confirmed that the response matches an active request and does not exceed its limits. In order to make this work, all messages have been changed to use rlp.RawList instead of a slice of the decoded item type. For block bodies specifically, the decoding has been delayed all the way until after verification of the response hash. The role of p2p/tracker.Tracker changes significantly in this PR. The Tracker's original purpose was to maintain metrics about requests and responses in the peer-to-peer protocols. Each protocol maintained a single global Tracker instance. As of this change, the Tracker is now always active (regardless of metrics collection), and there is a separate instance of it for each peer. Whenever a response arrives, it is first verified that a request exists for it in the tracker. The tracker is also the place where limits are kept.
rjl493456442
approved these changes
Feb 15, 2026
chris-mercer
added a commit
to chris-mercer/core-geth
that referenced
this pull request
Mar 21, 2026
A malicious peer can send a p2p response with a valid RLP list header claiming millions of tiny items. The 10 MiB maxMessageSize check passes, but msg.Decode allocates pointer/struct objects proportional to item count before the response is validated, causing OOM. This adds pre-decode item count validation for both eth and snap protocols. Before msg.Decode runs, the raw message payload (already buffered by the transport layer) is scanned using rlp.CountValues — a zero-allocation operation that reads only RLP tag bytes. If the item count exceeds the protocol limit, the message is rejected immediately. Validated eth messages: BlockHeaders, BlockBodies, Receipts, PooledTransactions, Transactions, NewBlockHashes. Validated snap messages: AccountRange, StorageRanges, ByteCodes, TrieNodes. Limits: 2048 for responses (2x serve-side maxHeadersServe/maxBodiesServe), 32768 for transaction broadcasts (matches maxKnownTxs). This is a minimal port of upstream go-ethereum PR #33835. The full upstream refactor (delayed message decoding with rlp.RawList) cannot be cleanly backported due to structural divergence (13 merge conflicts). References: - CVE-2026-26313: GHSA-689v-6xwf-5jf3 - Upstream fix: ethereum/go-ethereum#33835 - Issue etclabscore#692: etclabscore#692 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
chris-mercer
added a commit
to chris-mercer/core-geth
that referenced
this pull request
Mar 24, 2026
A malicious peer can send a p2p response with a valid RLP list header claiming millions of tiny items. The 10 MiB maxMessageSize check passes, but msg.Decode allocates pointer/struct objects proportional to item count before the response is validated, causing OOM. This adds pre-decode item count validation for both eth and snap protocols. Before msg.Decode runs, the raw message payload (already buffered by the transport layer) is scanned using rlp.CountValues — a zero-allocation operation that reads only RLP tag bytes. If the item count exceeds the protocol limit, the message is rejected immediately. Validated eth messages: BlockHeaders, BlockBodies, Receipts, PooledTransactions, Transactions, NewBlockHashes. Validated snap messages: AccountRange, StorageRanges, ByteCodes, TrieNodes. Limits: 2048 for responses (2x serve-side maxHeadersServe/maxBodiesServe), 32768 for transaction broadcasts (matches maxKnownTxs). This is a minimal port of upstream go-ethereum PR #33835. The full upstream refactor (delayed message decoding with rlp.RawList) cannot be cleanly backported due to structural divergence (13 merge conflicts). References: - CVE-2026-26313: GHSA-689v-6xwf-5jf3 - Upstream fix: ethereum/go-ethereum#33835 - Issue etclabscore#692: etclabscore#692 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sduchesneau
pushed a commit
to streamingfast/go-ethereum
that referenced
this pull request
Apr 7, 2026
…thereum#33835) This changes the p2p protocol handlers to delay message decoding. It's the first part of a larger change that will delay decoding all the way through message processing. For responses, we delay the decoding until it is confirmed that the response matches an active request and does not exceed its limits. In order to make this work, all messages have been changed to use rlp.RawList instead of a slice of the decoded item type. For block bodies specifically, the decoding has been delayed all the way until after verification of the response hash. The role of p2p/tracker.Tracker changes significantly in this PR. The Tracker's original purpose was to maintain metrics about requests and responses in the peer-to-peer protocols. Each protocol maintained a single global Tracker instance. As of this change, the Tracker is now always active (regardless of metrics collection), and there is a separate instance of it for each peer. Whenever a response arrives, it is first verified that a request exists for it in the tracker. The tracker is also the place where limits are kept.
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.
This changes the p2p protocol handlers to delay message decoding. It's the first part of a larger change that will delay decoding all the way through message processing. For responses, we delay the decoding until it is confirmed that the response matches an active request and does not exceed its limits.
In order to make this work, all messages have been changed to use rlp.RawList instead of a slice of the decoded item type. For block bodies specifically, the decoding has been delayed all the way until after verification of the response hash.
The role of p2p/tracker.Tracker changes significantly in this PR. The Tracker's original purpose was to maintain metrics about requests and responses in the peer-to-peer protocols. Each protocol maintained a single global Tracker instance. As of this change, the Tracker is now always active (regardless of metrics collection), and there is a separate instance of it for each peer. Whenever a response arrives, it is first verified that a request exists for it in the tracker. The tracker is also the place where limits are kept.