aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-02-10 11:38:05 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2023-02-10 14:34:44 +0100
commit50b2f41ed948a2a47420d8edc9abca2d477eccfb (patch)
treeadcef18a7dd0188e32dbf8ef4dad9d5b72f15dde
parent0241baba08ba2fd732e46a9634434154d58092e3 (diff)
pkg/subsystem: detect loops on the go
This lets us reduce the amount of code in parents.go.
-rw-r--r--pkg/subsystem/entity/entities.go3
-rw-r--r--pkg/subsystem/linux/parents.go46
-rw-r--r--pkg/subsystem/linux/parents_test.go15
3 files changed, 4 insertions, 60 deletions
diff --git a/pkg/subsystem/entity/entities.go b/pkg/subsystem/entity/entities.go
index 9d1d8e5a5..e2b29a7f3 100644
--- a/pkg/subsystem/entity/entities.go
+++ b/pkg/subsystem/entity/entities.go
@@ -21,6 +21,9 @@ func (subsystem *Subsystem) ReachableParents() map[*Subsystem]struct{} {
return
}
for _, p := range node.Parents {
+ if p == subsystem {
+ panic("loop in the parents relation")
+ }
ret[p] = struct{}{}
dfs(p)
}
diff --git a/pkg/subsystem/linux/parents.go b/pkg/subsystem/linux/parents.go
index 6d27565bf..fdea4a62f 100644
--- a/pkg/subsystem/linux/parents.go
+++ b/pkg/subsystem/linux/parents.go
@@ -4,8 +4,6 @@
package linux
import (
- "fmt"
-
"github.com/google/syzkaller/pkg/subsystem/entity"
"github.com/google/syzkaller/pkg/subsystem/match"
)
@@ -39,12 +37,9 @@ func setParents(matrix *match.CoincidenceMatrix, list []*entity.Subsystem) error
// Demand that >= 50% paths are related.
if 2*count/matrix.Count(a) >= 1 && matrix.Count(a) < matrix.Count(b) {
a.Parents = append(a.Parents, b)
+ a.ReachableParents() // make sure we haven't created a loop
}
})
- // Just in case.
- if loopsExist(list) {
- return fmt.Errorf("there are loops in the parents relation")
- }
transitiveReduction(list)
return nil
}
@@ -124,42 +119,3 @@ func transitiveReduction(list []*entity.Subsystem) {
s.Parents = newParents
}
}
-
-// loopsExist is a helper method that verifies that the resulting graph has no loops.
-func loopsExist(list []*entity.Subsystem) bool {
- type graphNode struct {
- obj *entity.Subsystem
- entered bool
- left bool
- }
- nodes := []*graphNode{}
- objToNode := map[*entity.Subsystem]*graphNode{}
- for _, obj := range list {
- node := &graphNode{obj: obj}
- nodes = append(nodes, node)
- objToNode[obj] = node
- }
- var dfs func(*graphNode) bool
- dfs = func(node *graphNode) bool {
- if node.left {
- return false
- }
- if node.entered {
- // We've found a cycle.
- return true
- }
- node.entered = true
- anyLoop := false
- for _, parent := range node.obj.Parents {
- anyLoop = anyLoop || dfs(objToNode[parent])
- }
- node.left = true
- return anyLoop
- }
- for _, node := range nodes {
- if dfs(node) {
- return true
- }
- }
- return false
-}
diff --git a/pkg/subsystem/linux/parents_test.go b/pkg/subsystem/linux/parents_test.go
index f1942671d..dde13177d 100644
--- a/pkg/subsystem/linux/parents_test.go
+++ b/pkg/subsystem/linux/parents_test.go
@@ -69,21 +69,6 @@ func TestDropDuplicateSubsystems(t *testing.T) {
assert.ElementsMatch(t, ret, expected)
}
-func TestLoopsDoExist(t *testing.T) {
- a := &entity.Subsystem{}
- b := &entity.Subsystem{Parents: []*entity.Subsystem{a}}
- c := &entity.Subsystem{Parents: []*entity.Subsystem{b}}
- a.Parents = []*entity.Subsystem{c}
- assert.True(t, loopsExist([]*entity.Subsystem{a, b, c}))
-}
-
-func TestLoopsDoNotExist(t *testing.T) {
- a := &entity.Subsystem{}
- b := &entity.Subsystem{Parents: []*entity.Subsystem{a}}
- c := &entity.Subsystem{Parents: []*entity.Subsystem{b}}
- assert.False(t, loopsExist([]*entity.Subsystem{a, b, c}))
-}
-
func TestTransitiveReduction(t *testing.T) {
// (d, c), (c, b), (b, a)
// (d, a)