Skip to content

Commit

Permalink
Prevent peer from failure on malformed proposal
Browse files Browse the repository at this point in the history
While new peer gateway service is trying to extract channel and
chaincode information from the signed proposal it doesn't check
the proposal fields for validity and therefore malformed proposal
might end up with crashing peer service. This commit adds
validation to the parameters extracted from the proposal.

Signed-off-by: Artem Barger <artem@bargr.net>
(cherry picked from commit 7478f53)
  • Loading branch information
C0rWin authored and denyeart committed Aug 8, 2022
1 parent 7c12fa6 commit 468332c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
56 changes: 56 additions & 0 deletions internal/pkg/gateway/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1973,6 +1973,62 @@ func TestNilArgs(t *testing.T) {
_, err = server.Evaluate(ctx, &pb.EvaluateRequest{ProposedTransaction: &peer.SignedProposal{ProposalBytes: []byte("jibberish")}})
require.ErrorContains(t, err, "failed to unpack transaction proposal: error unmarshalling Proposal")

request := &pb.EvaluateRequest{ProposedTransaction: &peer.SignedProposal{
ProposalBytes: protoutil.MarshalOrPanic(&peer.Proposal{
Header: protoutil.MarshalOrPanic(&cp.Header{}),
Payload: protoutil.MarshalOrPanic(&peer.ChaincodeActionPayload{
ChaincodeProposalPayload: protoutil.MarshalOrPanic(&peer.ChaincodeProposalPayload{
Input: protoutil.MarshalOrPanic(&peer.ChaincodeInvocationSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
ChaincodeId: &peer.ChaincodeID{
Name: "testChaincode",
},
},
}),
}),
}),
}),
}}
require.True(t, len(request.GetProposedTransaction().GetProposalBytes()) != 0)
_, err = server.Evaluate(ctx, request)
require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "failed to unpack transaction proposal: no channel id provided"))

_, err = server.Evaluate(ctx, &pb.EvaluateRequest{ProposedTransaction: &peer.SignedProposal{
ProposalBytes: protoutil.MarshalOrPanic(&peer.Proposal{
Header: protoutil.MarshalOrPanic(&cp.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cp.ChannelHeader{
ChannelId: "test",
}),
}),
Payload: protoutil.MarshalOrPanic(&peer.ChaincodeActionPayload{
ChaincodeProposalPayload: protoutil.MarshalOrPanic(&peer.ChaincodeProposalPayload{
Input: nil,
}),
}),
}),
}})
require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "failed to unpack transaction proposal: no chaincode spec is provided, channel id [test]"))

_, err = server.Evaluate(ctx, &pb.EvaluateRequest{ProposedTransaction: &peer.SignedProposal{
ProposalBytes: protoutil.MarshalOrPanic(&peer.Proposal{
Header: protoutil.MarshalOrPanic(&cp.Header{
ChannelHeader: protoutil.MarshalOrPanic(&cp.ChannelHeader{
ChannelId: "test",
}),
}),
Payload: protoutil.MarshalOrPanic(&peer.ChaincodeActionPayload{
ChaincodeProposalPayload: protoutil.MarshalOrPanic(&peer.ChaincodeProposalPayload{
Input: protoutil.MarshalOrPanic(&peer.ChaincodeSpec{
ChaincodeId: &peer.ChaincodeID{
Name: "",
},
}),
}),
}),
}),
}})
require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "failed to unpack transaction proposal: no chaincode name is provided, channel id [test]"))

_, err = server.Endorse(ctx, nil)
require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "an endorse request is required"))

Expand Down
18 changes: 17 additions & 1 deletion internal/pkg/gateway/apiutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,23 @@ func getChannelAndChaincodeFromSignedProposal(signedProposal *peer.SignedProposa
return "", "", false, err
}

return channelHeader.GetChannelId(), spec.GetChaincodeSpec().GetChaincodeId().GetName(), len(payload.GetTransientMap()) > 0, nil
if len(channelHeader.GetChannelId()) == 0 {
return "", "", false, fmt.Errorf("no channel id provided")
}

if spec.GetChaincodeSpec() == nil {
return "", "", false, fmt.Errorf("no chaincode spec is provided, channel id [%s]", channelHeader.GetChannelId())
}

if spec.GetChaincodeSpec().GetChaincodeId() == nil {
return "", "", false, fmt.Errorf("no chaincode id is provided, channel id [%s]", channelHeader.GetChannelId())
}

if len(spec.GetChaincodeSpec().GetChaincodeId().GetName()) == 0 {
return "", "", false, fmt.Errorf("no chaincode name is provided, channel id [%s]", channelHeader.GetChannelId())
}

return channelHeader.GetChannelId(), spec.GetChaincodeSpec().GetChaincodeId().GetName(), len(payload.TransientMap) > 0, nil
}

func newRpcError(code codes.Code, message string, details ...proto.Message) error {
Expand Down

0 comments on commit 468332c

Please sign in to comment.