aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2021-12-01 17:25:40 +0000
committerAleksandr Nogikh <wp32pw@gmail.com>2021-12-10 12:30:07 +0100
commit18f846ca807cfc6df9c3da3c0ab08251277dfefb (patch)
treee14f783b914409f21ae77a01a6b74ededaba6901 /prog
parent52c8379f77b5f292e2d527c66dfe17a899381d20 (diff)
all: add the `rerun` call property
To be able to collide specific syscalls more precisely, we need to repeat the process many times. Introduce the `rerun` call property, which instructs `syz-executor` to repeat the call the specified number of times. The intended use is: call1() (rerun: 100, async) call2() (rerun: 100) For now, assign rerun values randomly to consecutive pairs of calls, where the first one is async.
Diffstat (limited to 'prog')
-rw-r--r--prog/collide.go16
-rw-r--r--prog/encoding_test.go8
-rw-r--r--prog/encodingexec_test.go14
-rw-r--r--prog/minimization.go9
-rw-r--r--prog/minimization_test.go23
-rw-r--r--prog/prog.go1
6 files changed, 62 insertions, 9 deletions
diff --git a/prog/collide.go b/prog/collide.go
index cd059c60f..77065147f 100644
--- a/prog/collide.go
+++ b/prog/collide.go
@@ -55,3 +55,19 @@ func AssignRandomAsync(origProg *Prog, rand *rand.Rand) *Prog {
return prog
}
+
+var rerunSteps = []int{32, 64}
+
+func AssignRandomRerun(prog *Prog, rand *rand.Rand) {
+ for i := 0; i+1 < len(prog.Calls); i++ {
+ if !prog.Calls[i].Props.Async || rand.Intn(4) != 0 {
+ continue
+ }
+ // We assign rerun to consecutive pairs of calls, where the first call is async.
+ // TODO: consider assigning rerun also to non-collided progs.
+ rerun := rerunSteps[rand.Intn(len(rerunSteps))]
+ prog.Calls[i].Props.Rerun = rerun
+ prog.Calls[i+1].Props.Rerun = rerun
+ i++
+ }
+}
diff --git a/prog/encoding_test.go b/prog/encoding_test.go
index e0e6fbefd..4717c402b 100644
--- a/prog/encoding_test.go
+++ b/prog/encoding_test.go
@@ -421,7 +421,7 @@ func TestSerializeCallProps(t *testing.T) {
},
{
"serialize0(0x0) (fail_nth: 5)\n",
- []CallProps{{5, false}},
+ []CallProps{{5, false, 0}},
},
{
"serialize0(0x0) (fail_nth)\n",
@@ -433,7 +433,11 @@ func TestSerializeCallProps(t *testing.T) {
},
{
"serialize0(0x0) (async)\n",
- []CallProps{{0, true}},
+ []CallProps{{0, true, 0}},
+ },
+ {
+ "serialize0(0x0) (async, rerun: 10)\n",
+ []CallProps{{0, true, 10}},
},
}
diff --git a/prog/encodingexec_test.go b/prog/encodingexec_test.go
index fe6a4dfb4..879aed893 100644
--- a/prog/encodingexec_test.go
+++ b/prog/encodingexec_test.go
@@ -465,14 +465,14 @@ func TestSerializeForExec(t *testing.T) {
{
`test() (fail_nth: 3)
test() (fail_nth: 4)
-test() (async)
+test() (async, rerun: 10)
`,
[]uint64{
- execInstrSetProps, 3, 0,
+ execInstrSetProps, 3, 0, 0,
callID("test"), ExecNoCopyout, 0,
- execInstrSetProps, 4, 0,
+ execInstrSetProps, 4, 0, 0,
callID("test"), ExecNoCopyout, 0,
- execInstrSetProps, 0, 1,
+ execInstrSetProps, 0, 1, 10,
callID("test"), ExecNoCopyout, 0,
execInstrEOF,
},
@@ -481,17 +481,17 @@ test() (async)
{
Meta: target.SyscallMap["test"],
Index: ExecNoCopyout,
- Props: CallProps{3, false},
+ Props: CallProps{3, false, 0},
},
{
Meta: target.SyscallMap["test"],
Index: ExecNoCopyout,
- Props: CallProps{4, false},
+ Props: CallProps{4, false, 0},
},
{
Meta: target.SyscallMap["test"],
Index: ExecNoCopyout,
- Props: CallProps{0, true},
+ Props: CallProps{0, true, 10},
},
},
},
diff --git a/prog/minimization.go b/prog/minimization.go
index 89ed6e142..26a4dfc93 100644
--- a/prog/minimization.go
+++ b/prog/minimization.go
@@ -120,6 +120,15 @@ func minimizeCallProps(p0 *Prog, callIndex, callIndex0 int, pred func(*Prog, int
}
}
+ // Try to drop rerun.
+ if props.Rerun > 0 {
+ p := p0.Clone()
+ p.Calls[callIndex].Props.Rerun = 0
+ if pred(p, callIndex0) {
+ p0 = p
+ }
+ }
+
return p0
}
diff --git a/prog/minimization_test.go b/prog/minimization_test.go
index cf499b7f1..697937e92 100644
--- a/prog/minimization_test.go
+++ b/prog/minimization_test.go
@@ -8,6 +8,7 @@ import (
"testing"
)
+// nolint:gocyclo
func TestMinimize(t *testing.T) {
tests := []struct {
os string
@@ -193,6 +194,28 @@ func TestMinimize(t *testing.T) {
"pipe2(0x0, 0x0) (async)\n",
-1,
},
+ // Clear unneeded rerun.
+ {
+ "linux", "amd64",
+ "pipe2(0x0, 0x0) (rerun: 100)\n",
+ -1,
+ func(p *Prog, callIndex int) bool {
+ return len(p.Calls) == 1 && p.Calls[0].Meta.Name == "pipe2"
+ },
+ "pipe2(0x0, 0x0)\n",
+ -1,
+ },
+ // Keep important rerun.
+ {
+ "linux", "amd64",
+ "pipe2(0x0, 0x0) (rerun: 100)\n",
+ -1,
+ func(p *Prog, callIndex int) bool {
+ return len(p.Calls) == 1 && p.Calls[0].Meta.Name == "pipe2" && p.Calls[0].Props.Rerun >= 100
+ },
+ "pipe2(0x0, 0x0) (rerun: 100)\n",
+ -1,
+ },
}
t.Parallel()
for ti, test := range tests {
diff --git a/prog/prog.go b/prog/prog.go
index 09da7fdf2..86e424299 100644
--- a/prog/prog.go
+++ b/prog/prog.go
@@ -21,6 +21,7 @@ type Prog struct {
type CallProps struct {
FailNth int `key:"fail_nth"`
Async bool `key:"async"`
+ Rerun int `key:"rerun"`
}
type Call struct {