golang.org/x/tools/gopls@v0.15.3/internal/vulncheck/vulntest/report.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.18 6 // +build go1.18 7 8 package vulntest 9 10 import ( 11 "fmt" 12 "io" 13 "os" 14 "strings" 15 "time" 16 17 "golang.org/x/mod/semver" 18 "golang.org/x/tools/gopls/internal/vulncheck/osv" 19 "gopkg.in/yaml.v3" 20 ) 21 22 // 23 // The following was selectively copied from golang.org/x/vulndb/internal/report 24 // 25 26 // readReport reads a Report in YAML format. 27 func readReport(in io.Reader) (*Report, error) { 28 d := yaml.NewDecoder(in) 29 // Require that all fields in the file are in the struct. 30 // This corresponds to v2's UnmarshalStrict. 31 d.KnownFields(true) 32 var r Report 33 if err := d.Decode(&r); err != nil { 34 return nil, fmt.Errorf("yaml.Decode: %v", err) 35 } 36 return &r, nil 37 } 38 39 // Report represents a vulnerability report in the vulndb. 40 // See https://go.googlesource.com/vulndb/+/refs/heads/master/doc/format.md 41 type Report struct { 42 ID string `yaml:",omitempty"` 43 44 Modules []*Module `yaml:",omitempty"` 45 46 // Summary is a short phrase describing the vulnerability. 47 Summary string `yaml:",omitempty"` 48 49 // Description is the CVE description from an existing CVE. If we are 50 // assigning a CVE ID ourselves, use CVEMetadata.Description instead. 51 Description string `yaml:",omitempty"` 52 Published time.Time `yaml:",omitempty"` 53 Withdrawn *time.Time `yaml:",omitempty"` 54 55 References []*Reference `yaml:",omitempty"` 56 } 57 58 // Write writes r to filename in YAML format. 59 func (r *Report) Write(filename string) (err error) { 60 f, err := os.Create(filename) 61 if err != nil { 62 return err 63 } 64 err = r.encode(f) 65 err2 := f.Close() 66 if err == nil { 67 err = err2 68 } 69 return err 70 } 71 72 // ToString encodes r to a YAML string. 73 func (r *Report) ToString() (string, error) { 74 var b strings.Builder 75 if err := r.encode(&b); err != nil { 76 return "", err 77 } 78 return b.String(), nil 79 } 80 81 func (r *Report) encode(w io.Writer) error { 82 e := yaml.NewEncoder(w) 83 defer e.Close() 84 e.SetIndent(4) 85 return e.Encode(r) 86 } 87 88 type VersionRange struct { 89 Introduced Version `yaml:"introduced,omitempty"` 90 Fixed Version `yaml:"fixed,omitempty"` 91 } 92 93 type Module struct { 94 Module string `yaml:",omitempty"` 95 Versions []VersionRange `yaml:",omitempty"` 96 Packages []*Package `yaml:",omitempty"` 97 } 98 99 type Package struct { 100 Package string `yaml:",omitempty"` 101 GOOS []string `yaml:"goos,omitempty"` 102 GOARCH []string `yaml:"goarch,omitempty"` 103 // Symbols originally identified as vulnerable. 104 Symbols []string `yaml:",omitempty"` 105 // Additional vulnerable symbols, computed from Symbols via static analysis 106 // or other technique. 107 DerivedSymbols []string `yaml:"derived_symbols,omitempty"` 108 } 109 110 // Version is an SemVer 2.0.0 semantic version with no leading "v" prefix, 111 // as used by OSV. 112 type Version string 113 114 // V returns the version with a "v" prefix. 115 func (v Version) V() string { 116 return "v" + string(v) 117 } 118 119 // IsValid reports whether v is a valid semantic version string. 120 func (v Version) IsValid() bool { 121 return semver.IsValid(v.V()) 122 } 123 124 // Before reports whether v < v2. 125 func (v Version) Before(v2 Version) bool { 126 return semver.Compare(v.V(), v2.V()) < 0 127 } 128 129 // Canonical returns the canonical formatting of the version. 130 func (v Version) Canonical() string { 131 return strings.TrimPrefix(semver.Canonical(v.V()), "v") 132 } 133 134 // Reference type is a reference (link) type. 135 type ReferenceType string 136 137 const ( 138 ReferenceTypeAdvisory = ReferenceType("ADVISORY") 139 ReferenceTypeArticle = ReferenceType("ARTICLE") 140 ReferenceTypeReport = ReferenceType("REPORT") 141 ReferenceTypeFix = ReferenceType("FIX") 142 ReferenceTypePackage = ReferenceType("PACKAGE") 143 ReferenceTypeEvidence = ReferenceType("EVIDENCE") 144 ReferenceTypeWeb = ReferenceType("WEB") 145 ) 146 147 // ReferenceTypes is the set of reference types defined in OSV. 148 var ReferenceTypes = []ReferenceType{ 149 ReferenceTypeAdvisory, 150 ReferenceTypeArticle, 151 ReferenceTypeReport, 152 ReferenceTypeFix, 153 ReferenceTypePackage, 154 ReferenceTypeEvidence, 155 ReferenceTypeWeb, 156 } 157 158 // A Reference is a link to some external resource. 159 // 160 // For ease of typing, References are represented in the YAML as a 161 // single-element mapping of type to URL. 162 type Reference osv.Reference 163 164 func (r *Reference) MarshalYAML() (interface{}, error) { 165 return map[string]string{ 166 strings.ToLower(string(r.Type)): r.URL, 167 }, nil 168 } 169 170 func (r *Reference) UnmarshalYAML(n *yaml.Node) (err error) { 171 if n.Kind != yaml.MappingNode || len(n.Content) != 2 || n.Content[0].Kind != yaml.ScalarNode || n.Content[1].Kind != yaml.ScalarNode { 172 return &yaml.TypeError{Errors: []string{ 173 fmt.Sprintf("line %d: report.Reference must contain a mapping with one value", n.Line), 174 }} 175 } 176 r.Type = osv.ReferenceType(strings.ToUpper(n.Content[0].Value)) 177 r.URL = n.Content[1].Value 178 return nil 179 }