From ec45a79a0a746dc3c7d6961db698b0039d96a138 Mon Sep 17 00:00:00 2001 From: D Lohachov Date: Thu, 24 Jan 2019 16:35:34 +0000 Subject: [PATCH] Fix two bugs: - nvdjson.smartVerCmp was comparing the full version strings instead of major, minor, path etc. substrings; - off-by-one error in AttributeColumnMap.CPE() --- cmd/csv2cpe/csv2cpe.go | 2 +- cmd/csv2cpe/csv2cpe_test.go | 71 +++++++++++++------- cvefeed/internal/nvdjson/interfaces.go | 6 +- cvefeed/internal/nvdjson/smartvercmp_test.go | 1 + 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/cmd/csv2cpe/csv2cpe.go b/cmd/csv2cpe/csv2cpe.go index aadc2aa..7c097c4 100644 --- a/cmd/csv2cpe/csv2cpe.go +++ b/cmd/csv2cpe/csv2cpe.go @@ -180,7 +180,7 @@ func (acm *AttributeColumnMap) CPE(cols []string, lower bool) (string, error) { for i, v := range m { j := i - 1 - if len(cols) < j { + if j >= len(cols) { continue } diff --git a/cmd/csv2cpe/csv2cpe_test.go b/cmd/csv2cpe/csv2cpe_test.go index 7ce7c37..c7a7a7a 100644 --- a/cmd/csv2cpe/csv2cpe_test.go +++ b/cmd/csv2cpe/csv2cpe_test.go @@ -17,6 +17,7 @@ package main import ( "bytes" "flag" + "fmt" "reflect" "testing" ) @@ -74,37 +75,59 @@ func TestRemoveColumns(t *testing.T) { } func TestProcessor(t *testing.T) { - fs := flag.NewFlagSet("test", flag.ContinueOnError) + cases := []struct { + flags []string + skips IntSet + in string + out string + }{ + { + []string{"-cpe_product=1", "-cpe_version=2"}, + NewIntSet(1, 2, 3), + "Foo\t1.0...\tdelet\ta\nbar\t2.0\tdelet\tb", + "a,cpe:/::foo:1.0\nb,cpe:/::bar:2.0\n", + }, + { + []string{"-cpe_part=1", "-cpe_product=2", "-cpe_product=4"}, + NewIntSet(1, 2, 3), + "a\tb\tc\n", + "cpe:/a\n", + }, + } - acm := &AttributeColumnMap{} - acm.AddFlags(fs) + for n, c := range cases { + t.Run(fmt.Sprintf("case_%d", n), func(t *testing.T) { + fs := flag.NewFlagSet("test", flag.ContinueOnError) - err := fs.Parse([]string{"-cpe_product=1", "-cpe_version=2"}) - if err != nil { - t.Fatal(err) - } + acm := &AttributeColumnMap{} + acm.AddFlags(fs) - var stdin, stdout bytes.Buffer + err := fs.Parse(c.flags) + if err != nil { + t.Fatal(err) + } - p := &Processor{ - InputComma: rune('\t'), - OutputComma: rune(','), - CPEToLower: true, - CPEOutputColumn: 2, - EraseInputColumns: NewIntSet(1, 2, 3), - } + var stdin, stdout bytes.Buffer - stdin.Write([]byte("Foo\t1.0...\tdelet\ta\nbar\t2.0\tdelet\tb")) + p := &Processor{ + InputComma: rune('\t'), + OutputComma: rune(','), + CPEToLower: true, + CPEOutputColumn: 2, + EraseInputColumns: c.skips, + } - err = p.Process(acm, &stdin, &stdout) - if err != nil { - t.Fatal(err) - } + stdin.Write([]byte(c.in)) - have := stdout.String() - want := "a,cpe:/::foo:1.0\nb,cpe:/::bar:2.0\n" + err = p.Process(acm, &stdin, &stdout) + if err != nil { + t.Fatal(err) + } - if have != want { - t.Fatalf("unexpected output:\nwant: %q\nhave: %q\n", want, have) + if out := stdout.String(); out != c.out { + t.Fatalf("unexpected output:\nwant: %q\nhave: %q\n", c.out, out) + } + }) } + } diff --git a/cvefeed/internal/nvdjson/interfaces.go b/cvefeed/internal/nvdjson/interfaces.go index 0dc3825..7046970 100644 --- a/cvefeed/internal/nvdjson/interfaces.go +++ b/cvefeed/internal/nvdjson/interfaces.go @@ -147,8 +147,8 @@ func node2CPE(node *NVDCVEFeedJSON10DefCPEMatch) (*wfn.Attributes, error) { // Returns -1 if v1 < v2, 1 if v1 > v2 and 0 if v1 == v2. func smartVerCmp(v1, v2 string) int { for s1, s2 := v1, v2; len(s1) > 0 && len(s2) > 0; { - num1, alpha1, skip1 := parseVerParts(v1) - num2, alpha2, skip2 := parseVerParts(v2) + num1, alpha1, skip1 := parseVerParts(s1) + num2, alpha2, skip2 := parseVerParts(s2) if num1 > num2 { return 1 } @@ -183,6 +183,8 @@ func parseVerParts(v string) (num int, alpha string, skip int) { skip = strings.IndexRune(v, '.') if skip == -1 { skip = len(v) + } else { + skip++ } } return num, v[alphaAt:skip], skip diff --git a/cvefeed/internal/nvdjson/smartvercmp_test.go b/cvefeed/internal/nvdjson/smartvercmp_test.go index de275f6..1e47f97 100644 --- a/cvefeed/internal/nvdjson/smartvercmp_test.go +++ b/cvefeed/internal/nvdjson/smartvercmp_test.go @@ -29,6 +29,7 @@ func TestSmartVerCmp(t *testing.T) { {"1.0.14", "1.0.4", 1}, {"95SE", "98SP1", -1}, {"16.0.0", "3.2.7", 1}, + {"10.23", "10.21", 1}, } for _, c := range cases { t.Run(fmt.Sprintf("%q vs %q", c.v1, c.v2), func(t *testing.T) {