diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-05-07 14:24:00 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-05-07 14:42:22 +0200 |
| commit | 068da17e1ff5761c92d2dfa080c68bbc7b25ce90 (patch) | |
| tree | 236dde1d949471b47785fc7345e6d97188a78fed | |
| parent | 5f9dcfdadbca65b92a9cfd193cf280bc4968bb1a (diff) | |
prog: dedup mutation code
Update #538
| -rw-r--r-- | .gometalinter.json | 2 | ||||
| -rw-r--r-- | prog/hints.go | 17 | ||||
| -rw-r--r-- | prog/mutation.go | 198 |
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)) } } |
