diff --git a/boc/boc.go b/boc/boc.go index 7c297873..69ce2177 100644 --- a/boc/boc.go +++ b/boc/boc.go @@ -27,6 +27,9 @@ const depthSize = 2 const maxLevel = 3 const maxDepth = 1024 const maxCellWhs = 64 +const minCellSize = 4 +const minTotCellsSize = 2 +const maxCellsCount = 131072 var crcTable = crc32.MakeTable(crc32.Castagnoli) @@ -99,6 +102,10 @@ func parseBocHeader(boc []byte) (*bocHeader, error) { return nil, errors.New("not enough bytes for encoding cells counters") } + if sizeBytes > minCellSize { + return nil, errors.New("invalid cell size value") + } + offsetBytes := int(boc[0]) boc = boc[1:] cellsCount := readNBytesUIntFromArray(sizeBytes, boc) @@ -114,6 +121,18 @@ func parseBocHeader(boc []byte) (*bocHeader, error) { return nil, errors.New("not enough bytes for encoding root cells hashes") } + if totCellsSize < minTotCellsSize { + return nil, errors.New("invalid cell data size value") + } + + if 2*cellsCount > totCellsSize { + return nil, errors.New("not enough bytes for encoding all cells data") + } + + if cellsCount > maxCellsCount { + return nil, errors.New("boc is too large") + } + // Roots rootList := make([]uint, 0, rootsCount) for i := 0; i < int(rootsCount); i++ { diff --git a/boc/boc_test.go b/boc/boc_test.go index 46ace8bd..13bbbd68 100644 --- a/boc/boc_test.go +++ b/boc/boc_test.go @@ -383,3 +383,44 @@ func Test_bagOfCells_serializeBoc(t *testing.T) { }) } } + +func Test_bagOfCells_invalidCellDeserialize(t *testing.T) { + tests := []struct { + name string + hexBoc string + err string + }{ + { + name: "boc with invalid large size bytes", + hexBoc: "b5ee9c720501010100020000001231231231232131231231231231231231231231", + err: "invalid cell size value", + }, + { + name: "boc with invalid small tot_cells_size", + hexBoc: "b5ee9c72010101010001000000", + err: "invalid cell data size value", + }, + { + name: "boc with invalid large amount with cells", + hexBoc: "b5ee9c720101ff010002000000", + err: "not enough bytes for encoding all cells data", + }, + { + name: "too large boc", + hexBoc: "b5ee9c7204fffffffffe010002000000123123123123213123123123123123123123123123123123123123" + strings.Repeat("1234", 33565456), + err: "boc is too large", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bocBytes, err := hex.DecodeString(tt.hexBoc) + if err != nil { + t.Fatalf("failed to decode boc: %v", err) + } + _, err = DeserializeBoc(bocBytes) + if err == nil || err.Error() != tt.err { + t.Fatalf("invalid error: %v", err) + } + }) + } +}