Repository navigation
Reject oversized node response size before zeroing the receive buffer - #135
Merged
Merged
Conversation
fnordspace
requested changes
Oct 15, 2026
fnordspace
left a comment
Contributor
There was a problem hiding this comment.
Good catch, need slight adjustments. Also please keep comments short and concise and only where the code is not self-explanatory.
Thanks for the submission!
…buffer receivePacketWithHeaderAs zeroed `remainingSize` bytes of mBuffer, but remainingSize is derived from the node-controlled header size() (which returns INT32_MAX when the size field is zero), so it can exceed mBuffer and std::fill_n would write past it. Fill only sizeof(T) -- the bytes actually read back into result -- and let receiveData()'s existing `sz > buffer.size()` guard reject an oversized payload.
parthod0x
force-pushed
the
fix/validate-node-response-size
branch
from
October 15, 2026 18:18
53098ee to
4f11964
Compare
Contributor
Author
|
Adopted your approach: fill only |
fnordspace
approved these changes
Oct 20, 2026
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.
receivePacketWithHeaderAscomputesremainingSize = header.size() - sizeof(RequestResponseHeader)from anode-controlled value, then runs
std::fill_n(mBuffer.begin(), remainingSize, 0)before any bound check.RequestResponseHeader::size()returnsINT32_MAXwhen the 24-bit size fieldis zero (the code comments "size is never zero, zero means broken packets"). So
a node that sends a response header with a zero size field produces
remainingSize == 2147483639, andfill_nwrites ~2.1 GB into the 16 MBmBuffer— well past its end.Confirmed with AddressSanitizer:
global-buffer-overflow, WRITE of size 2147483639. A malicious or malfunctioning node can corrupt the memory of anyclient that queries it (the client trusts the node only for its response, but
this happens before the size is validated).
Fix
Require
remainingSize > 0and reject aremainingSizelarger than the receivebuffer before
fill_n.receiveDataalready throws on an oversized read,but
fill_nran first; this closes that window.Verified: the oversize case overflows under ASAN on current
main; with theguard it is rejected before
fill_n, andg++ -std=c++20 -fsyntax-onlyis clean.This is the response-parsing path, distinct from the user-input buffer fixes in
#133 and #134, and is the more security-relevant of the set because it is
triggerable by the remote node rather than by local input.