fix: types: ensure .Amount is non-nil in Coin.Validate() (#15691)

This change fixes a scenario in which Coin.Validate() would panic when given a nil Amount.
While here, added a fuzz test along with unit/regression tests.

Fixes #15690
This commit is contained in:
Emmanuel T Odeke
2023-04-05 07:36:36 +00:00
committed by GitHub
parent 5b1ee227c2
commit a7e2df2a46
4 changed files with 64 additions and 0 deletions
+5
View File
@@ -2,6 +2,7 @@ package types
import (
"encoding/json"
"errors"
"fmt"
"regexp"
"sort"
@@ -44,6 +45,10 @@ func (coin Coin) Validate() error {
return err
}
if coin.Amount.IsNil() {
return errors.New("amount is nil")
}
if coin.Amount.IsNegative() {
return fmt.Errorf("negative coin amount: %v", coin.Amount)
}
+34
View File
@@ -1276,6 +1276,40 @@ func (s *coinTestSuite) TestMarshalJSONCoins() {
}
}
func (s *coinTestSuite) TestCoinValidate() {
testCases := []struct {
name string
coin sdk.Coin
wantErr string
}{
{"nil coin: nil Amount", sdk.Coin{}, "invalid denom"},
{"non-blank coin, nil Amount", sdk.Coin{Denom: "atom"}, "amount is nil"},
{"valid coin", sdk.Coin{Denom: "atom", Amount: math.NewInt(100)}, ""},
{"negative coin", sdk.Coin{Denom: "atom", Amount: math.NewInt(-999)}, "negative coin amount"},
}
for _, tc := range testCases {
tc := tc
t := s.T()
t.Run(tc.name, func(t *testing.T) {
err := tc.coin.Validate()
if tc.wantErr == "" {
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
return
} else {
if err == nil {
t.Error("Expected an error")
} else if !strings.Contains(err.Error(), tc.wantErr) {
t.Errorf("Error mismatch\n\tGot: %q\nWant: %q", err, tc.wantErr)
}
}
})
}
}
func (s *coinTestSuite) TestCoinAminoEncoding() {
cdc := codec.NewLegacyAmino()
c := sdk.NewInt64Coin(testDenom1, 5)
+24
View File
@@ -0,0 +1,24 @@
package types
import (
"testing"
"github.com/cosmos/cosmos-sdk/codec"
)
func FuzzCoinUnmarshalJSON(f *testing.F) {
if testing.Short() {
f.Skip()
}
cdc := codec.NewLegacyAmino()
f.Add(`{"denom":"atom","amount":"1000"}`)
f.Add(`{"denom":"atom","amount":"-1000"}`)
f.Add(`{"denom":"uatom","amount":"1000111111111111111111111"}`)
f.Add(`{"denom":"mu","amount":"0"}`)
f.Fuzz(func(t *testing.T, jsonBlob string) {
var c Coin
_ = cdc.UnmarshalJSON([]byte(jsonBlob), &c)
})
}