CVE-2022-39213: Out-of-bounds Read (CWE-125)
value: go-cvss is a Go module to manipulate Common Vulnerability Scoring System (CVSS). In affected versions when a full CVSS v2.0 vector string is parsed using `ParseVector`, an Out-of-Bounds Read is possible due to a lack of tests. The Go module will then panic. The problem is patched in tag `v0.4.0`, by the commit `d9d478ff0c13b8b09ace030db9262f3c2fe031f4`. Users are advised to upgrade. Users unable to upgrade may avoid this issue by parsing only CVSS v2.0 vector strings that do not have all attributes defined (e.g. `AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M`). As stated in [SECURITY.md](https://github.com/pandatix/go-cvss/blob/master/SECURITY.md), the CPE v2.3 to refer to this Go module is `cpe:2.3:a:pandatix:go_cvss:*:*:*:*:*:*:*:*`. The entry has already been requested to the NVD CPE dictionary.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.5
Published: 2022-09-15T22:15Z
Repository: https://github.com/pandatix/go-cvss
Language: Go
Files changed: 20/cvss20.go, 20/cvss20_bench_test.go, 20/cvss20_fuzz_test.go, 20/cvss20_test.go, 20/errors.go, README.md
Commit date: 2022-09-13 19:46:05 +0200
Commit message: Improve CVSS v2.0 implementation (0/1 allocs/op)

Diff: diff --git a/20/cvss20.go b/20/cvss20.go
index 0ee29ea..dddee92 100644
--- a/20/cvss20.go
+++ b/20/cvss20.go
@@ -1,176 +1,254 @@
 package gocvss20
 
 import (
 	"math"
 	"strings"
+	"sync"
+	"unsafe"
 )
 
+var order = [][]string{
+	{"AV", "AC", "Au", "C", "I", "A"}, // Base metrics
+	{"E", "RL", "RC"},                 // Temporal metrics
+	{"CDP", "TD", "CR", "IR", "AR"},   // Environmental metrics
+}
+
 // ParseVector parses a CVSS v2.0 vector.
 func ParseVector(vector string) (*CVSS20, error) {
 	// Split parts
-	pts := strings.Split(vector, "/")
-	if len(pts) != 6 && len(pts) != 9 && len(pts) != 14 {
+	pts, l := split(vector)
+	if l != 6 && l != 9 && l != 14 {
 		return nil, ErrTooShortVector
 	}
+	pts = pts[:l]
 
 	// Work on each CVSS part
 	cvss20 := &CVSS20{
-		Base: Base{},
-		Temporal: Temporal{
-			Exploitability:   "ND",
-			RemediationLevel: "ND",
-			ReportConfidence: "ND",
+		base: base{},
+		temporal: temporal{
+			exploitability:   "ND",
+			remediationLevel: "ND",
+			reportConfidence: "ND",
 		},
-		Environmental: Environmental{
-			CollateralDamagePotential:  "ND",
-			TargetDistribution:         "ND",
-			ConfidentialityRequirement: "ND",
-			IntegrityRequirement:       "ND",
-			AvailabilityRequirement:    "ND",
+		environmental: environmental{
+			collateralDamagePotential:  "ND",
+			targetDistribution:         "ND",
+			confidentialityRequirement: "ND",
+			integrityRequirement:       "ND",
+			availabilityRequirement:    "ND",
 		},
 	}
 
-	// Parse metrics in order
-	slcs := [][]string{
-		{"AV", "AC", "Au", "C", "I", "A"}, // Base metrics
-		{"E", "RL", "RC"},                 // Temporal metrics
-		{"CDP", "TD", "CR", "IR", "AR"},   // Environmental metrics
-	}
 	slci := 0
-	currSlc := slcs[slci]
 	i := 0
 	for _, pt := range pts {
 		abv, v, _ := strings.Cut(pt, ":")
-		if abv != currSlc[i] {
+		if slci == 4 {
+			return nil, &ErrDefinedN{Abv: abv}
+		}
+		if abv != order[slci][i] {
 			return nil, ErrInvalidMetricOrder
 		}
+
 		if err := cvss20.Set(abv, v); err != nil {
 			return nil, err
 		}
+
 		// Go to next element in slice, or next slice if fully consumed
 		i++
-		if i == len(currSlc) {
+		if i == len(order[slci]) {
 			slci++
-			currSlc = slcs[slci]
 			i = 0
 		}
 	}
 
 	return cvss20, nil
 }
 
+var splitPool = sync.Pool{
+	New: func() any {
+		return make([]string, 14)
+	},
+}
+
+func split(vector string) ([]string, int) {
+	partsPtr := splitPool.Get()
+	defer splitPool.Put(partsPtr)
+	parts := partsPtr.([]string)
+
+	start := 0
+	curr := 0
+	l := len(vector)
+	i := 0
+	for ; i < l; i++ {
+		if vector[i] == '/' {
+			parts[curr] = vector[start:i]
+
+			start = i + 1
+			curr++
+
+			if curr == 13 {
+				break
+			}
+		}
+	}
+	parts[curr] = vector[start:]
+	return parts, curr + 1
+}
+
 func (cvss20 CVSS20) Vector() string {
-	s := ""
+	l := lenVec(&cvss20)
+	b := make([]byte, 0, l)
+
 	// Base
-	s += "AV:" + cvss20.AccessVector
-	s += "/AC:" + cvss20.AccessComplexity
-	s += "/Au:" + cvss20.Authentication
-	s += "/C:" + cvss20.ConfidentialityImpact
-	s += "/I:" + cvss20.IntegrityImpact
-	s += "/A:" + cvss20.AvailabilityImpact
-	// Temporal, if any is defined
-	if cvss20.Exploitability != "ND" || cvss20.RemediationLevel != "ND" || cvss20.ReportConfidence != "ND" {
-		s += "/E:" + cvss20.Exploitability
-		s += "/RL:" + cvss20.RemediationLevel
-		s += "/RC:" + cvss20.ReportConfidence
+	app(&b, "AV:", cvss20.accessVector)
+	app(&b, "/AC:", cvss20.accessComplexity)
+	app(&b, "/Au:", cvss20.authentication)
+	app(&b, "/C:", cvss20.confidentialityImpact)
+	app(&b, "/I:", cvss20.integrityImpact)
+	app(&b, "/A:", cvss20.availabilityImpact)
+
+	// Temporal
+	if cvss20.exploitability != "ND" || cvss20.remediationLevel != "ND" || cvss20.reportConfidence != "ND" {
+		app(&b, "/E:", cvss20.exploitability)
+		app(&b, "/RL:", cvss20.remediationLevel)
+		app(&b, "/RC:", cvss20.reportConfidence)
 	}
-	// Environmental, if any is defined
-	if cvss20.CollateralDamagePotential != "ND" || cvss20.TargetDistribution != "ND" || cvss20.ConfidentialityRequirement != "ND" || cvss20.IntegrityRequirement != "ND" || cvss20.AvailabilityRequirement != "ND" {
-		s += "/CDP:" + cvss20.CollateralDamagePotential
-		s += "/TD:" + cvss20.TargetDistribution
-		s += "/CR:" + cvss20.ConfidentialityRequirement
-		s += "/IR:" + cvss20.IntegrityRequirement
-		s += "/AR:" + cvss20.AvailabilityRequirement
+
+	// Environmental
+	if cvss20.collateralDamagePotential != "ND" || cvss20.targetDistribution != "ND" || cvss20.confidentialityRequirement != "ND" || cvss20.integrityRequirement != "ND" || cvss20.availabilityRequirement != "ND" {
+		app(&b, "/CDP:", cvss20.collateralDamagePotential)
+		app(&b, "/TD:", cvss20.targetDistribution)
+		app(&b, "/CR:", cvss20.confidentialityRequirement)
+		app(&b, "/IR:", cvss20.integrityRequirement)
+		app(&b, "/AR:", cvss20.availabilityRequirement)
 	}
-	return s
+
+	return *(*string)(unsafe.Pointer(&b))
+}
+
+func lenVec(cvss20 *CVSS20) int {
+	// Base:
+	// - AV, AC, Au: 4
+	// - C, I, A: 3
+	// - separators: 5
+	// Total: 3*4 + 3*3 + 5 = 30
+	l := 26
+
+	// Temporal:
+	// - E: 2 + len(v)
+	// - RL: 3 + len(v)
+	// - RC: 3 + len(v)
+	// - separators: 3
+	// Total: 11 + 3*len(v)
+	if cvss20.exploitability != "ND" || cvss20.remediationLevel != "ND" || cvss20.reportConfidence != "ND" {
+		l += 11 + len(cvss20.exploitability) + len(cvss20.remediationLevel) + len(cvss20.reportConfidence)
+	}
+
+	// Environmental:
+	// - CDP: 4 + len(v)
+	// - TD: 3 + len(v)
+	// - CR, IR, AR: 3 + len(v)
+	// - separators: 5
+	// Total: 21 + 5*len(v)
+	if cvss20.collateralDamagePotential != "ND" || cvss20.targetDistribution != "ND" || cvss20.confidentialityRequirement != "ND" || cvss20.integrityRequirement != "ND" || cvss20.availabilityRequirement != "ND" {
+		l += 21 + len(cvss20.collateralDamagePotential) + len(cvss20.targetDistribution) + len(cvss20.confidentialityRequirement) + len(cvss20.integrityRequirement) + len(cvss20.availabilityRequirement)
+	}
+
+	return l
+}
+
+func app(b *[]byte, pre, v string) {
+	*b = append(*b, pre...)
+	*b = append(*b, v...)
 }
 
 // CVSS20 embeds all the metric values defined by the CVSS v2.0
 // rev2 specification.
 // Attributes values must not be manipulated directly. Use Get
 // and Set methods.
 type CVSS20 struct {
-	Base
-	Temporal
-	Environmental
+	base
+	temporal
+	environmental
 }
 
-// Base is the group of metrics defined with such name by the
+// base is the group of metrics defined with such name by the
 // first.org CVSS v2.0 rev2 specification.
 // Mandatory.
-type Base struct {
+type base struct {
 	// AV -> [L,A,N]
-	AccessVector string
+	accessVector string
 	// AC -> [H,M,L]
-	AccessComplexity string
+	accessComplexity string
 	// Au -> [M,S,N]
-	Authentication string
+	authentication string
 	// C -> [N,P,C]
-	ConfidentialityImpact string
+	confidentialityImpact string
 	// I -> [N,P,C]
-	IntegrityImpact string
+	integrityImpact string
 	// A -> [N,P,C]
-	AvailabilityImpact string
+	availabilityImpact string
 }
 
-// Temporal is the group of metrics defined with such name by the
+// temporal is the group of metrics defined with such name by the
 // first.org CVSS v2.0 rev2 specification.
 // Not mandatory.
-type Temporal struct {
+type temporal struct {
 	// E -> [U,POC,F,F,H,ND]
-	Exploitability string
+	exploitability string
 	// RL -> [OF,TF,W,U,ND]
-	RemediationLevel string
+	remediationLevel string
 	// RC -> [UC,UR,C,ND]
-	ReportConfidence string
+	reportConfidence string
 }
 
-// Environmental is the group of metrics defined with such name by the
+// environmental is the group of metrics defined with such name by the
 // first.org CVSS v2.0 rev2 specification.
 // Not mandatory.
-type Environmental struct {
+type environmental struct {
 	// CDP -> [N,L,LM,MH,H,ND]
-	CollateralDamagePotential string
+	collateralDamagePotential string
 	// TD -> [N,L,M,H,ND]
-	TargetDistribution string
+	targetDistribution string
 	// CR,IR,AR -> [L,M,H,ND]
-	ConfidentialityRequirement string
-	IntegrityRequirement       string
-	AvailabilityRequirement    string
+	confidentialityRequirement string
+	integrityRequirement       string
+	availabilityRequirement    string
 }
 
 func (cvss20 CVSS20) Get(abv string) (string, error) {
 	switch abv {
 	case "AV":
-		return cvss20.AccessVector, nil
+		return cvss20.accessVector, nil
 	case "AC":
-		return cvss20.AccessComplexity, nil
+		return cvss20.accessComplexity, nil
 	case "Au":
-		return cvss20.Authentication, nil
+		return cvss20.authentication, nil
 	case "C":
-		return cvss20.ConfidentialityImpact, nil
+		return cvss20.confidentialityImpact, nil
 	case "I":
-		return cvss20.IntegrityImpact, nil
+		return cvss20.integrityImpact, nil
 	case "A":
-		return cvss20.AvailabilityImpact, nil
+		return cvss20.availabilityImpact, nil
 	case "E":
-		return cvss20.Exploitability, nil
+		return cvss20.exploitability, nil
 	case "RL":
-		return cvss20.RemediationLevel, nil
+		return cvss20.remediationLevel, nil
 	case "RC":
-		return cvss20.ReportConfidence, nil
+		return cvss20.reportConfidence, nil
 	case "CDP":
-		return cvss20.CollateralDamagePotential, nil
+		return cvss20.collateralDamagePotential, nil
 	case "TD":
-		return cvss20.TargetDistribution, nil
+		return cvss20.targetDistribution, nil
 	case "CR":
-		return cvss20.ConfidentialityRequirement, nil
+		return cvss20.confidentialityRequirement, nil
 	case "IR":
-		return cvss20.IntegrityRequirement, nil
+		return cvss20.integrityRequirement, nil
 	case "AR":
-		return cvss20.AvailabilityRequirement, nil
+		return cvss20.availabilityRequirement, nil
 	default:
 		return "", &ErrInvalidMetric{Abv: abv}
 	}
 }
 
@@ -179,78 +257,78 @@ func (cvss20 *CVSS20) Set(abv string, value string) error {
 	// Base
 	case "AV":
 		if err := validate(value, []string{"L", "A", "N"}); err != nil {
 			return err
 		}
-		cvss20.AccessVector = value
+		cvss20.accessVector = value
 	case "AC":
 		if err := validate(value, []string{"H", "M", "L"}); err != nil {
 			return err
 		}
-		cvss20.AccessComplexity = value
+		cvss20.accessComplexity = value
 	case "Au":
 		if err := validate(value, []string{"M", "S", "N"}); err != nil {
 			return err
 		}
-		cvss20.Authentication = value
+		cvss20.authentication = value
 	case "C":
 		if err := validate(value, []string{"N", "P", "C"}); err != nil {
 			return err
 		}
-		cvss20.ConfidentialityImpact = value
+		cvss20.confidentialityImpact = value
 	case "I":
 		if err := validate(value, []string{"N", "P", "C"}); err != nil {
 			return err
 		}
-		cvss20.IntegrityImpact = value
+		cvss20.integrityImpact = value
 	case "A":
 		if err := validate(value, []string{"N", "P", "C"}); err != nil {
 			return err
 		}
-		cvss20.AvailabilityImpact = value
+		cvss20.availabilityImpact = value
 	// Temporal
 	case "E":
 		if err := validate(value, []string{"U", "POC", "F", "H", "ND"}); err != nil {
 			return err
 		}
-		cvss20.Exploitability = value
+		cvss20.exploitability = value
 	case "RL":
 		if err := validate(value, []string{"OF", "TF", "W", "U", "ND"}); err != nil {
 			return err
 		}
-		cvss20.RemediationLevel = value
+		cvss20.remediationLevel = value
 	case "RC":
 		if err := validate(value, []string{"UC", "UR", "C", "ND"}); err != nil {
 			return err
 		}
-		cvss20.ReportConfidence = value
+		cvss20.reportConfidence = value
 	// Environmental
 	case "CDP":
 		if err := validate(value, []string{"N", "L", "LM", "MH", "H", "ND"}); err != nil {
 			return err
 		}
-		cvss20.CollateralDamagePotential = value
+		cvss20.collateralDamagePotential = value
 	case "TD":
 		if err := validate(value, []string{"N", "L", "M", "H", "ND"}); err != nil {
 			return err
 		}
-		cvss20.TargetDistribution = value
+		cvss20.targetDistribution = value
 	case "CR":
 		if err := validate(value, []string{"L", "M", "H", "ND"}); err != nil {
 			return err
 		}
-		cvss20.ConfidentialityRequirement = value
+		cvss20.confidentialityRequirement = value
 	case "IR":
 		if err := validate(value, []string{"L", "M", "H", "ND"}); err != nil {
 			return err
 		}
-		cvss20.IntegrityRequirement = value
+		cvss20.integrityRequirement = value
 	case "AR":
 		if err := validate(value, []string{"L", "M", "H", "ND"}); err != nil {
 			return err
 		}
-		cvss20.AvailabilityRequirement = value
+		cvss20.availabilityRequirement = value
 	default:
 		return &ErrInvalidMetric{Abv: abv}
 	}
 	return nil
 }
@@ -265,36 +343,44 @@ func validate(value string, enabled []string) error {
 	return ErrInvalidMetricValue
 }
 
 // BaseScore returns the CVSS v2.0's base score.
 func (cvss20 CVSS20) BaseScore() float64 {
-	impact := 10.41 * (1 - (1-cia(cvss20.ConfidentialityImpact))*(1-cia(cvss20.IntegrityImpact))*(1-cia(cvss20.AvailabilityImpact)))
+	impact := cvss20.Impact()
 	fimpact := 0.0
 	if impact != 0 {
 		fimpact = 1.176
 	}
-	exploitability := 20 * accessVector(cvss20.AccessVector) * accessComplexity(cvss20.AccessComplexity) * authentication(cvss20.Authentication)
+	exploitability := cvss20.Exploitability()
 	return roundTo1Decimal(((0.6 * impact) + (0.4 * exploitability) - 1.5) * fimpact)
 }
 
+func (cvss20 CVSS20) Impact() float64 {
+	return 10.41 * (1 - (1-cia(cvss20.confidentialityImpact))*(1-cia(cvss20.integrityImpact))*(1-cia(cvss20.availabilityImpact)))
+}
+
+func (cvss20 CVSS20) Exploitability() float64 {
+	return 20 * accessVector(cvss20.accessVector) * accessComplexity(cvss20.accessComplexity) * authentication(cvss20.authentication)
+}
+
 // TemporalScore returns the CVSS v2.0's temporal score.
 func (cvss20 CVSS20) TemporalScore() float64 {
-	return roundTo1Decimal(cvss20.BaseScore() * exploitability(cvss20.Exploitability) * remediationLevel(cvss20.RemediationLevel) * reportConfidence(cvss20.ReportConfidence))
+	return roundTo1Decimal(cvss20.BaseScore() * exploitability(cvss20.exploitability) * remediationLevel(cvss20.remediationLevel) * reportConfidence(cvss20.reportConfidence))
 }
 
 // EnvironmentalScore returns the CVSS v2.0's environmental score.
 func (cvss20 CVSS20) EnvironmentalScore() float64 {
 	// Recompute base score
-	adjustedImpact := math.Min(10, 10.41*(1-(1-cia(cvss20.ConfidentialityImpact)*ciar(cvss20.ConfidentialityRequirement))*(1-cia(cvss20.IntegrityImpact)*ciar(cvss20.IntegrityRequirement))*(1-cia(cvss20.AvailabilityImpact)*ciar(cvss20.AvailabilityRequirement))))
+	adjustedImpact := math.Min(10, 10.41*(1-(1-cia(cvss20.confidentialityImpact)*ciar(cvss20.confidentialityRequirement))*(1-cia(cvss20.integrityImpact)*ciar(cvss20.integrityRequirement))*(1-cia(cvss20.availabilityImpact)*ciar(cvss20.availabilityRequirement))))
 	fimpactBase := 0.0
 	if adjustedImpact != 0 {
 		fimpactBase = 1.176
 	}
-	expltBase := 20 * accessVector(cvss20.AccessVector) * accessComplexity(cvss20.AccessComplexity) * authentication(cvss20.Authentication)
+	expltBase := 20 * accessVector(cvss20.accessVector) * accessComplexity(cvss20.accessComplexity) * authentication(cvss20.authentication)
 	recBase := roundTo1Decimal(((0.6 * adjustedImpact) + (0.4 * expltBase) - 1.5) * fimpactBase)
-	adjustedTemporal := roundTo1Decimal(recBase * exploitability(cvss20.Exploitability) * remediationLevel(cvss20.RemediationLevel) * reportConfidence(cvss20.ReportConfidence))
-	return roundTo1Decimal((adjustedTemporal + (10-adjustedTemporal)*collateralDamagePotential(cvss20.CollateralDamagePotential)) * targetDistribution(cvss20.TargetDistribution))
+	adjustedTemporal := roundTo1Decimal(recBase * exploitability(cvss20.exploitability) * remediationLevel(cvss20.remediationLevel) * reportConfidence(cvss20.reportConfidence))
+	return roundTo1Decimal((adjustedTemporal + (10-adjustedTemporal)*collateralDamagePotential(cvss20.collateralDamagePotential)) * targetDistribution(cvss20.targetDistribution))
 }
 
 // Helpers to compute CVSS v2.0 scores.
 
 func accessVector(v string) float64 {
diff --git a/20/cvss20_bench_test.go b/20/cvss20_bench_test.go
new file mode 100644
index 0000000..0b344fd
--- /dev/null
+++ b/20/cvss20_bench_test.go
@@ -0,0 +1,100 @@
+package gocvss20_test
+
+import (
+	"testing"
+
+	gocvss20 "github.com/pandatix/go-cvss/20"
+)
+
+var Gcvss20 *gocvss20.CVSS20
+var Gerr error
+
+func BenchmarkParseVector_Base(b *testing.B) {
+	benchmarkParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C", b)
+}
+
+func BenchmarkParseVector_WithTempAndEnv(b *testing.B) {
+	benchmarkParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M", b)
+}
+
+func benchmarkParseVector(vector string, b *testing.B) {
+	var cvss20 *gocvss20.CVSS20
+	var err error
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		cvss20, err = gocvss20.ParseVector(vector)
+	}
+	Gcvss20 = cvss20
+	Gerr = err
+}
+
+var Gstr string
+
+func BenchmarkCVSS20Vector(b *testing.B) {
+	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
+	var str string
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		str = cvss20.Vector()
+	}
+	Gstr = str
+}
+
+var Gget string
+
+func BenchmarkCVSS20Get(b *testing.B) {
+	const abv = "Au"
+	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
+	var get string
+	var err error
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		get, err = cvss20.Get(abv)
+	}
+	Gget = get
+	Gerr = err
+}
+
+func BenchmarkCVSS20Set(b *testing.B) {
+	const abv = "Au"
+	const value = "S"
+	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
+	var err error
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		err = cvss20.Set(abv, value)
+	}
+	Gerr = err
+}
+
+var Gscore float64
+
+func BenchmarkCVSS20BaseScore(b *testing.B) {
+	var score float64
+	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		score = cvss20.BaseScore()
+	}
+	Gscore = score
+}
+
+func BenchmarkCVSS20TemporalScore(b *testing.B) {
+	var score float64
+	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		score = cvss20.TemporalScore()
+	}
+	Gscore = score
+}
+
+func BenchmarkCVSS20EnvironmentalScore(b *testing.B) {
+	var score float64
+	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		score = cvss20.EnvironmentalScore()
+	}
+	Gscore = score
+}
diff --git a/20/cvss20_fuzz_test.go b/20/cvss20_fuzz_test.go
index d665bb2..e3601f8 100644
--- a/20/cvss20_fuzz_test.go
+++ b/20/cvss20_fuzz_test.go
@@ -1,20 +1,18 @@
-package gocvss20_test
+package gocvss20
 
 import (
 	"testing"
-
-	gocvss20 "github.com/pandatix/go-cvss/20"
 )
 
 func FuzzParseVector(f *testing.F) {
 	for _, tt := range testsParseVector {
 		f.Add(tt.Vector)
 	}
 
 	f.Fuzz(func(t *testing.T, vector string) {
-		cvss20, err := gocvss20.ParseVector(vector)
+		cvss20, err := ParseVector(vector)
 
 		if err != nil {
 			if cvss20 != nil {
 				t.Fatal("not supposed to get a CVSS20 when an error is returned")
 			}
diff --git a/20/cvss20_test.go b/20/cvss20_test.go
index bf6a3d2..5ef6065 100644
--- a/20/cvss20_test.go
+++ b/20/cvss20_test.go
@@ -1,107 +1,140 @@
-package gocvss20_test
+package gocvss20
 
 import (
 	"testing"
 
-	gocvss20 "github.com/pandatix/go-cvss/20"
 	"github.com/stretchr/testify/assert"
 )
 
 var testsParseVector = map[string]struct {
 	Vector         string
-	ExpectedCVSS20 *gocvss20.CVSS20
+	ExpectedCVSS20 *CVSS20
 	ExpectedErr    error
 }{
 	"CVSS v2.0 Guide Section 3.3.1 CVE-2002-0392": {
 		Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:C/E:F/RL:OF/RC:C",
-		ExpectedCVSS20: &gocvss20.CVSS20{
-			Base: gocvss20.Base{
-				AccessVector:          "N",
-				AccessComplexity:      "L",
-				Authentication:        "N",
-				ConfidentialityImpact: "N",
-				IntegrityImpact:       "N",
-				AvailabilityImpact:    "C",
+		ExpectedCVSS20: &CVSS20{
+			base: base{
+				accessVector:          "N",
+				accessComplexity:      "L",
+				authentication:        "N",
+				confidentialityImpact: "N",
+				integrityImpact:       "N",
+				availabilityImpact:    "C",
 			},
-			Temporal: gocvss20.Temporal{
-				Exploitability:   "F",
-				RemediationLevel: "OF",
-				ReportConfidence: "C",
+			temporal: temporal{
+				exploitability:   "F",
+				remediationLevel: "OF",
+				reportConfidence: "C",
 			},
-			Environmental: gocvss20.Environmental{
-				CollateralDamagePotential:  "ND",
-				TargetDistribution:         "ND",
-				ConfidentialityRequirement: "ND",
-				IntegrityRequirement:       "ND",
-				AvailabilityRequirement:    "ND",
+			environmental: environmental{
+				collateralDamagePotential:  "ND",
+				targetDistribution:         "ND",
+				confidentialityRequirement: "ND",
+				integrityRequirement:       "ND",
+				availabilityRequirement:    "ND",
 			},
 		},
 		ExpectedErr: nil,
 	},
 	"CVSS v2.0 Guide Section 3.3.2 CVE-2003-0818": {
 		Vector: "AV:N/AC:L/Au:N/C:C/I:C/A:C/E:F/RL:OF/RC:C",
-		ExpectedCVSS20: &gocvss20.CVSS20{
-			Base: gocvss20.Base{
-				AccessVector:          "N",
-				AccessComplexity:      "L",
-				Authentication:        "N",
-				ConfidentialityImpact: "C",
-				IntegrityImpact:       "C",
-				AvailabilityImpact:    "C",
+		ExpectedCVSS20: &CVSS20{
+			base: base{
+				accessVector:          "N",
+				accessComplexity:      "L",
+				authentication:        "N",
+				confidentialityImpact: "C",
+				integrityImpact:       "C",
+				availabilityImpact:    "C",
 			},
-			Temporal: gocvss20.Temporal{
-				Exploitability:   "F",
-				RemediationLevel: "OF",
-				ReportConfidence: "C",
+			temporal: temporal{
+				exploitability:   "F",
+				remediationLevel: "OF",
+				reportConfidence: "C",
 			},
-			Environmental: gocvss20.Environmental{
-				CollateralDamagePotential:  "ND",
-				TargetDistribution:         "ND",
-				ConfidentialityRequirement: "ND",
-				IntegrityRequirement:       "ND",
-				AvailabilityRequirement:    "ND",
+			environmental: environmental{
+				collateralDamagePotential:  "ND",
+				targetDistribution:         "ND",
+				confidentialityRequirement: "ND",
+				integrityRequirement:       "ND",
+				availabilityRequirement:    "ND",
 			},
 		},
 		ExpectedErr: nil,
 	},
 	"CVSS v2.0 Guide Section 3.3.3 CVE-2003-0062": {
 		Vector: "AV:L/AC:H/Au:N/C:C/I:C/A:C/E:POC/RL:OF/RC:C",
-		ExpectedCVSS20: &gocvss20.CVSS20{
-			Base: gocvss20.Base{
-				AccessVector:          "L",
-				AccessComplexity:      "H",
-				Authentication:        "N",
-				ConfidentialityImpact: "C",
-				IntegrityImpact:       "C",
-				AvailabilityImpact:    "C",
+		ExpectedCVSS20: &CVSS20{
+			base: base{
+				accessVector:          "L",
+				accessComplexity:      "H",
+				authentication:        "N",
+				confidentialityImpact: "C",
+				integrityImpact:       "C",
+				availabilityImpact:    "C",
 			},
-			Temporal: gocvss20.Temporal{
-				Exploitability:   "POC",
-				RemediationLevel: "OF",
-				ReportConfidence: "C",
+			temporal: temporal{
+				exploitability:   "POC",
+				remediationLevel: "OF",
+				reportConfidence: "C",
 			},
-			Environmental: gocvss20.Environmental{
-				CollateralDamagePotential:  "ND",
-				TargetDistribution:         "ND",
-				ConfidentialityRequirement: "ND",
-				IntegrityRequirement:       "ND",
-				AvailabilityRequirement:    "ND",
+			environmental: environmental{
+				collateralDamagePotential:  "ND",
+				targetDistribution:         "ND",
+				confidentialityRequirement: "ND",
+				integrityRequirement:       "ND",
+				availabilityRequirement:    "ND",
 			},
 		},
 		ExpectedErr: nil,
 	},
+	"all-defined": {
+		Vector: "AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M",
+		ExpectedCVSS20: &CVSS20{
+			base: base{
+				accessVector:          "N",
+				accessComplexity:      "L",
+				authentication:        "N",
+				confidentialityImpact: "P",
+				integrityImpact:       "P",
+				availabilityImpact:    "C",
+			},
+			temporal: temporal{
+				exploitability:   "U",
+				remediationLevel: "OF",
+				reportConfidence: "C",
+			},
+			environmental: environmental{
+				collateralDamagePotential:  "MH",
+				targetDistribution:         "H",
+				confidentialityRequirement: "M",
+				integrityRequirement:       "M",
+				availabilityRequirement:    "M",
+			},
+		},
+		ExpectedErr: nil,
+	},
+	"Fuzz_50620a37c4a7716a77a14602b4bcc7b02e6f751d0a714ed796d9b04402c745ac": {
+		// This fuzz crasher enabled detecting that the split function
+		// (comming from the optimization step) was doing an Out-Of-Bounds
+		// Write (CWE-787) if the vector was only composed of '/'.
+		Vector:         "//////////////",
+		ExpectedCVSS20: nil,
+		ExpectedErr:    ErrInvalidMetricOrder,
+	},
 }
 
 func TestParseVector(t *testing.T) {
 	t.Parallel()
 
 	for testname, tt := range testsParseVector {
 		t.Run(testname, func(t *testing.T) {
 			assert := assert.New(t)
 
-			cvss20, err := gocvss20.ParseVector(tt.Vector)
+			cvss20, err := ParseVector(tt.Vector)
 
 			assert.Equal(tt.ExpectedCVSS20, cvss20)
 			assert.Equal(tt.ExpectedErr, err)
 		})
 	}
@@ -109,90 +142,90 @@ func TestParseVector(t *testing.T) {
 
 func TestScores(t *testing.T) {
 	t.Parallel()
 
 	var tests = map[string]struct {
-		CVSS20                     *gocvss20.CVSS20
+		CVSS20                     *CVSS20
 		ExpectedBaseScore          float64
 		ExpectedTemporalScore      float64
 		ExpectedEnvironmentalScore float64
 	}{
 		"CVSS v2.0 Guide Section 3.3.1 CVE-2002-0392": {
-			CVSS20: &gocvss20.CVSS20{
-				Base: gocvss20.Base{
-					AccessVector:          "N",
-					AccessComplexity:      "L",
-					Authentication:        "N",
-					ConfidentialityImpact: "N",
-					IntegrityImpact:       "N",
-					AvailabilityImpact:    "C",
+			CVSS20: &CVSS20{
+				base: base{
+					accessVector:          "N",
+					accessComplexity:      "L",
+					authentication:        "N",
+					confidentialityImpact: "N",
+					integrityImpact:       "N",
+					availabilityImpact:    "C",
 				},
-				Temporal: gocvss20.Temporal{
-					Exploitability:   "F",
-					RemediationLevel: "OF",
-					ReportConfidence: "C",
+				temporal: temporal{
+					exploitability:   "F",
+					remediationLevel: "OF",
+					reportConfidence: "C",
 				},
-				Environmental: gocvss20.Environmental{
-					CollateralDamagePotential:  "ND",
-					TargetDistribution:         "ND",
-					ConfidentialityRequirement: "ND",
-					IntegrityRequirement:       "ND",
-					AvailabilityRequirement:    "ND",
+				environmental: environmental{
+					collateralDamagePotential:  "ND",
+					targetDistribution:         "ND",
+					confidentialityRequirement: "ND",
+					integrityRequirement:       "ND",
+					availabilityRequirement:    "ND",
 				},
 			},
 			ExpectedBaseScore:          7.8,
 			ExpectedTemporalScore:      6.4,
 			ExpectedEnvironmentalScore: 6.4,
 		},
 		"CVSS v2.0 Guide Section 3.3.2 CVE-2003-0818": {
-			CVSS20: &gocvss20.CVSS20{
-				Base: gocvss20.Base{
-					AccessVector:          "N",
-					AccessComplexity:      "L",
-					Authentication:        "N",
-					ConfidentialityImpact: "C",
-					IntegrityImpact:       "C",
-					AvailabilityImpact:    "C",
+			CVSS20: &CVSS20{
+				base: base{
+					accessVector:          "N",
+					accessComplexity:      "L",
+					authentication:        "N",
+					confidentialityImpact: "C",
+					integrityImpact:       "C",
+					availabilityImpact:    "C",
 				},
-				Temporal: gocvss20.Temporal{
-					Exploitability:   "F",
-					RemediationLevel: "OF",
-					ReportConfidence: "C",
+				temporal: temporal{
+					exploitability:   "F",
+					remediationLevel: "OF",
+					reportConfidence: "C",
 				},
-				Environmental: gocvss20.Environmental{
-					CollateralDamagePotential:  "ND",
-					TargetDistribution:         "ND",
-					ConfidentialityRequirement: "ND",
-					IntegrityRequirement:       "ND",
-					AvailabilityRequirement:    "ND",
+				environmental: environmental{
+					collateralDamagePotential:  "ND",
+					targetDistribution:         "ND",
+					confidentialityRequirement: "ND",
+					integrityRequirement:       "ND",
+					availabilityRequirement:    "ND",
 				},
 			},
 			ExpectedBaseScore:          10.0,
 			ExpectedTemporalScore:      8.3,
 			ExpectedEnvironmentalScore: 8.3,
 		},
 		"CVSS v2.0 Guide Section 3.3.3 CVE-2003-0062": {
-			CVSS20: &gocvss20.CVSS20{
-				Base: gocvss20.Base{
-					AccessVector:          "L",
-					AccessComplexity:      "H",
-					Authentication:        "N",
-					ConfidentialityImpact: "C",
-					IntegrityImpact:       "C",
-					AvailabilityImpact:    "C",
+			CVSS20: &CVSS20{
+				base: base{
+					accessVector:          "L",
+					accessComplexity:      "H",
+					authentication:        "N",
+					confidentialityImpact: "C",
+					integrityImpact:       "C",
+					availabilityImpact:    "C",
 				},
-				Temporal: gocvss20.Temporal{
-					Exploitability:   "POC",
-					RemediationLevel: "OF",
-					ReportConfidence: "C",
+				temporal: temporal{
+					exploitability:   "POC",
+					remediationLevel: "OF",
+					reportConfidence: "C",
 				},
-				Environmental: gocvss20.Environmental{
-					CollateralDamagePotential:  "ND",
-					TargetDistribution:         "ND",
-					ConfidentialityRequirement: "ND",
-					IntegrityRequirement:       "ND",
-					AvailabilityRequirement:    "ND",
+				environmental: environmental{
+					collateralDamagePotential:  "ND",
+					targetDistribution:         "ND",
+					confidentialityRequirement: "ND",
+					integrityRequirement:       "ND",
+					availabilityRequirement:    "ND",
 				},
 			},
 			ExpectedBaseScore:          6.2,
 			ExpectedTemporalScore:      4.9,
 			ExpectedEnvironmentalScore: 4.9,
diff --git a/20/errors.go b/20/errors.go
index 94e778c..f63819c 100644
--- a/20/errors.go
+++ b/20/errors.go
@@ -9,30 +9,18 @@ var (
 	ErrTooShortVector     = errors.New("too short vector")
 	ErrInvalidMetricOrder = errors.New("invalid metric order")
 	ErrInvalidMetricValue = errors.New("invalid metric value")
 )
 
-// ErrBaseScore is an error returned by ParseVector when the
-// given vector have missing base score attributes.
-type ErrBaseScore struct {
-	Missings []string
-}
-
-func (err ErrBaseScore) Error() string {
-	return fmt.Sprintf("base score is missing metrics %v", err.Missings)
-}
-
-var _ error = (*ErrBaseScore)(nil)
-
 // ErrDefinedN is an error return by ParseVector when the
 // given vector has metrics abbreviations defined multiple times.
 type ErrDefinedN struct {
-	Abv []string
+	Abv string
 }
 
 func (err ErrDefinedN) Error() string {
-	return fmt.Sprintf("given CVSS v3.1 vector has %v metric abbreviations defined multiple times", err.Abv)
+	return fmt.Sprintf("given CVSS v3.1 vector has %s metric abbreviation defined after vector end", err.Abv)
 }
 
 var _ error = (*ErrDefinedN)(nil)
 
 // ErrInvalidMetric is an error returned when a given
diff --git a/README.md b/README.md
index 0bcb620..24f12cc 100644
--- a/README.md
+++ b/README.md
@@ -72,42 +72,57 @@ This reduce drastically the pressure on the Garbage Collector using this Go modu
 The following shows the performances results.
 We challenge any other Go implementation to do better :stuck_out_tongue_winking_eye:
 
 ### CVSS v2.0
 
+```
+goos: linux
+goarch: amd64
+pkg: github.com/pandatix/go-cvss/20
+cpu: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
+BenchmarkParseVector_Base-4             	 2089275	       572.9 ns/op	     224 B/op	       1 allocs/op
+BenchmarkParseVector_WithTempAndEnv-4   	 1000000	        1118 ns/op	     224 B/op	       1 allocs/op
+BenchmarkCVSS20Vector-4                 	 6806152	       176.3 ns/op	      80 B/op	       1 allocs/op
+BenchmarkCVSS20Get-4                    	46162280	       26.50 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS20Set-4                    	42365036	       27.50 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS20BaseScore-4              	20117143	       57.68 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS20TemporalScore-4          	14383033	       83.66 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS20EnvironmentalScore-4     	15307656	       79.48 ns/op	       0 B/op	       0 allocs/op
+```
+
 ### CVSS v3.0
 
 ```
 goos: linux
 goarch: amd64
 pkg: github.com/pandatix/go-cvss/30
 cpu: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
-BenchmarkParseVector_Base-4                      1443836               808.4 ns/op           352 B/op          1 allocs/op
-BenchmarkParseVector_WithTempAndEnv-4             701901              1711 ns/op             352 B/op          1 allocs/op
-BenchmarkCVSS30Vector-4                          5593758               215.8 ns/op            96 B/op          1 allocs/op
-BenchmarkCVSS30Get-4                            27306528                41.66 ns/op            0 B/op          0 allocs/op
-BenchmarkCVSS30Set-4                            31862641                37.94 ns/op            0 B/op          0 allocs/op
-BenchmarkCVSS30BaseScore-4                       7769804               139.2 ns/op             0 B/op          0 allocs/op
-BenchmarkCVSS30TemporalScore-4                   5814230               189.1 ns/op             0 B/op          0 allocs/op
-BenchmarkCVSS30EnvironmentalScore-4              6402489               188.7 ns/op             0 B/op          0 allocs/op
+BenchmarkParseVector_Base-4             	 1458514	       843.4 ns/op	     352 B/op	       1 allocs/op
+BenchmarkParseVector_WithTempAndEnv-4   	  703789	        2067 ns/op	     352 B/op	       1 allocs/op
+BenchmarkCVSS30Vector-4                 	 4587404	       237.0 ns/op	      96 B/op	       1 allocs/op
+BenchmarkCVSS30Get-4                    	26877397	       51.38 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS30Set-4                    	32284153	       38.53 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS30BaseScore-4              	 8275440	       145.4 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS30TemporalScore-4          	 6054021	       195.7 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS30EnvironmentalScore-4     	 6230708	       191.2 ns/op	       0 B/op	       0 allocs/op
 ```
 
 ### CVSS v3.1
 
 ```
 goos: linux
 goarch: amd64
 pkg: github.com/pandatix/go-cvss/31
 cpu: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
-BenchmarkParseVector_Base-4             	 1312525	       895.0 ns/op	     352 B/op	       1 allocs/op
-BenchmarkParseVector_WithTempAndEnv-4   	  685629	        2232 ns/op	     352 B/op	       1 allocs/op
-BenchmarkCVSS31Vector-4                 	 4867528	       223.2 ns/op	      96 B/op	       1 allocs/op
-BenchmarkCVSS31Get-4                    	31498058	       36.37 ns/op	       0 B/op	       0 allocs/op
-BenchmarkCVSS31Set-4                    	30187612	       38.73 ns/op	       0 B/op	       0 allocs/op
-BenchmarkCVSS31BaseScore-4              	11144173	       101.2 ns/op	       0 B/op	       0 allocs/op
-BenchmarkCVSS31TemporalScore-4          	 7856455	       154.4 ns/op	       0 B/op	       0 allocs/op
-BenchmarkCVSS31EnvironmentalScore-4     	 6310815	       169.4 ns/op	       0 B/op	       0 allocs/op
+BenchmarkParseVector_Base-4             	 1445559	       825.3 ns/op	     352 B/op	       1 allocs/op
+BenchmarkParseVector_WithTempAndEnv-4   	  658578	        1836 ns/op	     352 B/op	       1 allocs/op
+BenchmarkCVSS31Vector-4                 	 5087984	       244.1 ns/op	      96 B/op	       1 allocs/op
+BenchmarkCVSS31Get-4                    	28350058	       41.40 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS31Set-4                    	30340425	       40.16 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS31BaseScore-4              	 8535666	       139.3 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS31TemporalScore-4          	 6004561	       189.7 ns/op	       0 B/op	       0 allocs/op
+BenchmarkCVSS31EnvironmentalScore-4     	 5937879	       184.5 ns/op	       0 B/op	       0 allocs/op
 ```
 
 ## Feedbacks
 
 ### CVSS v2.0

Vulnerable code: 	pts := strings.Split(vector, "/")
	if len(pts) != 6 && len(pts) != 9 && len(pts) != 14 {
		Base: Base{},
		Temporal: Temporal{
			Exploitability:   "ND",
			RemediationLevel: "ND",
			ReportConfidence: "ND",
		Environmental: Environmental{
			CollateralDamagePotential:  "ND",
			TargetDistribution:         "ND",
			ConfidentialityRequirement: "ND",
			IntegrityRequirement:       "ND",
			AvailabilityRequirement:    "ND",
	// Parse metrics in order
	slcs := [][]string{
		{"AV", "AC", "Au", "C", "I", "A"}, // Base metrics
		{"E", "RL", "RC"},                 // Temporal metrics
		{"CDP", "TD", "CR", "IR", "AR"},   // Environmental metrics
	}
	currSlc := slcs[slci]
		if abv != currSlc[i] {
		if i == len(currSlc) {
			currSlc = slcs[slci]
	s := ""
	s += "AV:" + cvss20.AccessVector
	s += "/AC:" + cvss20.AccessComplexity
	s += "/Au:" + cvss20.Authentication
	s += "/C:" + cvss20.ConfidentialityImpact
	s += "/I:" + cvss20.IntegrityImpact
	s += "/A:" + cvss20.AvailabilityImpact
	// Temporal, if any is defined
	if cvss20.Exploitability != "ND" || cvss20.RemediationLevel != "ND" || cvss20.ReportConfidence != "ND" {
		s += "/E:" + cvss20.Exploitability
		s += "/RL:" + cvss20.RemediationLevel
		s += "/RC:" + cvss20.ReportConfidence
	// Environmental, if any is defined
	if cvss20.CollateralDamagePotential != "ND" || cvss20.TargetDistribution != "ND" || cvss20.ConfidentialityRequirement != "ND" || cvss20.IntegrityRequirement != "ND" || cvss20.AvailabilityRequirement != "ND" {
		s += "/CDP:" + cvss20.CollateralDamagePotential
		s += "/TD:" + cvss20.TargetDistribution
		s += "/CR:" + cvss20.ConfidentialityRequirement
		s += "/IR:" + cvss20.IntegrityRequirement
		s += "/AR:" + cvss20.AvailabilityRequirement
	return s
	Base
	Temporal
	Environmental
// Base is the group of metrics defined with such name by the
type Base struct {
	AccessVector string
	AccessComplexity string
	Authentication string
	ConfidentialityImpact string
	IntegrityImpact string
	AvailabilityImpact string
// Temporal is the group of metrics defined with such name by the
type Temporal struct {
	Exploitability string
	RemediationLevel string
	ReportConfidence string
// Environmental is the group of metrics defined with such name by the
type Environmental struct {
	CollateralDamagePotential string
	TargetDistribution string
	ConfidentialityRequirement string
	IntegrityRequirement       string
	AvailabilityRequirement    string
		return cvss20.AccessVector, nil
		return cvss20.AccessComplexity, nil
		return cvss20.Authentication, nil
		return cvss20.ConfidentialityImpact, nil
		return cvss20.IntegrityImpact, nil
		return cvss20.AvailabilityImpact, nil
		return cvss20.Exploitability, nil
		return cvss20.RemediationLevel, nil
		return cvss20.ReportConfidence, nil
		return cvss20.CollateralDamagePotential, nil
		return cvss20.TargetDistribution, nil
		return cvss20.ConfidentialityRequirement, nil
		return cvss20.IntegrityRequirement, nil
		return cvss20.AvailabilityRequirement, nil
		cvss20.AccessVector = value
		cvss20.AccessComplexity = value
		cvss20.Authentication = value
		cvss20.ConfidentialityImpact = value
		cvss20.IntegrityImpact = value
		cvss20.AvailabilityImpact = value
		cvss20.Exploitability = value
		cvss20.RemediationLevel = value
		cvss20.ReportConfidence = value
		cvss20.CollateralDamagePotential = value
		cvss20.TargetDistribution = value
		cvss20.ConfidentialityRequirement = value
		cvss20.IntegrityRequirement = value
		cvss20.AvailabilityRequirement = value
	impact := 10.41 * (1 - (1-cia(cvss20.ConfidentialityImpact))*(1-cia(cvss20.IntegrityImpact))*(1-cia(cvss20.AvailabilityImpact)))
	exploitability := 20 * accessVector(cvss20.AccessVector) * accessComplexity(cvss20.AccessComplexity) * authentication(cvss20.Authentication)
	return roundTo1Decimal(cvss20.BaseScore() * exploitability(cvss20.Exploitability) * remediationLevel(cvss20.RemediationLevel) * reportConfidence(cvss20.ReportConfidence))
	adjustedImpact := math.Min(10, 10.41*(1-(1-cia(cvss20.ConfidentialityImpact)*ciar(cvss20.ConfidentialityRequirement))*(1-cia(cvss20.IntegrityImpact)*ciar(cvss20.IntegrityRequirement))*(1-cia(cvss20.AvailabilityImpact)*ciar(cvss20.AvailabilityRequirement))))
	expltBase := 20 * accessVector(cvss20.AccessVector) * accessComplexity(cvss20.AccessComplexity) * authentication(cvss20.Authentication)
	adjustedTemporal := roundTo1Decimal(recBase * exploitability(cvss20.Exploitability) * remediationLevel(cvss20.RemediationLevel) * reportConfidence(cvss20.ReportConfidence))
	return roundTo1Decimal((adjustedTemporal + (10-adjustedTemporal)*collateralDamagePotential(cvss20.CollateralDamagePotential)) * targetDistribution(cvss20.TargetDistribution))
package gocvss20_test

	gocvss20 "github.com/pandatix/go-cvss/20"
		cvss20, err := gocvss20.ParseVector(vector)
package gocvss20_test
	gocvss20 "github.com/pandatix/go-cvss/20"
	ExpectedCVSS20 *gocvss20.CVSS20
		ExpectedCVSS20: &gocvss20.CVSS20{
			Base: gocvss20.Base{
				AccessVector:          "N",
				AccessComplexity:      "L",
				Authentication:        "N",
				ConfidentialityImpact: "N",
				IntegrityImpact:       "N",
				AvailabilityImpact:    "C",
			Temporal: gocvss20.Temporal{
				Exploitability:   "F",
				RemediationLevel: "OF",
				ReportConfidence: "C",
			Environmental: gocvss20.Environmental{
				CollateralDamagePotential:  "ND",
				TargetDistribution:         "ND",
				ConfidentialityRequirement: "ND",
				IntegrityRequirement:       "ND",
				AvailabilityRequirement:    "ND",
		ExpectedCVSS20: &gocvss20.CVSS20{
			Base: gocvss20.Base{
				AccessVector:          "N",
				AccessComplexity:      "L",
				Authentication:        "N",
				ConfidentialityImpact: "C",
				IntegrityImpact:       "C",
				AvailabilityImpact:    "C",
			Temporal: gocvss20.Temporal{
				Exploitability:   "F",
				RemediationLevel: "OF",
				ReportConfidence: "C",
			Environmental: gocvss20.Environmental{
				CollateralDamagePotential:  "ND",
				TargetDistribution:         "ND",
				ConfidentialityRequirement: "ND",
				IntegrityRequirement:       "ND",
				AvailabilityRequirement:    "ND",
		ExpectedCVSS20: &gocvss20.CVSS20{
			Base: gocvss20.Base{
				AccessVector:          "L",
				AccessComplexity:      "H",
				Authentication:        "N",
				ConfidentialityImpact: "C",
				IntegrityImpact:       "C",
				AvailabilityImpact:    "C",
			Temporal: gocvss20.Temporal{
				Exploitability:   "POC",
				RemediationLevel: "OF",
				ReportConfidence: "C",
			Environmental: gocvss20.Environmental{
				CollateralDamagePotential:  "ND",
				TargetDistribution:         "ND",
				ConfidentialityRequirement: "ND",
				IntegrityRequirement:       "ND",
				AvailabilityRequirement:    "ND",
			cvss20, err := gocvss20.ParseVector(tt.Vector)
		CVSS20                     *gocvss20.CVSS20
			CVSS20: &gocvss20.CVSS20{
				Base: gocvss20.Base{
					AccessVector:          "N",
					AccessComplexity:      "L",
					Authentication:        "N",
					ConfidentialityImpact: "N",
					IntegrityImpact:       "N",
					AvailabilityImpact:    "C",
				Temporal: gocvss20.Temporal{
					Exploitability:   "F",
					RemediationLevel: "OF",
					ReportConfidence: "C",
				Environmental: gocvss20.Environmental{
					CollateralDamagePotential:  "ND",
					TargetDistribution:         "ND",
					ConfidentialityRequirement: "ND",
					IntegrityRequirement:       "ND",
					AvailabilityRequirement:    "ND",
			CVSS20: &gocvss20.CVSS20{
				Base: gocvss20.Base{
					AccessVector:          "N",
					AccessComplexity:      "L",
					Authentication:        "N",
					ConfidentialityImpact: "C",
					IntegrityImpact:       "C",
					AvailabilityImpact:    "C",
				Temporal: gocvss20.Temporal{
					Exploitability:   "F",
					RemediationLevel: "OF",
					ReportConfidence: "C",
				Environmental: gocvss20.Environmental{
					CollateralDamagePotential:  "ND",
					TargetDistribution:         "ND",
					ConfidentialityRequirement: "ND",
					IntegrityRequirement:       "ND",
					AvailabilityRequirement:    "ND",
			CVSS20: &gocvss20.CVSS20{
				Base: gocvss20.Base{
					AccessVector:          "L",
					AccessComplexity:      "H",
					Authentication:        "N",
					ConfidentialityImpact: "C",
					IntegrityImpact:       "C",
					AvailabilityImpact:    "C",
				Temporal: gocvss20.Temporal{
					Exploitability:   "POC",
					RemediationLevel: "OF",
					ReportConfidence: "C",
				Environmental: gocvss20.Environmental{
					CollateralDamagePotential:  "ND",
					TargetDistribution:         "ND",
					ConfidentialityRequirement: "ND",
					IntegrityRequirement:       "ND",
					AvailabilityRequirement:    "ND",
// ErrBaseScore is an error returned by ParseVector when the
// given vector have missing base score attributes.
type ErrBaseScore struct {
	Missings []string
}

func (err ErrBaseScore) Error() string {
	return fmt.Sprintf("base score is missing metrics %v", err.Missings)
}

var _ error = (*ErrBaseScore)(nil)

	Abv []string
	return fmt.Sprintf("given CVSS v3.1 vector has %v metric abbreviations defined multiple times", err.Abv)
BenchmarkParseVector_Base-4                      1443836               808.4 ns/op           352 B/op          1 allocs/op
BenchmarkParseVector_WithTempAndEnv-4             701901              1711 ns/op             352 B/op          1 allocs/op
BenchmarkCVSS30Vector-4                          5593758               215.8 ns/op            96 B/op          1 allocs/op
BenchmarkCVSS30Get-4                            27306528                41.66 ns/op            0 B/op          0 allocs/op
BenchmarkCVSS30Set-4                            31862641                37.94 ns/op            0 B/op          0 allocs/op
BenchmarkCVSS30BaseScore-4                       7769804               139.2 ns/op             0 B/op          0 allocs/op
BenchmarkCVSS30TemporalScore-4                   5814230               189.1 ns/op             0 B/op          0 allocs/op
BenchmarkCVSS30EnvironmentalScore-4              6402489               188.7 ns/op             0 B/op          0 allocs/op
BenchmarkParseVector_Base-4             	 1312525	       895.0 ns/op	     352 B/op	       1 allocs/op
BenchmarkParseVector_WithTempAndEnv-4   	  685629	        2232 ns/op	     352 B/op	       1 allocs/op
BenchmarkCVSS31Vector-4                 	 4867528	       223.2 ns/op	      96 B/op	       1 allocs/op
BenchmarkCVSS31Get-4                    	31498058	       36.37 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31Set-4                    	30187612	       38.73 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31BaseScore-4              	11144173	       101.2 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31TemporalScore-4          	 7856455	       154.4 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31EnvironmentalScore-4     	 6310815	       169.4 ns/op	       0 B/op	       0 allocs/op
Fixed code: 	"sync"
	"unsafe"
var order = [][]string{
	{"AV", "AC", "Au", "C", "I", "A"}, // Base metrics
	{"E", "RL", "RC"},                 // Temporal metrics
	{"CDP", "TD", "CR", "IR", "AR"},   // Environmental metrics
}

	pts, l := split(vector)
	if l != 6 && l != 9 && l != 14 {
	pts = pts[:l]
		base: base{},
		temporal: temporal{
			exploitability:   "ND",
			remediationLevel: "ND",
			reportConfidence: "ND",
		environmental: environmental{
			collateralDamagePotential:  "ND",
			targetDistribution:         "ND",
			confidentialityRequirement: "ND",
			integrityRequirement:       "ND",
			availabilityRequirement:    "ND",
		if slci == 4 {
			return nil, &ErrDefinedN{Abv: abv}
		}
		if abv != order[slci][i] {


		if i == len(order[slci]) {
var splitPool = sync.Pool{
	New: func() any {
		return make([]string, 14)
	},
}

func split(vector string) ([]string, int) {
	partsPtr := splitPool.Get()
	defer splitPool.Put(partsPtr)
	parts := partsPtr.([]string)

	start := 0
	curr := 0
	l := len(vector)
	i := 0
	for ; i < l; i++ {
		if vector[i] == '/' {
			parts[curr] = vector[start:i]

			start = i + 1
			curr++

			if curr == 13 {
				break
			}
		}
	}
	parts[curr] = vector[start:]
	return parts, curr + 1
}

	l := lenVec(&cvss20)
	b := make([]byte, 0, l)

	app(&b, "AV:", cvss20.accessVector)
	app(&b, "/AC:", cvss20.accessComplexity)
	app(&b, "/Au:", cvss20.authentication)
	app(&b, "/C:", cvss20.confidentialityImpact)
	app(&b, "/I:", cvss20.integrityImpact)
	app(&b, "/A:", cvss20.availabilityImpact)

	// Temporal
	if cvss20.exploitability != "ND" || cvss20.remediationLevel != "ND" || cvss20.reportConfidence != "ND" {
		app(&b, "/E:", cvss20.exploitability)
		app(&b, "/RL:", cvss20.remediationLevel)
		app(&b, "/RC:", cvss20.reportConfidence)

	// Environmental
	if cvss20.collateralDamagePotential != "ND" || cvss20.targetDistribution != "ND" || cvss20.confidentialityRequirement != "ND" || cvss20.integrityRequirement != "ND" || cvss20.availabilityRequirement != "ND" {
		app(&b, "/CDP:", cvss20.collateralDamagePotential)
		app(&b, "/TD:", cvss20.targetDistribution)
		app(&b, "/CR:", cvss20.confidentialityRequirement)
		app(&b, "/IR:", cvss20.integrityRequirement)
		app(&b, "/AR:", cvss20.availabilityRequirement)

	return *(*string)(unsafe.Pointer(&b))
}

func lenVec(cvss20 *CVSS20) int {
	// Base:
	// - AV, AC, Au: 4
	// - C, I, A: 3
	// - separators: 5
	// Total: 3*4 + 3*3 + 5 = 30
	l := 26

	// Temporal:
	// - E: 2 + len(v)
	// - RL: 3 + len(v)
	// - RC: 3 + len(v)
	// - separators: 3
	// Total: 11 + 3*len(v)
	if cvss20.exploitability != "ND" || cvss20.remediationLevel != "ND" || cvss20.reportConfidence != "ND" {
		l += 11 + len(cvss20.exploitability) + len(cvss20.remediationLevel) + len(cvss20.reportConfidence)
	}

	// Environmental:
	// - CDP: 4 + len(v)
	// - TD: 3 + len(v)
	// - CR, IR, AR: 3 + len(v)
	// - separators: 5
	// Total: 21 + 5*len(v)
	if cvss20.collateralDamagePotential != "ND" || cvss20.targetDistribution != "ND" || cvss20.confidentialityRequirement != "ND" || cvss20.integrityRequirement != "ND" || cvss20.availabilityRequirement != "ND" {
		l += 21 + len(cvss20.collateralDamagePotential) + len(cvss20.targetDistribution) + len(cvss20.confidentialityRequirement) + len(cvss20.integrityRequirement) + len(cvss20.availabilityRequirement)
	}

	return l
}

func app(b *[]byte, pre, v string) {
	*b = append(*b, pre...)
	*b = append(*b, v...)
	base
	temporal
	environmental
// base is the group of metrics defined with such name by the
type base struct {
	accessVector string
	accessComplexity string
	authentication string
	confidentialityImpact string
	integrityImpact string
	availabilityImpact string
// temporal is the group of metrics defined with such name by the
type temporal struct {
	exploitability string
	remediationLevel string
	reportConfidence string
// environmental is the group of metrics defined with such name by the
type environmental struct {
	collateralDamagePotential string
	targetDistribution string
	confidentialityRequirement string
	integrityRequirement       string
	availabilityRequirement    string
		return cvss20.accessVector, nil
		return cvss20.accessComplexity, nil
		return cvss20.authentication, nil
		return cvss20.confidentialityImpact, nil
		return cvss20.integrityImpact, nil
		return cvss20.availabilityImpact, nil
		return cvss20.exploitability, nil
		return cvss20.remediationLevel, nil
		return cvss20.reportConfidence, nil
		return cvss20.collateralDamagePotential, nil
		return cvss20.targetDistribution, nil
		return cvss20.confidentialityRequirement, nil
		return cvss20.integrityRequirement, nil
		return cvss20.availabilityRequirement, nil
		cvss20.accessVector = value
		cvss20.accessComplexity = value
		cvss20.authentication = value
		cvss20.confidentialityImpact = value
		cvss20.integrityImpact = value
		cvss20.availabilityImpact = value
		cvss20.exploitability = value
		cvss20.remediationLevel = value
		cvss20.reportConfidence = value
		cvss20.collateralDamagePotential = value
		cvss20.targetDistribution = value
		cvss20.confidentialityRequirement = value
		cvss20.integrityRequirement = value
		cvss20.availabilityRequirement = value
	impact := cvss20.Impact()
	exploitability := cvss20.Exploitability()
func (cvss20 CVSS20) Impact() float64 {
	return 10.41 * (1 - (1-cia(cvss20.confidentialityImpact))*(1-cia(cvss20.integrityImpact))*(1-cia(cvss20.availabilityImpact)))
}

func (cvss20 CVSS20) Exploitability() float64 {
	return 20 * accessVector(cvss20.accessVector) * accessComplexity(cvss20.accessComplexity) * authentication(cvss20.authentication)
}

	return roundTo1Decimal(cvss20.BaseScore() * exploitability(cvss20.exploitability) * remediationLevel(cvss20.remediationLevel) * reportConfidence(cvss20.reportConfidence))
	adjustedImpact := math.Min(10, 10.41*(1-(1-cia(cvss20.confidentialityImpact)*ciar(cvss20.confidentialityRequirement))*(1-cia(cvss20.integrityImpact)*ciar(cvss20.integrityRequirement))*(1-cia(cvss20.availabilityImpact)*ciar(cvss20.availabilityRequirement))))
	expltBase := 20 * accessVector(cvss20.accessVector) * accessComplexity(cvss20.accessComplexity) * authentication(cvss20.authentication)
	adjustedTemporal := roundTo1Decimal(recBase * exploitability(cvss20.exploitability) * remediationLevel(cvss20.remediationLevel) * reportConfidence(cvss20.reportConfidence))
	return roundTo1Decimal((adjustedTemporal + (10-adjustedTemporal)*collateralDamagePotential(cvss20.collateralDamagePotential)) * targetDistribution(cvss20.targetDistribution))
package gocvss20_test

import (
	"testing"

	gocvss20 "github.com/pandatix/go-cvss/20"
)

var Gcvss20 *gocvss20.CVSS20
var Gerr error

func BenchmarkParseVector_Base(b *testing.B) {
	benchmarkParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C", b)
}

func BenchmarkParseVector_WithTempAndEnv(b *testing.B) {
	benchmarkParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M", b)
}

func benchmarkParseVector(vector string, b *testing.B) {
	var cvss20 *gocvss20.CVSS20
	var err error
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		cvss20, err = gocvss20.ParseVector(vector)
	}
	Gcvss20 = cvss20
	Gerr = err
}

var Gstr string

func BenchmarkCVSS20Vector(b *testing.B) {
	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
	var str string
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		str = cvss20.Vector()
	}
	Gstr = str
}

var Gget string

func BenchmarkCVSS20Get(b *testing.B) {
	const abv = "Au"
	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
	var get string
	var err error
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		get, err = cvss20.Get(abv)
	}
	Gget = get
	Gerr = err
}

func BenchmarkCVSS20Set(b *testing.B) {
	const abv = "Au"
	const value = "S"
	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
	var err error
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		err = cvss20.Set(abv, value)
	}
	Gerr = err
}

var Gscore float64

func BenchmarkCVSS20BaseScore(b *testing.B) {
	var score float64
	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		score = cvss20.BaseScore()
	}
	Gscore = score
}

func BenchmarkCVSS20TemporalScore(b *testing.B) {
	var score float64
	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		score = cvss20.TemporalScore()
	}
	Gscore = score
}

func BenchmarkCVSS20EnvironmentalScore(b *testing.B) {
	var score float64
	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		score = cvss20.EnvironmentalScore()
	}
	Gscore = score
}
package gocvss20
		cvss20, err := ParseVector(vector)
package gocvss20
	ExpectedCVSS20 *CVSS20
		ExpectedCVSS20: &CVSS20{
			base: base{
				accessVector:          "N",
				accessComplexity:      "L",
				authentication:        "N",
				confidentialityImpact: "N",
				integrityImpact:       "N",
				availabilityImpact:    "C",
			temporal: temporal{
				exploitability:   "F",
				remediationLevel: "OF",
				reportConfidence: "C",
			environmental: environmental{
				collateralDamagePotential:  "ND",
				targetDistribution:         "ND",
				confidentialityRequirement: "ND",
				integrityRequirement:       "ND",
				availabilityRequirement:    "ND",
		ExpectedCVSS20: &CVSS20{
			base: base{
				accessVector:          "N",
				accessComplexity:      "L",
				authentication:        "N",
				confidentialityImpact: "C",
				integrityImpact:       "C",
				availabilityImpact:    "C",
			temporal: temporal{
				exploitability:   "F",
				remediationLevel: "OF",
				reportConfidence: "C",
			environmental: environmental{
				collateralDamagePotential:  "ND",
				targetDistribution:         "ND",
				confidentialityRequirement: "ND",
				integrityRequirement:       "ND",
				availabilityRequirement:    "ND",
		ExpectedCVSS20: &CVSS20{
			base: base{
				accessVector:          "L",
				accessComplexity:      "H",
				authentication:        "N",
				confidentialityImpact: "C",
				integrityImpact:       "C",
				availabilityImpact:    "C",
			temporal: temporal{
				exploitability:   "POC",
				remediationLevel: "OF",
				reportConfidence: "C",
			environmental: environmental{
				collateralDamagePotential:  "ND",
				targetDistribution:         "ND",
				confidentialityRequirement: "ND",
				integrityRequirement:       "ND",
				availabilityRequirement:    "ND",
	"all-defined": {
		Vector: "AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M",
		ExpectedCVSS20: &CVSS20{
			base: base{
				accessVector:          "N",
				accessComplexity:      "L",
				authentication:        "N",
				confidentialityImpact: "P",
				integrityImpact:       "P",
				availabilityImpact:    "C",
			},
			temporal: temporal{
				exploitability:   "U",
				remediationLevel: "OF",
				reportConfidence: "C",
			},
			environmental: environmental{
				collateralDamagePotential:  "MH",
				targetDistribution:         "H",
				confidentialityRequirement: "M",
				integrityRequirement:       "M",
				availabilityRequirement:    "M",
			},
		},
		ExpectedErr: nil,
	},
	"Fuzz_50620a37c4a7716a77a14602b4bcc7b02e6f751d0a714ed796d9b04402c745ac": {
		// This fuzz crasher enabled detecting that the split function
		// (comming from the optimization step) was doing an Out-Of-Bounds
		// Write (CWE-787) if the vector was only composed of '/'.
		Vector:         "//////////////",
		ExpectedCVSS20: nil,
		ExpectedErr:    ErrInvalidMetricOrder,
	},
			cvss20, err := ParseVector(tt.Vector)
		CVSS20                     *CVSS20
			CVSS20: &CVSS20{
				base: base{
					accessVector:          "N",
					accessComplexity:      "L",
					authentication:        "N",
					confidentialityImpact: "N",
					integrityImpact:       "N",
					availabilityImpact:    "C",
				temporal: temporal{
					exploitability:   "F",
					remediationLevel: "OF",
					reportConfidence: "C",
				environmental: environmental{
					collateralDamagePotential:  "ND",
					targetDistribution:         "ND",
					confidentialityRequirement: "ND",
					integrityRequirement:       "ND",
					availabilityRequirement:    "ND",
			CVSS20: &CVSS20{
				base: base{
					accessVector:          "N",
					accessComplexity:      "L",
					authentication:        "N",
					confidentialityImpact: "C",
					integrityImpact:       "C",
					availabilityImpact:    "C",
				temporal: temporal{
					exploitability:   "F",
					remediationLevel: "OF",
					reportConfidence: "C",
				environmental: environmental{
					collateralDamagePotential:  "ND",
					targetDistribution:         "ND",
					confidentialityRequirement: "ND",
					integrityRequirement:       "ND",
					availabilityRequirement:    "ND",
			CVSS20: &CVSS20{
				base: base{
					accessVector:          "L",
					accessComplexity:      "H",
					authentication:        "N",
					confidentialityImpact: "C",
					integrityImpact:       "C",
					availabilityImpact:    "C",
				temporal: temporal{
					exploitability:   "POC",
					remediationLevel: "OF",
					reportConfidence: "C",
				environmental: environmental{
					collateralDamagePotential:  "ND",
					targetDistribution:         "ND",
					confidentialityRequirement: "ND",
					integrityRequirement:       "ND",
					availabilityRequirement:    "ND",
	Abv string
	return fmt.Sprintf("given CVSS v3.1 vector has %s metric abbreviation defined after vector end", err.Abv)
```
goos: linux
goarch: amd64
pkg: github.com/pandatix/go-cvss/20
cpu: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
BenchmarkParseVector_Base-4             	 2089275	       572.9 ns/op	     224 B/op	       1 allocs/op
BenchmarkParseVector_WithTempAndEnv-4   	 1000000	        1118 ns/op	     224 B/op	       1 allocs/op
BenchmarkCVSS20Vector-4                 	 6806152	       176.3 ns/op	      80 B/op	       1 allocs/op
BenchmarkCVSS20Get-4                    	46162280	       26.50 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS20Set-4                    	42365036	       27.50 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS20BaseScore-4              	20117143	       57.68 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS20TemporalScore-4          	14383033	       83.66 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS20EnvironmentalScore-4     	15307656	       79.48 ns/op	       0 B/op	       0 allocs/op
```

BenchmarkParseVector_Base-4             	 1458514	       843.4 ns/op	     352 B/op	       1 allocs/op
BenchmarkParseVector_WithTempAndEnv-4   	  703789	        2067 ns/op	     352 B/op	       1 allocs/op
BenchmarkCVSS30Vector-4                 	 4587404	       237.0 ns/op	      96 B/op	       1 allocs/op
BenchmarkCVSS30Get-4                    	26877397	       51.38 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS30Set-4                    	32284153	       38.53 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS30BaseScore-4              	 8275440	       145.4 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS30TemporalScore-4          	 6054021	       195.7 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS30EnvironmentalScore-4     	 6230708	       191.2 ns/op	       0 B/op	       0 allocs/op
BenchmarkParseVector_Base-4             	 1445559	       825.3 ns/op	     352 B/op	       1 allocs/op
BenchmarkParseVector_WithTempAndEnv-4   	  658578	        1836 ns/op	     352 B/op	       1 allocs/op
BenchmarkCVSS31Vector-4                 	 5087984	       244.1 ns/op	      96 B/op	       1 allocs/op
BenchmarkCVSS31Get-4                    	28350058	       41.40 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31Set-4                    	30340425	       40.16 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31BaseScore-4              	 8535666	       139.3 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31TemporalScore-4          	 6004561	       189.7 ns/op	       0 B/op	       0 allocs/op
BenchmarkCVSS31EnvironmentalScore-4     	 5937879	       184.5 ns/op	       0 B/op	       0 allocs/op