diff options
| author | Veronica Radu <veronicaradu@google.com> | 2019-08-07 18:00:46 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-08-09 15:02:02 +0200 |
| commit | aff9e255cd708709adef545d1f932020ee5c0978 (patch) | |
| tree | 353468cb149a587e747cfc702003946abd5130a2 /prog | |
| parent | e5701ed16c822ef5a4abc4224b44c36b3489aca3 (diff) | |
prog: add special mutation for binary flags
Diffstat (limited to 'prog')
| -rw-r--r-- | prog/mutation.go | 26 | ||||
| -rw-r--r-- | prog/mutation_test.go | 34 | ||||
| -rw-r--r-- | prog/rand.go | 16 |
3 files changed, 67 insertions, 9 deletions
diff --git a/prog/mutation.go b/prog/mutation.go index dbb605041..a3ab17637 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -234,7 +234,31 @@ func (t *IntType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Ca } func (t *FlagsType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) { - return mutateInt(r, s, arg) + a := arg.(*ConstArg) + + for oldVal := a.Val; oldVal == a.Val; { + // Generate a new value. + if r.nOutOf(1, 5) { + a.Val = r.flags(t.Vals, t.BitMask, 0) + continue + } + + if !t.BitMask || (t.BitMask && r.nOutOf(1, 4)) { + a.Val = r.flags(t.Vals, t.BitMask, a.Val) + continue + } + + for stop := false; !stop; stop = r.oneOf(3) { + idx := r.rand(len(t.Vals)) + if r.bin() { + a.Val |= 1 << t.Vals[idx] + } else { + a.Val &= ^(1 << t.Vals[idx]) + } + } + } + + return } func (t *LenType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) { diff --git a/prog/mutation_test.go b/prog/mutation_test.go index 100820dd7..6b50b975e 100644 --- a/prog/mutation_test.go +++ b/prog/mutation_test.go @@ -11,6 +11,32 @@ import ( "testing" ) +func TestMutationFlags(t *testing.T) { + tests := [][2]string{ + // Mutate flags (bitmask = true). + { + `r0 = mutate$flags(&(0x7f0000000000)="2e2f66696c653000", 0x0, 0x1, 0x1)`, + `r0 = mutate$flags(&(0x7f0000000000)="2e2f66696c653000", 0x20, 0x1, 0x9)`, + }, + { + `r0 = mutate$flags2(&(0x7f0000000000)="2e2f66696c653000", 0x0)`, + `r0 = mutate$flags2(&(0x7f0000000000)="2e2f66696c653000", 0xd9)`, + }, + + // Mutate flags (bitmask = false). + { + `r0 = mutate$flags3(&(0x7f0000000000)="2e2f66696c653000", 0x0)`, + `r0 = mutate$flags3(&(0x7f0000000000)="2e2f66696c653000", 0xddddddddeeeeeeee)`, + }, + { + `r0 = mutate$flags3(&(0x7f0000000000)="2e2f66696c653000", 0xddddddddeeeeeeee)`, + `r0 = mutate$flags3(&(0x7f0000000000)="2e2f66696c653000", 0xaaaaaaaaaaaaaaaa)`, + }, + } + + runMutationTests(t, tests) +} + func TestClone(t *testing.T) { target, rs, iters := initTest(t) for i := 0; i < iters; i++ { @@ -68,7 +94,6 @@ func TestMutateCorpus(t *testing.T) { } func TestMutateTable(t *testing.T) { - target := initTargetTest(t, "test", "64") tests := [][2]string{ // Insert a call. {` @@ -151,6 +176,13 @@ mutate8(0x2) mutate8(0xffffffffffffffff) `}, } + + runMutationTests(t, tests) +} + +func runMutationTests(t *testing.T, tests [][2]string) { + target := initTargetTest(t, "test", "64") + for ti, test := range tests { test := test t.Run(fmt.Sprint(ti), func(t *testing.T) { diff --git a/prog/rand.go b/prog/rand.go index e4164b74a..be57c3e64 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -137,15 +137,17 @@ func (r *randGen) randPageCount() (n uint64) { return } -func (r *randGen) flags(vv []uint64) (v uint64) { +// Change a flag value or generate a new one. +func (r *randGen) flags(vv []uint64, bitmask bool, oldVal uint64) (v uint64) { + v = oldVal switch { - case r.nOutOf(90, 111): + case (bitmask && r.nOutOf(7, 10)) || (!bitmask && r.nOutOf(1, 5)): for stop := false; !stop; stop = r.bin() { - v |= vv[r.rand(len(vv))] + v |= vv[r.rand(len(vv))] // prioritized when bitmask = true } - case r.nOutOf(10, 21): - v = vv[r.rand(len(vv))] - case r.nOutOf(10, 11): + case (bitmask && r.nOutOf(2, 3)) || (!bitmask && r.nOutOf(7, 8)): + v = vv[r.rand(len(vv))] // prioritized when bitmask = false + case r.bin(): v = 0 default: v = r.rand64() @@ -675,7 +677,7 @@ func (a *VmaType) generate(r *randGen, s *state) (arg Arg, calls []*Call) { } func (a *FlagsType) generate(r *randGen, s *state) (arg Arg, calls []*Call) { - return MakeConstArg(a, r.flags(a.Vals)), nil + return MakeConstArg(a, r.flags(a.Vals, a.BitMask, 0)), nil } func (a *ConstType) generate(r *randGen, s *state) (arg Arg, calls []*Call) { |
