diff --git a/protocols/bgp/packet/large_community.go b/protocols/bgp/packet/large_community.go index 5b3f7788b16c921f114880ac36d04e8868938627..7547fd60c1dce29886d917ae72b889613b898617 100644 --- a/protocols/bgp/packet/large_community.go +++ b/protocols/bgp/packet/large_community.go @@ -2,10 +2,13 @@ package packet import ( "fmt" + "regexp" "strconv" "strings" ) +var largeCommunityRegEx = regexp.MustCompile("^\\(?\\d+,\\d+,\\d+\\)?$") + type LargeCommunity struct { GlobalAdministrator uint32 DataPart1 uint32 @@ -17,13 +20,12 @@ func (c LargeCommunity) String() string { } func ParseLargeCommunityString(s string) (com LargeCommunity, err error) { + if !largeCommunityRegEx.Match([]byte(s)) { + return com, fmt.Errorf("malformed large community string %s", s) + } s = strings.Trim(s, "()") t := strings.Split(s, ",") - if len(t) != 3 { - return com, fmt.Errorf("can not parse large community %s", s) - } - v, err := strconv.ParseUint(t[0], 10, 32) if err != nil { return com, err diff --git a/protocols/bgp/packet/large_community_test.go b/protocols/bgp/packet/large_community_test.go new file mode 100644 index 0000000000000000000000000000000000000000..867fe27e073b3246ee806f5fd0f04fb1b28daccc --- /dev/null +++ b/protocols/bgp/packet/large_community_test.go @@ -0,0 +1,86 @@ +package packet + +import ( + "errors" + "testing" + + "fmt" + "math" + + "strconv" + + "github.com/stretchr/testify/assert" +) + +func TestParseLargeCommunityString(t *testing.T) { + tests := []struct { + name string + in string + expected LargeCommunity + err error + }{ + { + name: "normal large community", + in: "(1,2,3)", + expected: LargeCommunity{ + GlobalAdministrator: 1, + DataPart1: 2, + DataPart2: 3, + }, + err: nil, + }, + { + name: "too short community", + in: "(1,2)", + expected: LargeCommunity{}, + err: errors.New("malformed large community string (1,2)"), + }, + { + name: "missing parentheses large community", + in: "1,2,3", + expected: LargeCommunity{ + GlobalAdministrator: 1, + DataPart1: 2, + DataPart2: 3, + }, + err: nil, + }, + { + name: "malformed large community", + in: "[1,2,3]", + expected: LargeCommunity{}, + err: errors.New("malformed large community string [1,2,3]"), + }, + { + name: "missing digit", + in: "(,2,3)", + expected: LargeCommunity{}, + err: errors.New("malformed large community string (,2,3)"), + }, + { + name: "to big global administrator", + in: fmt.Sprintf("(%d,1,2)", math.MaxInt64), + expected: LargeCommunity{}, + err: &strconv.NumError{Func: "ParseUint", Num: fmt.Sprintf("%d", math.MaxInt64), Err: strconv.ErrRange}, + }, + { + name: "to big data part 1", + in: fmt.Sprintf("(1,%d,2)", math.MaxInt64), + expected: LargeCommunity{1, 0, 0}, + err: &strconv.NumError{Func: "ParseUint", Num: fmt.Sprintf("%d", math.MaxInt64), Err: strconv.ErrRange}, + }, + { + name: "to big data part 2", + in: fmt.Sprintf("(1,2,%d)", math.MaxInt64), + expected: LargeCommunity{1, 2, 0}, + err: &strconv.NumError{Func: "ParseUint", Num: fmt.Sprintf("%d", math.MaxInt64), Err: strconv.ErrRange}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + com, err := ParseLargeCommunityString(test.in) + assert.Equal(t, test.err, err) + assert.Equal(t, test.expected, com) + }) + } +}