-
Notifications
You must be signed in to change notification settings - Fork 1
/
new.go
99 lines (91 loc) · 2.43 KB
/
new.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package database
import (
"fmt"
"github.com/khulnasoft-lab/go-vulndb/internal/osv"
"github.com/khulnasoft-lab/go-vulndb/internal/version"
)
// New creates a new database from the given entries.
// Errors if there are multiple entries with the same ID.
func New(entries ...osv.Entry) (*Database, error) {
db := &Database{
DB: DBMeta{},
Modules: make(ModulesIndex),
Vulns: make(VulnsIndex),
Entries: make([]osv.Entry, 0, len(entries)),
}
for _, entry := range entries {
if err := db.Add(entry); err != nil {
return nil, err
}
}
return db, nil
}
// Add adds new entries to a database, erroring if any of the entries
// is already in the database.
func (db *Database) Add(entries ...osv.Entry) error {
for _, entry := range entries {
if err := db.Vulns.add(entry); err != nil {
return err
}
// Only add the entry once we are sure it won't
// cause an error.
db.Entries = append(db.Entries, entry)
db.Modules.add(entry)
db.DB.add(entry)
}
return nil
}
func (dbi *DBMeta) add(entry osv.Entry) {
if entry.Modified.After(dbi.Modified.Time) {
dbi.Modified = entry.Modified
}
}
func (m *ModulesIndex) add(entry osv.Entry) {
for _, affected := range entry.Affected {
modulePath := affected.Module.Path
if _, ok := (*m)[modulePath]; !ok {
(*m)[modulePath] = &Module{
Path: modulePath,
Vulns: []ModuleVuln{},
}
}
module := (*m)[modulePath]
module.Vulns = append(module.Vulns, ModuleVuln{
ID: entry.ID,
Modified: entry.Modified,
Fixed: latestFixedVersion(affected.Ranges),
})
}
}
func (v *VulnsIndex) add(entry osv.Entry) error {
if _, ok := (*v)[entry.ID]; ok {
return fmt.Errorf("id %q appears twice in database", entry.ID)
}
(*v)[entry.ID] = &Vuln{
ID: entry.ID,
Modified: entry.Modified,
Aliases: entry.Aliases,
}
return nil
}
func latestFixedVersion(ranges []osv.Range) string {
var latestFixed string
for _, r := range ranges {
if r.Type == osv.RangeTypeSemver {
for _, e := range r.Events {
if fixed := e.Fixed; fixed != "" && version.Before(latestFixed, fixed) {
latestFixed = fixed
}
}
// If the vulnerability was re-introduced after the latest fix
// we found, there is no latest fix for this range.
for _, e := range r.Events {
if introduced := e.Introduced; introduced != "" && introduced != "0" && version.Before(latestFixed, introduced) {
latestFixed = ""
break
}
}
}
}
return string(latestFixed)
}