Add static analyzer to discourage use of panic() (#15075)

* Implement static analysis to prevent panics

* Add nopanic to nogo

* Fix violations and add exclusions

Fix violations and add exclusions for all

* Changelog fragment

* Use pass.Report instead of pass.Reportf

* Remove strings.ToLower for checking init method name

* Add exclusion for herumi init

* Move api/client/beacon template function to init and its own file

* Fix nopanic testcase
This commit is contained in:
Preston Van Loon
2025-03-19 13:04:15 -05:00
committed by GitHub
parent 16d5abd21b
commit 2aa52fb56a
74 changed files with 329 additions and 104 deletions

View File

@@ -490,6 +490,7 @@ func (b *SignedBeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) {
// of fastssz's SizeSSZ() interface function to avoid panicking.
// Changing the signature causes very problematic issues with wealdtech deps.
// For the time being panicking is preferable.
// lint:nopanic -- Panic warning is communicated in godoc commentary.
func (b *SignedBeaconBlock) SizeSSZ() int {
pb, err := b.Proto()
if err != nil {
@@ -530,7 +531,7 @@ func (b *SignedBeaconBlock) SizeSSZ() int {
}
}
// UnmarshalSSZ unmarshals the signed beacon block from its relevant ssz form.
// UnmarshalSSZ unmarshals the sitime/slots/slottime.gogned beacon block from its relevant ssz form.
// nolint:gocognit
func (b *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error {
var newBlock *SignedBeaconBlock
@@ -884,6 +885,7 @@ func (b *BeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) {
// of fastssz's SizeSSZ() interface function to avoid panicking.
// Changing the signature causes very problematic issues with wealdtech deps.
// For the time being panicking is preferable.
// lint:nopanic -- Panic is communicated in godoc.
func (b *BeaconBlock) SizeSSZ() int {
pb, err := b.Proto()
if err != nil {

View File

@@ -1,3 +1,5 @@
// package mock
// lint:nopanic -- This is test / mock code, allowed to panic.
package mock
import (

View File

@@ -27,7 +27,7 @@ func MaxEpoch(a, b Epoch) Epoch {
func (e Epoch) Mul(x uint64) Epoch {
res, err := e.SafeMul(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -44,7 +44,7 @@ func (e Epoch) SafeMul(x uint64) (Epoch, error) {
func (e Epoch) Div(x uint64) Epoch {
res, err := e.SafeDiv(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -61,7 +61,7 @@ func (e Epoch) SafeDiv(x uint64) (Epoch, error) {
func (e Epoch) Add(x uint64) Epoch {
res, err := e.SafeAdd(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -90,7 +90,7 @@ func (e Epoch) SafeAddEpoch(x Epoch) (Epoch, error) {
func (e Epoch) Sub(x uint64) Epoch {
res, err := e.SafeSub(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -107,7 +107,7 @@ func (e Epoch) SafeSub(x uint64) (Epoch, error) {
func (e Epoch) Mod(x uint64) Epoch {
res, err := e.SafeMod(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}

View File

@@ -19,7 +19,7 @@ type Slot uint64
func (s Slot) Mul(x uint64) Slot {
res, err := s.SafeMul(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -48,7 +48,7 @@ func (s Slot) SafeMulSlot(x Slot) (Slot, error) {
func (s Slot) Div(x uint64) Slot {
res, err := s.SafeDiv(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -77,7 +77,7 @@ func (s Slot) SafeDivSlot(x Slot) (Slot, error) {
func (s Slot) Add(x uint64) Slot {
res, err := s.SafeAdd(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -106,7 +106,7 @@ func (s Slot) SafeAddSlot(x Slot) (Slot, error) {
func (s Slot) Sub(x uint64) Slot {
res, err := s.SafeSub(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}
@@ -143,7 +143,7 @@ func (s Slot) SafeSubSlot(x Slot) (Slot, error) {
func (s Slot) Mod(x uint64) Slot {
res, err := s.SafeMod(x)
if err != nil {
panic(err.Error())
panic(err.Error()) // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return res
}

View File

@@ -14,9 +14,10 @@ var _ fssz.Unmarshaler = (*ValidatorIndex)(nil)
type ValidatorIndex uint64
// Div divides validator index by x.
// This method panics if dividing by zero!
func (v ValidatorIndex) Div(x uint64) ValidatorIndex {
if x == 0 {
panic("divbyzero")
panic("divbyzero") // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return ValidatorIndex(uint64(v) / x)
}
@@ -27,9 +28,10 @@ func (v ValidatorIndex) Add(x uint64) ValidatorIndex {
}
// Sub subtracts x from the validator index.
// This method panics if causing an underflow!
func (v ValidatorIndex) Sub(x uint64) ValidatorIndex {
if uint64(v) < x {
panic("underflow")
panic("underflow") // lint:nopanic -- Panic is communicated in the godoc commentary.
}
return ValidatorIndex(uint64(v) - x)
}