fix(op-service/eth): stabilize blob fuzz targets#20940
Merged
Merged
Conversation
ea637f0 to
f1a0edb
Compare
982f703 to
d99c8e5
Compare
Blob.FromData formatted the entire input payload into the ErrBlobInputTooLarge error message via %v on eth.Data (hexutil.Bytes). For a single oversize input that produced a ~260KiB error string. Inside FuzzEncodeDecodeBlob the oversize input flowed straight into require.NoError, so each oversize execution allocated and formatted that 260KiB message; under coverage-instrumented minimization that work multiplies across iterations until the harness reports "fuzzing process hung or terminated unexpectedly while minimizing: EOF" and throughput collapses to 0 execs/sec for the remainder of fuzztime. Two minimal changes: 1. Format len(data) instead of data in the error in FromData. Add a regression assertion in TestTooLongDataEncoding that the error message stays under 1KiB. 2. In FuzzEncodeDecodeBlob, treat ErrBlobInputTooLarge as documented out-of-scope and return early, instead of asserting NoError. This removes the formatting amplification path entirely and preserves full input-size coverage (no caps). The flake is intermittent because the libFuzzer mutator only sporadically produces inputs above MaxBlobDataSize; runs that never hit the oversize branch never trigger the stall. Refs #20935
The fuzz function captured a shared *rand.Rand outside the f.Fuzz closure and used it to pick which bit to flip on each iteration. Go's fuzz engine requires fuzz targets to be deterministic for the same input — it re-runs inputs to verify reproducibility, to gather baseline coverage, and during minimization. A shared rand source meant the same input produced different behavior on re-execution, which causes worker subprocesses to stall during minimization and ultimately exit with EOF (#20936). Derive the bit to flip from a SHA-256 of the input instead, so the target is a pure function of its input. The shared Blob buffer outside the closure is fine — within one worker subprocess the fuzz callback runs sequentially.
CircleCI Gen2 docker images expose the full host core count to Go's runtime, so the fuzz harness was spawning 32 workers on an xlarge.gen2 runner (8 vCPU). The resulting 4x CPU oversubscription collapsed throughput from ~7000 execs/sec/worker to <10 and broke the Go fuzz coordinator-worker liveness heartbeats, surfacing as fuzzing process hung or terminated unexpectedly while minimizing: EOF at fuzztime. Pinning GOMAXPROCS=8 restores stable throughput (~450-550 execs/sec total over 8 workers, full 60s) and clears the flake.
…U budget" This reverts commit e30866a.
d99c8e5 to
1dea76e
Compare
hdcesario-op
requested changes
May 21, 2026
Contributor
hdcesario-op
left a comment
There was a problem hiding this comment.
Requesting one targeted fix in the remaining blob fuzz target.
Address review feedback on FuzzDetectNonBijectivity: truncate input to MaxBlobDataSize before hashing so bit selection is derived from the encoded data, and check NotEqual only on successful decode.
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.
Claude: Authored by Claude on Adrian's behalf.
Two correctness fixes in the blob fuzz path that surfaced while chasing a CI flake:
blob.go: formatlen(data)(%d) instead of the full payload (%v) in theErrBlobInputTooLargeerror. The previous form produced a ~260 KiB hex string per oversize input.FuzzEncodeDecodeBlob: truncatedtoMaxBlobDataSizeso every input exercises the round-trip.FuzzDetectNonBijectivity: derive the bit to flip fromsha256(d)instead of a shared*rand.Rand— Go fuzz requires deterministic targets.The original CI flake was on
fuzz-golang-op-servicerunning atmedium.gen2(2 vCPU) via the W4 pilot in #20899; the runner has since been resized back toxlarge.gen2in #20931. This PR is rebased onto develop to pick up that resize, and verifies the remaining test changes pass on the proper runner.Closes #20935
Closes #20936