aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-05-07 14:24:00 +0200
committerDmitry Vyukov <dvyukov@google.com>2018-05-07 14:42:22 +0200
commit068da17e1ff5761c92d2dfa080c68bbc7b25ce90 (patch)
tree236dde1d949471b47785fc7345e6d97188a78fed
parent5f9dcfdadbca65b92a9cfd193cf280bc4968bb1a (diff)
prog: dedup mutation code
Update #538
-rw-r--r--.gometalinter.json2
-rw-r--r--prog/hints.go17
-rw-r--r--prog/mutation.go198
3 files changed, 82 insertions, 135 deletions
diff --git a/.gometalinter.json b/.gometalinter.json
index 83ea5f7fc..b9cba54f3 100644
--- a/.gometalinter.json
+++ b/.gometalinter.json
@@ -6,7 +6,7 @@
"minconstlength": 7,
"linelength": 120,
"cyclo": 50,
- "duplthreshold": 85,
+ "duplthreshold": 83,
"skip": [
"pkg/kd",
"sys/akaros/gen",
diff --git a/prog/hints.go b/prog/hints.go
index 11c7b697b..3d519d694 100644
--- a/prog/hints.go
+++ b/prog/hints.go
@@ -162,13 +162,16 @@ func checkDataArg(arg *DataArg, compMap CompMap, exec func()) {
// Note that executor sign extends all the comparison operands to int64.
// ======================================================================
func shrinkExpand(v uint64, compMap CompMap) (replacers uint64Set) {
- for _, isize := range []int{64, 32, 16, 8, -32, -16, -8} {
+ for _, iwidth := range []int{8, 4, 2, 1, -4, -2, -1} {
+ var width int
var size, mutant uint64
- if isize > 0 {
- size = uint64(isize)
+ if iwidth > 0 {
+ width = iwidth
+ size = uint64(width) * 8
mutant = v & ((1 << size) - 1)
} else {
- size = uint64(-isize)
+ width = -iwidth
+ size = uint64(width) * 8
mutant = v | ^((1 << size) - 1)
}
// Use big-endian match/replace for both blobs and ints.
@@ -181,10 +184,10 @@ func shrinkExpand(v uint64, compMap CompMap) (replacers uint64Set) {
// In such case we will see dynamic operand that does not match what we have in the program.
for _, bigendian := range []bool{false, true} {
if bigendian {
- if size == 8 {
+ if width == 1 {
continue
}
- mutant = swap(mutant, size)
+ mutant = swapInt(mutant, width)
}
for newV := range compMap[mutant] {
mask := uint64(1<<size - 1)
@@ -194,7 +197,7 @@ func shrinkExpand(v uint64, compMap CompMap) (replacers uint64Set) {
continue
}
if bigendian {
- newV = swap(newV, size)
+ newV = swapInt(newV, width)
}
if specialIntsSet[newV] {
continue
diff --git a/prog/mutation.go b/prog/mutation.go
index 1c4115731..65cd25325 100644
--- a/prog/mutation.go
+++ b/prog/mutation.go
@@ -425,136 +425,48 @@ var mutateDataFuncs = [...]func(r *randGen, data []byte, minLen, maxLen uint64)
},
// Replace int8/int16/int32/int64 with a random value.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
- switch r.Intn(4) {
- case 0: // int8
- if len(data) == 0 {
- return data, false
- }
- data[r.Intn(len(data))] = byte(r.rand(1 << 8))
- case 1: // int16
- if len(data) < 2 {
- return data, false
- }
- i := r.Intn(len(data) - 1)
- p := (*uint16)(unsafe.Pointer(&data[i]))
- *p = uint16(r.rand(1 << 16))
- case 2: // int32
- if len(data) < 4 {
- return data, false
- }
- i := r.Intn(len(data) - 3)
- p := (*uint32)(unsafe.Pointer(&data[i]))
- *p = r.Uint32()
- case 3: // int64
- if len(data) < 8 {
- return data, false
- }
- i := r.Intn(len(data) - 7)
- p := (*uint64)(unsafe.Pointer(&data[i]))
- *p = r.Uint64()
+ width := 1 << uint(r.Intn(4))
+ if len(data) < width {
+ return data, false
}
+ i := r.Intn(len(data) - width + 1)
+ storeInt(data[i:], r.Uint64(), width)
return data, true
},
// Add/subtract from an int8/int16/int32/int64.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
- switch r.Intn(4) {
- case 0: // int8
- if len(data) == 0 {
- return data, false
- }
- i := r.Intn(len(data))
- delta := byte(r.rand(2*maxInc+1) - maxInc)
- if delta == 0 {
- delta = 1
- }
- data[i] += delta
- case 1: // int16
- if len(data) < 2 {
- return data, false
- }
- i := r.Intn(len(data) - 1)
- p := (*uint16)(unsafe.Pointer(&data[i]))
- delta := uint16(r.rand(2*maxInc+1) - maxInc)
- if delta == 0 {
- delta = 1
- }
- if r.oneOf(10) {
- *p = swap16(swap16(*p) + delta)
- } else {
- *p += delta
- }
- case 2: // int32
- if len(data) < 4 {
- return data, false
- }
- i := r.Intn(len(data) - 3)
- p := (*uint32)(unsafe.Pointer(&data[i]))
- delta := uint32(r.rand(2*maxInc+1) - maxInc)
- if delta == 0 {
- delta = 1
- }
- if r.oneOf(10) {
- *p = swap32(swap32(*p) + delta)
- } else {
- *p += delta
- }
- case 3: // int64
- if len(data) < 8 {
- return data, false
- }
- i := r.Intn(len(data) - 7)
- p := (*uint64)(unsafe.Pointer(&data[i]))
- delta := r.rand(2*maxInc+1) - maxInc
- if delta == 0 {
- delta = 1
- }
- if r.oneOf(10) {
- *p = swap64(swap64(*p) + delta)
- } else {
- *p += delta
- }
+ width := 1 << uint(r.Intn(4))
+ if len(data) < width {
+ return data, false
+ }
+ i := r.Intn(len(data) - width + 1)
+ v := loadInt(data[i:], width)
+ delta := r.rand(2*maxInc+1) - maxInc
+ if delta == 0 {
+ delta = 1
+ }
+ if r.oneOf(10) {
+ v = swapInt(v, width)
+ v += delta
+ v = swapInt(v, width)
+ } else {
+ v += delta
}
+ storeInt(data[i:], v, width)
return data, true
},
// Set int8/int16/int32/int64 to an interesting value.
func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
- switch r.Intn(4) {
- case 0: // int8
- if len(data) == 0 {
- return data, false
- }
- data[r.Intn(len(data))] = byte(r.randInt())
- case 1: // int16
- if len(data) < 2 {
- return data, false
- }
- i := r.Intn(len(data) - 1)
- value := uint16(r.randInt())
- if r.oneOf(10) {
- value = swap16(value)
- }
- *(*uint16)(unsafe.Pointer(&data[i])) = value
- case 2: // int32
- if len(data) < 4 {
- return data, false
- }
- i := r.Intn(len(data) - 3)
- value := uint32(r.randInt())
- if r.oneOf(10) {
- value = swap32(value)
- }
- *(*uint32)(unsafe.Pointer(&data[i])) = value
- case 3: // int64
- if len(data) < 8 {
- return data, false
- }
- i := r.Intn(len(data) - 7)
- value := r.randInt()
- if r.oneOf(10) {
- value = swap64(value)
- }
- *(*uint64)(unsafe.Pointer(&data[i])) = value
+ width := 1 << uint(r.Intn(4))
+ if len(data) < width {
+ return data, false
+ }
+ i := r.Intn(len(data) - width + 1)
+ value := r.randInt()
+ if r.oneOf(10) {
+ value = swap64(value)
}
+ storeInt(data[i:], value, width)
return data, true
},
}
@@ -602,17 +514,49 @@ func swap64(v uint64) uint64 {
return v
}
-func swap(v, size uint64) uint64 {
+func swapInt(v uint64, size int) uint64 {
switch size {
- case 64:
- return swap64(v)
- case 32:
- return uint64(swap32(uint32(v)))
- case 16:
+ case 1:
+ return v
+ case 2:
return uint64(swap16(uint16(v)))
+ case 4:
+ return uint64(swap32(uint32(v)))
case 8:
- return v
+ return swap64(v)
+ default:
+ panic(fmt.Sprintf("swapInt: bad size %v", size))
+ }
+}
+
+func loadInt(data []byte, size int) uint64 {
+ p := unsafe.Pointer(&data[0])
+ switch size {
+ case 1:
+ return uint64(*(*uint8)(p))
+ case 2:
+ return uint64(*(*uint16)(p))
+ case 4:
+ return uint64(*(*uint32)(p))
+ case 8:
+ return *(*uint64)(p)
+ default:
+ panic(fmt.Sprintf("loadInt: bad size %v", size))
+ }
+}
+
+func storeInt(data []byte, v uint64, size int) {
+ p := unsafe.Pointer(&data[0])
+ switch size {
+ case 1:
+ *(*uint8)(p) = uint8(v)
+ case 2:
+ *(*uint16)(p) = uint16(v)
+ case 4:
+ *(*uint32)(p) = uint32(v)
+ case 8:
+ *(*uint64)(p) = v
default:
- panic(fmt.Sprintf("swap: bad size %v", size))
+ panic(fmt.Sprintf("storeInt: bad size %v", size))
}
}