Skip to content

Commit 54d2162

Browse files
committed
[FAB-3549] Peer panic from bad block bytes
This CR fixes two situations that led to peer panics: 1) the block passed to GetChainIDFromBlock was nil, and 2) the payload header within the block was nil. It also tests the path through the CSCC, which resulted in a panic when the payload header was nil. Change-Id: Ice827d292823f12fead0756e956d9851770b2566 Signed-off-by: Will Lahti <[email protected]>
1 parent fa63fb9 commit 54d2162

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

core/scc/cscc/configure_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"github.com/hyperledger/fabric/msp/mgmt/testtools"
4343
peergossip "github.com/hyperledger/fabric/peer/gossip"
4444
"github.com/hyperledger/fabric/peer/gossip/mocks"
45+
cb "github.com/hyperledger/fabric/protos/common"
4546
pb "github.com/hyperledger/fabric/protos/peer"
4647
"github.com/hyperledger/fabric/protos/utils"
4748
"github.com/spf13/viper"
@@ -214,6 +215,20 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) {
214215
res := stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), nil}, sProp)
215216
assert.Equal(t, res.Status, int32(shim.ERROR))
216217

218+
// Try fail path with block and nil payload header
219+
payload, _ := proto.Marshal(&cb.Payload{})
220+
env, _ := proto.Marshal(&cb.Envelope{
221+
Payload: payload,
222+
})
223+
badBlock := &cb.Block{
224+
Data: &cb.BlockData{
225+
Data: [][]byte{env},
226+
},
227+
}
228+
badBlockBytes := utils.MarshalOrPanic(badBlock)
229+
res = stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), badBlockBytes}, sProp)
230+
assert.Equal(t, res.Status, int32(shim.ERROR))
231+
217232
// Now, continue with valid execution path
218233
if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK {
219234
t.Fatalf("cscc invoke JoinChain failed with: %v", res.Message)

protos/utils/blockutils.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,22 @@ func GetChainIDFromBlockBytes(bytes []byte) (string, error) {
3535

3636
// GetChainIDFromBlock returns chain ID in the block
3737
func GetChainIDFromBlock(block *cb.Block) (string, error) {
38-
if block.Data == nil || block.Data.Data == nil || len(block.Data.Data) == 0 {
39-
return "", fmt.Errorf("Failed to find chain ID because the block is empty.")
38+
if block == nil || block.Data == nil || block.Data.Data == nil || len(block.Data.Data) == 0 {
39+
return "", fmt.Errorf("failed to retrieve channel id - block is empty")
4040
}
4141
var err error
4242
envelope := &cb.Envelope{}
4343
if err = proto.Unmarshal(block.Data.Data[0], envelope); err != nil {
44-
return "", fmt.Errorf("Error reconstructing envelope(%s)", err)
44+
return "", fmt.Errorf("error reconstructing envelope(%s)", err)
4545
}
4646
payload := &cb.Payload{}
4747
if err = proto.Unmarshal(envelope.Payload, payload); err != nil {
48-
return "", fmt.Errorf("Error reconstructing payload(%s)", err)
48+
return "", fmt.Errorf("error reconstructing payload(%s)", err)
4949
}
5050

51+
if payload.Header == nil {
52+
return "", fmt.Errorf("failed to retrieve channel id - payload header is empty")
53+
}
5154
chdr, err := UnmarshalChannelHeader(payload.Header.ChannelHeader)
5255
if err != nil {
5356
return "", err

protos/utils/blockutils_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ func TestGetChainIDFromBlock(t *testing.T) {
4848
var gb *common.Block
4949
var cid string
5050

51+
// nil block
52+
_, err = utils.GetChainIDFromBlock(gb)
53+
assert.Error(t, err, "Expected error getting channel id from nil block")
54+
5155
gb, err = configtxtest.MakeGenesisBlock(testChainID)
5256
assert.NoError(t, err, "Failed to create test configuration block")
5357

@@ -98,6 +102,19 @@ func TestGetChainIDFromBlock(t *testing.T) {
98102
}
99103
_, err = utils.GetChainIDFromBlock(badBlock)
100104
assert.Error(t, err, "Expected error with malformed channel header")
105+
106+
// nil payload header
107+
payload, _ = proto.Marshal(&cb.Payload{})
108+
env, _ = proto.Marshal(&cb.Envelope{
109+
Payload: payload,
110+
})
111+
badBlock = &cb.Block{
112+
Data: &cb.BlockData{
113+
Data: [][]byte{env},
114+
},
115+
}
116+
_, err = utils.GetChainIDFromBlock(badBlock)
117+
assert.Error(t, err, "Expected error when payload header is nil")
101118
}
102119

103120
func TestGetBlockFromBlockBytes(t *testing.T) {

0 commit comments

Comments
 (0)