Skip to content

Commit

Permalink
Use protobuf Getters to avoid nil reference (#2646)
Browse files Browse the repository at this point in the history
In the gateway registry, use the proto generated Get… methods to access the proto structures rather than direct field references.
This protects against dereferencing nil pointers for incomplete structures.  Some unit tests added.

Signed-off-by: andrew-coleman <andrew_coleman@uk.ibm.com>
  • Loading branch information
andrew-coleman authored Jun 7, 2021
1 parent 07808a0 commit 04796e6
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 10 deletions.
39 changes: 39 additions & 0 deletions internal/pkg/gateway/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,16 @@ func TestEvaluate(t *testing.T) {
},
errString: "failed to create new connection: orderer not answering",
},
{
name: "discovery returns incomplete information - no Properties",
postSetup: func(t *testing.T, def *preparedTest) {
def.discovery.PeersOfChannelReturns([]gdiscovery.NetworkMember{{
Endpoint: "localhost:7051",
PKIid: []byte("ill-defined"),
}})
},
errString: "no endorsing peers found for channel",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -428,6 +438,35 @@ func TestEndorse(t *testing.T) {
},
errString: "peach-melba",
},
{
name: "discovery returns incomplete protos - nil layout",
plan: endorsementPlan{
"g1": {{endorser: localhostMock, height: 2}},
},
postSetup: func(t *testing.T, def *preparedTest) {
ed := &dp.EndorsementDescriptor{
Chaincode: "my_channel",
Layouts: []*dp.Layout{nil},
}
def.discovery.PeersForEndorsementReturns(ed, nil)
},
errString: "failed to assemble transaction",
},
{
name: "discovery returns incomplete protos - nil state info",
plan: endorsementPlan{
"g1": {{endorser: localhostMock, height: 2}},
},
postSetup: func(t *testing.T, def *preparedTest) {
ed := &dp.EndorsementDescriptor{
Chaincode: "my_channel",
Layouts: []*dp.Layout{{QuantitiesByGroup: map[string]uint32{"g1": 1}}},
EndorsersByGroups: map[string]*dp.Peers{"g1": {Peers: []*dp.Peer{{StateInfo: nil}}}},
}
def.discovery.PeersForEndorsementReturns(ed, nil)
},
errString: "failed to select a set of endorsers that satisfy the endorsement policy",
},
{
name: "process proposal fails",
plan: endorsementPlan{
Expand Down
20 changes: 10 additions & 10 deletions internal/pkg/gateway/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,27 @@ func (reg *registry) endorsers(channel string, chaincode string) ([]*endorser, e
reg.configLock.RLock()
defer reg.configLock.RUnlock()

for _, layout := range descriptor.Layouts {
for _, layout := range descriptor.GetLayouts() {
var receivers []*endorserState // The set of peers the client needs to request endorsements from
abandonLayout := false
for group, quantity := range layout.QuantitiesByGroup {
for group, quantity := range layout.GetQuantitiesByGroup() {
// Select n remoteEndorsers from each group sorted by block height

// block heights
var groupPeers []*endorserState
for _, peer := range descriptor.EndorsersByGroups[group].Peers {
for _, peer := range descriptor.GetEndorsersByGroups()[group].GetPeers() {
msg := &gossip.GossipMessage{}
err := proto.Unmarshal(peer.StateInfo.Payload, msg)
err := proto.Unmarshal(peer.GetStateInfo().GetPayload(), msg)
if err != nil {
return nil, err
}

height := msg.GetStateInfo().Properties.LedgerHeight
err = proto.Unmarshal(peer.MembershipInfo.Payload, msg)
height := msg.GetStateInfo().GetProperties().GetLedgerHeight()
err = proto.Unmarshal(peer.GetMembershipInfo().GetPayload(), msg)
if err != nil {
return nil, err
}
endpoint := msg.GetAliveMsg().Membership.Endpoint
endpoint := msg.GetAliveMsg().GetMembership().GetEndpoint()

// find the endorser in the registry for this endpoint
var endorser *endorser
Expand Down Expand Up @@ -165,7 +165,7 @@ func (reg *registry) endorsersByOrg(channel string, chaincode string) map[string
defer reg.configLock.RUnlock()

for _, member := range members {
endpoint := member.Endpoint
endpoint := member.PreferredEndpoint()
// find the endorser in the registry for this endpoint
var endorser *endorser
if endpoint == reg.localEndorser.address {
Expand All @@ -178,8 +178,8 @@ func (reg *registry) endorsersByOrg(channel string, chaincode string) map[string
}
for _, installedChaincode := range member.Properties.GetChaincodes() {
// only consider the peers that have our chaincode installed
if installedChaincode.Name == chaincode {
endorsersByOrg[endorser.mspid] = append(endorsersByOrg[endorser.mspid], &endorserState{endorser: endorser, height: member.Properties.LedgerHeight})
if installedChaincode.GetName() == chaincode {
endorsersByOrg[endorser.mspid] = append(endorsersByOrg[endorser.mspid], &endorserState{endorser: endorser, height: member.Properties.GetLedgerHeight()})
}
}
for _, es := range endorsersByOrg {
Expand Down

0 comments on commit 04796e6

Please sign in to comment.