From 6bba9d42a54247148a6923a0fd988b99cc6c814f Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 17 Jun 2025 23:02:36 +0200 Subject: [PATCH] tests/fuzzers: added bn marshaling fuzzers (#32053) Adds marshaling fuzzing for G1 and G2 to oss-fuzz. Also aligns the behavior of the google library to that of gnark and cloudflare, which only ever read the first 64 / 128 bytes of the input, regardless of how long the input is --- crypto/bn256/google/bn256.go | 4 +-- oss-fuzz.sh | 8 +++++ tests/fuzzers/bn256/bn256_fuzz.go | 54 +++++++++++++++++++++++++++++++ tests/fuzzers/bn256/bn256_test.go | 12 +++++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/crypto/bn256/google/bn256.go b/crypto/bn256/google/bn256.go index aca9cf62de..e427b8bf42 100644 --- a/crypto/bn256/google/bn256.go +++ b/crypto/bn256/google/bn256.go @@ -128,7 +128,7 @@ func (e *G1) Marshal() []byte { func (e *G1) Unmarshal(m []byte) ([]byte, error) { // Each value is a 256-bit number. const numBytes = 256 / 8 - if len(m) != 2*numBytes { + if len(m) < 2*numBytes { return nil, errors.New("bn256: not enough data") } // Unmarshal the points and check their caps @@ -253,7 +253,7 @@ func (n *G2) Marshal() []byte { func (e *G2) Unmarshal(m []byte) ([]byte, error) { // Each value is a 256-bit number. const numBytes = 256 / 8 - if len(m) != 4*numBytes { + if len(m) < 4*numBytes { return nil, errors.New("bn256: not enough data") } // Unmarshal the points and check their caps diff --git a/oss-fuzz.sh b/oss-fuzz.sh index 4db245a781..020b6fee27 100644 --- a/oss-fuzz.sh +++ b/oss-fuzz.sh @@ -152,6 +152,14 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bn256 \ FuzzPair fuzzBn256Pair \ $repo/tests/fuzzers/bn256/bn256_test.go +compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bn256 \ + FuzzUnmarshalG1 fuzzBn256UnmarshalG1 \ + $repo/tests/fuzzers/bn256/bn256_test.go + +compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bn256 \ + FuzzUnmarshalG2 fuzzBn256UnmarshalG2 \ + $repo/tests/fuzzers/bn256/bn256_test.go + compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/txfetcher \ Fuzz fuzzTxfetcher \ $repo/tests/fuzzers/txfetcher/txfetcher_test.go diff --git a/tests/fuzzers/bn256/bn256_fuzz.go b/tests/fuzzers/bn256/bn256_fuzz.go index 4521f6b0db..d53bdbb4b9 100644 --- a/tests/fuzzers/bn256/bn256_fuzz.go +++ b/tests/fuzzers/bn256/bn256_fuzz.go @@ -161,6 +161,60 @@ func fuzzPair(data []byte) int { return 1 } +func fuzzUnmarshalG1(input []byte) int { + rc := new(cloudflare.G1) + _, errC := rc.Unmarshal(input) + + rg := new(google.G1) + _, errG := rg.Unmarshal(input) + + rs := new(gnark.G1) + _, errS := rs.Unmarshal(input) + + if errC != nil && errG != nil && errS != nil { + return 0 // bad input + } + if errC == nil && errG == nil && errS == nil { + //make sure we unmarshalled the same points: + if !bytes.Equal(rc.Marshal(), rg.Marshal()) { + panic("marshaling mismatch: cloudflare/google") + } + if !bytes.Equal(rc.Marshal(), rs.Marshal()) { + panic("marshaling mismatch: cloudflare/gnark") + } + return 1 + } else { + panic(fmt.Sprintf("error missmatch: cf: %v g: %v gn: %v", errC, errG, errS)) + } +} + +func fuzzUnmarshalG2(input []byte) int { + rc := new(cloudflare.G2) + _, errC := rc.Unmarshal(input) + + rg := new(google.G2) + _, errG := rg.Unmarshal(input) + + rs := new(gnark.G2) + _, errS := rs.Unmarshal(input) + + if errC != nil && errG != nil && errS != nil { + return 0 // bad input + } + if errC == nil && errG == nil && errS == nil { + //make sure we unmarshalled the same points: + if !bytes.Equal(rc.Marshal(), rg.Marshal()) { + panic("marshaling mismatch: cloudflare/google") + } + if !bytes.Equal(rc.Marshal(), rs.Marshal()) { + panic("marshaling mismatch: cloudflare/gnark") + } + return 1 + } else { + panic(fmt.Sprintf("error missmatch: cf: %v g: %v gn: %v", errC, errG, errS)) + } +} + // normalizeGTToGnark scales a Cloudflare/Google GT element by `s` // so that it can be compared with a gnark GT point. // diff --git a/tests/fuzzers/bn256/bn256_test.go b/tests/fuzzers/bn256/bn256_test.go index 8b2f962284..80fb850103 100644 --- a/tests/fuzzers/bn256/bn256_test.go +++ b/tests/fuzzers/bn256/bn256_test.go @@ -35,3 +35,15 @@ func FuzzPair(f *testing.F) { fuzzPair(data) }) } + +func FuzzUnmarshalG1(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + fuzzUnmarshalG1(data) + }) +} + +func FuzzUnmarshalG2(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + fuzzUnmarshalG2(data) + }) +}