diff options
| author | Paul Chaignon <paul.chaignon@orange.com> | 2019-10-18 14:45:31 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-10-25 18:16:59 +0200 |
| commit | 713f727d983ec2c0c8307a7dcafc270aeee900dd (patch) | |
| tree | 6f3d539931db47b892b5eecafd8a890a1cb9faf4 /prog/mutation.go | |
| parent | ced0f73a673b1ab94725fe1710dcf7105015eb74 (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.go | 57 |
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. |
