blob: e54086b295a531b465268a7cd0bd1930d529b7cd (
plain)
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
|
// Copyright 2023 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
package subsystem
import (
"github.com/google/syzkaller/pkg/subsystem/entity"
)
// Extractor deduces the subsystems from the list of crashes.
type Extractor struct {
raw rawExtractorInterface
}
// Crash represents the subset of the available crash information that's required for
// subsystem inference.
type Crash struct {
GuiltyPath string
SyzRepro []byte
}
// rawExtractorInterface simplifies testing.
type rawExtractorInterface interface {
FromPath(path string) []*entity.Subsystem
FromProg(progBytes []byte) []*entity.Subsystem
}
func MakeExtractor(list []*entity.Subsystem) *Extractor {
return &Extractor{raw: makeRawExtractor(list)}
}
func (e *Extractor) Extract(crashes []*Crash) []*entity.Subsystem {
// First put all subsystems to the same list.
subsystems := []*entity.Subsystem{}
for _, crash := range crashes {
if crash.GuiltyPath != "" {
subsystems = append(subsystems, e.raw.FromPath(crash.GuiltyPath)...)
}
if len(crash.SyzRepro) > 0 {
subsystems = append(subsystems, e.raw.FromProg(crash.SyzRepro)...)
}
}
// If there are both parents and children, remove parents.
ignore := make(map[*entity.Subsystem]struct{})
for _, entry := range subsystems {
for p := range entry.ReachableParents() {
ignore[p] = struct{}{}
}
}
// And calculate counts.
counts := make(map[*entity.Subsystem]int)
maxCount := 0
for _, entry := range subsystems {
if _, ok := ignore[entry]; ok {
continue
}
counts[entry]++
if counts[entry] > maxCount {
maxCount = counts[entry]
}
}
// Pick the most prevalent ones.
ret := []*entity.Subsystem{}
for entry, count := range counts {
if count < maxCount {
continue
}
ret = append(ret, entry)
}
return ret
}
|