aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorVeronica Radu <veronicaradu@google.com>2019-08-07 18:00:46 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-08-09 15:02:02 +0200
commitaff9e255cd708709adef545d1f932020ee5c0978 (patch)
tree353468cb149a587e747cfc702003946abd5130a2 /prog
parente5701ed16c822ef5a4abc4224b44c36b3489aca3 (diff)
prog: add special mutation for binary flags
Diffstat (limited to 'prog')
-rw-r--r--prog/mutation.go26
-rw-r--r--prog/mutation_test.go34
-rw-r--r--prog/rand.go16
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) {