aboutsummaryrefslogtreecommitdiffstats
path: root/prog/mutation.go
diff options
context:
space:
mode:
authorPaul Chaignon <paul.chaignon@orange.com>2019-10-18 14:45:31 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-10-25 18:16:59 +0200
commit713f727d983ec2c0c8307a7dcafc270aeee900dd (patch)
tree6f3d539931db47b892b5eecafd8a890a1cb9faf4 /prog/mutation.go
parentced0f73a673b1ab94725fe1710dcf7105015eb74 (diff)
prog, pkg/compiler: alignment for integer ranges
Enables the syntax intN[start:end, alignment] for integer ranges. For instance, int32[0:10, 2] represents even 32-bit numbers between 0 and 10 included. With this change, two NEED tags in syscall descriptions can be addressed. Signed-off-by: Paul Chaignon <paul.chaignon@orange.com>
Diffstat (limited to 'prog/mutation.go')
-rw-r--r--prog/mutation.go57
1 files changed, 45 insertions, 12 deletions
diff --git a/prog/mutation.go b/prog/mutation.go
index 3f5129f4d..c9f647ae8 100644
--- a/prog/mutation.go
+++ b/prog/mutation.go
@@ -254,26 +254,50 @@ func regenerate(r *randGen, s *state, arg Arg) (calls []*Call, retry, preserve b
return
}
-func mutateInt(r *randGen, s *state, arg Arg) (calls []*Call, retry, preserve bool) {
- if r.bin() {
- return regenerate(r, s, arg)
+func mutateInt(r *randGen, a *ConstArg, t *IntType) uint64 {
+ switch {
+ case r.nOutOf(1, 3):
+ return a.Val + (uint64(r.Intn(4)) + 1)
+ case r.nOutOf(1, 2):
+ return a.Val - (uint64(r.Intn(4)) + 1)
+ default:
+ return a.Val ^ (1 << uint64(r.Intn(int(t.TypeBitSize()))))
}
- bits := arg.Type().TypeBitSize()
- a := arg.(*ConstArg)
+}
+
+func mutateAlignedInt(r *randGen, a *ConstArg, t *IntType) uint64 {
+ rangeEnd := t.RangeEnd
+ if t.RangeBegin == 0 && int64(rangeEnd) == -1 {
+ // Special [0:-1] range for all possible values.
+ rangeEnd = uint64(1<<t.TypeBitSize() - 1)
+ }
+ index := (a.Val - t.RangeBegin) / t.Align
+ misalignment := (a.Val - t.RangeBegin) % t.Align
switch {
case r.nOutOf(1, 3):
- a.Val += uint64(r.Intn(4)) + 1
+ index += uint64(r.Intn(4)) + 1
case r.nOutOf(1, 2):
- a.Val -= uint64(r.Intn(4)) + 1
+ index -= uint64(r.Intn(4)) + 1
default:
- a.Val ^= 1 << uint64(r.Intn(int(bits)))
+ index ^= 1 << uint64(r.Intn(int(t.TypeBitSize())))
}
- a.Val = truncateToBitSize(a.Val, bits)
- return
+ lastIndex := (rangeEnd - t.RangeBegin) / t.Align
+ index %= lastIndex + 1
+ return t.RangeBegin + index*t.Align + misalignment
}
func (t *IntType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
- return mutateInt(r, s, arg)
+ if r.bin() {
+ return regenerate(r, s, arg)
+ }
+ a := arg.(*ConstArg)
+ if t.Align == 0 {
+ a.Val = mutateInt(r, a, t)
+ } else {
+ a.Val = mutateAlignedInt(r, a, t)
+ }
+ a.Val = truncateToBitSize(a.Val, t.TypeBitSize())
+ return
}
func (t *FlagsType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
@@ -501,7 +525,16 @@ func (t *IntType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (
return plainPrio, false
}
- switch size := t.RangeEnd - t.RangeBegin + 1; {
+ size := t.RangeEnd - t.RangeBegin + 1
+ if t.Align != 0 {
+ if t.RangeBegin == 0 && int64(t.RangeEnd) == -1 {
+ // Special [0:-1] range for all possible values.
+ size = (1<<t.TypeBitSize()-1)/t.Align + 1
+ } else {
+ size = (t.RangeEnd-t.RangeBegin)/t.Align + 1
+ }
+ }
+ switch {
case size <= 15:
// For a small range, we assume that it is effectively
// similar with FlagsType and we need to try all possible values.