tests/fuzzers: added bn marshaling fuzzers #32053 (#1228)

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

Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
This commit is contained in:
Daniel Liu 2025-07-26 17:36:58 +08:00 committed by GitHub
parent f30a126380
commit 0fd51f13a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 105 additions and 5 deletions

View file

@ -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

View file

@ -14,9 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
//go:build gofuzz
// +build gofuzz
package bn256
import (
@ -164,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.
//

View file

@ -0,0 +1,49 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package bn256
import "testing"
func FuzzAdd(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzAdd(data)
})
}
func FuzzMul(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
fuzzMul(data)
})
}
func FuzzPair(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
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)
})
}