fix: add gRPC nil/zero check in query (#13352)
This commit is contained in:
parent
3d0e214446
commit
a9f02d9cb7
|
@ -172,6 +172,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||||
* (x/gov) [#13051](https://github.com/cosmos/cosmos-sdk/pull/13051) In SubmitPropsal, when a legacy msg fails it's handler call, wrap the error as ErrInvalidProposalContent (instead of ErrNoProposalHandlerExists).
|
* (x/gov) [#13051](https://github.com/cosmos/cosmos-sdk/pull/13051) In SubmitPropsal, when a legacy msg fails it's handler call, wrap the error as ErrInvalidProposalContent (instead of ErrNoProposalHandlerExists).
|
||||||
* (x/gov) [#13045](https://github.com/cosmos/cosmos-sdk/pull/13045) Fix gov migrations for v3(0.46).
|
* (x/gov) [#13045](https://github.com/cosmos/cosmos-sdk/pull/13045) Fix gov migrations for v3(0.46).
|
||||||
* (Store) [#13334](https://github.com/cosmos/cosmos-sdk/pull/13334) Call streaming listeners for deliver tx event, it was removed accidentally.
|
* (Store) [#13334](https://github.com/cosmos/cosmos-sdk/pull/13334) Call streaming listeners for deliver tx event, it was removed accidentally.
|
||||||
|
* (grpc) [#13352](https://github.com/cosmos/cosmos-sdk/pull/13352) fix grpc query panic that could crash the node.
|
||||||
* (snapshot) [#13400](https://github.com/cosmos/cosmos-sdk/pull/13400) Fix snapshot checksum issue in golang 1.19.
|
* (snapshot) [#13400](https://github.com/cosmos/cosmos-sdk/pull/13400) Fix snapshot checksum issue in golang 1.19.
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
|
@ -35,9 +35,9 @@ func TestGRPCQueryRouter(t *testing.T) {
|
||||||
require.NotNil(t, res)
|
require.NotNil(t, res)
|
||||||
require.Equal(t, "hello", res.Message)
|
require.Equal(t, "hello", res.Message)
|
||||||
|
|
||||||
require.Panics(t, func() {
|
res, err = client.Echo(context.Background(), nil)
|
||||||
_, _ = client.Echo(context.Background(), nil)
|
require.Nil(t, err)
|
||||||
})
|
require.Empty(t, res.Message)
|
||||||
|
|
||||||
res2, err := client.SayHello(context.Background(), &testdata.SayHelloRequest{Name: "Foo"})
|
res2, err := client.SayHello(context.Background(), &testdata.SayHelloRequest{Name: "Foo"})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
@ -153,9 +153,9 @@ func testQueryDataRacesSameHandler(t *testing.T, makeClientConn func(*baseapp.GR
|
||||||
require.NotNil(t, res)
|
require.NotNil(t, res)
|
||||||
require.Equal(t, "hello", res.Message)
|
require.Equal(t, "hello", res.Message)
|
||||||
|
|
||||||
require.Panics(t, func() {
|
res, err = client.Echo(context.Background(), nil)
|
||||||
_, _ = client.Echo(context.Background(), nil)
|
require.Nil(t, err)
|
||||||
})
|
require.Empty(t, res.Message)
|
||||||
|
|
||||||
res2, err := client.SayHello(context.Background(), &testdata.SayHelloRequest{Name: "Foo"})
|
res2, err := client.SayHello(context.Background(), &testdata.SayHelloRequest{Name: "Foo"})
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
|
@ -43,6 +43,11 @@ func NewProtoCodec(interfaceRegistry types.InterfaceRegistry) *ProtoCodec {
|
||||||
// NOTE: this function must be used with a concrete type which
|
// NOTE: this function must be used with a concrete type which
|
||||||
// implements proto.Message. For interface please use the codec.MarshalInterface
|
// implements proto.Message. For interface please use the codec.MarshalInterface
|
||||||
func (pc *ProtoCodec) Marshal(o ProtoMarshaler) ([]byte, error) {
|
func (pc *ProtoCodec) Marshal(o ProtoMarshaler) ([]byte, error) {
|
||||||
|
// Size() check can catch the typed nil value.
|
||||||
|
if o == nil || o.Size() == 0 {
|
||||||
|
// return empty bytes instead of nil, because nil has special meaning in places like store.Set
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
return o.Marshal()
|
return o.Marshal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,15 +3,20 @@ package codec_test
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cosmos/gogoproto/proto"
|
"github.com/cosmos/gogoproto/proto"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/encoding"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createTestInterfaceRegistry() types.InterfaceRegistry {
|
func createTestInterfaceRegistry() types.InterfaceRegistry {
|
||||||
|
@ -109,6 +114,28 @@ func TestProtoCodecMarshal(t *testing.T) {
|
||||||
|
|
||||||
err = cartoonCdc.UnmarshalInterface(bz, &cartoon)
|
err = cartoonCdc.UnmarshalInterface(bz, &cartoon)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// test typed nil input shouldn't panic
|
||||||
|
var v *banktypes.QueryBalanceResponse
|
||||||
|
bz, err = grpcServerEncode(cartoonCdc.GRPCCodec(), v)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Empty(t, bz)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emulate grpc server implementation
|
||||||
|
// https://github.com/grpc/grpc-go/blob/b1d7f56b81b7902d871111b82dec6ba45f854ede/rpc_util.go#L590
|
||||||
|
func grpcServerEncode(c encoding.Codec, msg interface{}) ([]byte, error) {
|
||||||
|
if msg == nil { // NOTE: typed nils will not be caught by this check
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
b, err := c.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
|
||||||
|
}
|
||||||
|
if uint(len(b)) > math.MaxUint32 {
|
||||||
|
return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b))
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProtoCodecUnmarshalLengthPrefixedChecks(t *testing.T) {
|
func TestProtoCodecUnmarshalLengthPrefixedChecks(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue