Repository navigation
Conversation
BlockTime::since_epoch unwrapped the Option from Timestamp::since_epoch, so an out-of-range block time (seconds beyond the representable range, or nanos >= 2e9) panicked the node. This is reachable from untrusted sources: the firehose/ substreams decode path and the JSON-RPC header deserialization both feed it provider-supplied values (and a protobuf i32 `nanos` cast `as u32` turns a negative value into a huge one). Make it defensive input validation: - Add BlockTime::try_since_epoch, which returns an error instead of panicking. - deserialize_block_time and ExtendedBlockPtr's TryFrom (both already fallible) now return an error for an out-of-range block time rather than panicking. - The infallible since_epoch (used where there is no error channel, e.g. the firehose decode path and From impls) now drops a bad sub-second component and clamps an out-of-range second to BlockTime::MIN/MAX instead of panicking. Adds tests: an out-of-range timestamp in ExtendedBlockPtr deserialization is rejected as an error, and since_epoch/try_since_epoch handle out-of-range inputs without panicking.
This branch has not been deployed
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.
What
BlockTime::since_epochpanics on an out-of-range block time, and that value comes from provider-supplied input. This makes the conversion defensive input validation: return errors where there's an error channel, and clamp (never panic) where there isn't.Detail
Timestamp::since_epochwrapsDateTime::from_timestamp, which returnsNonefor an out-of-range second (year beyond ~262143) ornanos >= 2_000_000_000. The.unwrap()then panics. Both the firehose/substreams decode path (chain/ethereum/src/codec.rs) and the JSON-RPC header deserialization (deserialize_block_time,ExtendedBlockPtr::try_from) pass provider-suppliedsecs/nanosinto this — and a protobufi32nanoscastas u32can become a large value — so a malformed header crashes the node instead of being rejected.Change
BlockTime::try_since_epoch(secs, nanos) -> Result<Self, _>that returns the error instead of panicking.deserialize_block_timeandExtendedBlockPtr'sTryFrom(both already fallible) now return an error for an out-of-range block time.since_epoch(used where there's no error channel — the firehose decode path,Fromimpls, tests) now drops a bad sub-second component and clamps an out-of-range second toBlockTime::MIN/MAXrather than panicking. Valid inputs are unchanged.A maintainer may prefer the firehose path to reject such blocks upstream instead of clamping, which would mean plumbing a
Resultthrough the decoder — happy to follow up if that's the preferred direction.Tests
timestampinExtendedBlockPtrdeserialization is now rejected as an error (previously panicked).try_since_epochsurfaces the error, andsince_epochclamps, for out-of-range seconds and nanos.Verification note
The
graphcrate needs system OpenSSL to build, which my environment lacks, so I verified the conversion/clamp behaviour against the pinnedchrono = 0.4.45in a standalone crate:from_timestamp(i64::MAX, 0)andfrom_timestamp(0, 2_000_000_000)both returnNone, and the clamp composes on top to yield MIN/MAX (both cases pass). CI will run the added in-crate tests.