Merge pull request #71 from xairy/blob_mutation

Better blob mutation
This commit is contained in:
Dmitry Vyukov 2016-09-19 19:43:53 +02:00 committed by GitHub
commit 8f1cbd29ba

View File

@ -6,6 +6,7 @@ package prog
import (
"fmt"
"math/rand"
"unsafe"
"github.com/google/syzkaller/sys"
)
@ -380,27 +381,59 @@ func mutationArgs(c *Call) (args, bases []*Arg, parents []*[]*Arg) {
return
}
func swap16(v uint16) uint16 {
v0 := byte(v >> 0)
v1 := byte(v >> 8)
v = 0
v |= uint16(v1) << 0
v |= uint16(v0) << 8
return v
}
func swap32(v uint32) uint32 {
v0 := byte(v >> 0)
v1 := byte(v >> 8)
v2 := byte(v >> 16)
v3 := byte(v >> 24)
v = 0
v |= uint32(v3) << 0
v |= uint32(v2) << 8
v |= uint32(v1) << 16
v |= uint32(v0) << 24
return v
}
func swap64(v uint64) uint64 {
v0 := byte(v >> 0)
v1 := byte(v >> 8)
v2 := byte(v >> 16)
v3 := byte(v >> 24)
v4 := byte(v >> 32)
v5 := byte(v >> 40)
v6 := byte(v >> 48)
v7 := byte(v >> 56)
v = 0
v |= uint64(v7) << 0
v |= uint64(v6) << 8
v |= uint64(v5) << 16
v |= uint64(v4) << 24
v |= uint64(v3) << 32
v |= uint64(v2) << 40
v |= uint64(v1) << 48
v |= uint64(v0) << 56
return v
}
func mutateData(r *randGen, data []byte) []byte {
const maxInc = 35
for stop := false; !stop; stop = r.bin() {
r.choose(
1, func() {
100, func() {
// Append byte.
data = append(data, byte(r.rand(256)))
},
1, func() {
if len(data) == 0 {
return
}
data[r.Intn(len(data))] = byte(r.rand(256))
},
1, func() {
if len(data) == 0 {
return
}
byt := r.Intn(len(data))
bit := r.Intn(8)
data[byt] ^= 1 << uint(bit)
},
1, func() {
100, func() {
// Remove byte.
if len(data) == 0 {
return
}
@ -408,6 +441,137 @@ func mutateData(r *randGen, data []byte) []byte {
copy(data[i:], data[i+1:])
data = data[:len(data)-1]
},
100, func() {
// Replace byte with random value.
if len(data) == 0 {
return
}
data[r.Intn(len(data))] = byte(r.rand(256))
},
100, func() {
// Flip bit in byte.
if len(data) == 0 {
return
}
byt := r.Intn(len(data))
bit := r.Intn(8)
data[byt] ^= 1 << uint(bit)
},
100, func() {
// Swap two bytes.
if len(data) < 2 {
return
}
i1 := r.Intn(len(data))
i2 := r.Intn(len(data))
data[i1], data[i2] = data[i2], data[i1]
},
100, func() {
// Add / subtract from a byte.
if len(data) == 0 {
return
}
i := r.Intn(len(data))
delta := byte(r.rand(2*maxInc+1) - maxInc)
if delta == 0 {
delta = 1
}
data[i] += delta
},
100, func() {
// Add / subtract from a uint16.
if len(data) < 2 {
return
}
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.bin() {
*p += delta
} else {
*p = swap16(swap16(*p) + delta)
}
},
100, func() {
// Add / subtract from a uint32.
if len(data) < 4 {
return
}
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.bin() {
*p += delta
} else {
*p = swap32(swap32(*p) + delta)
}
},
100, func() {
// Add / subtract from a uint64.
if len(data) < 8 {
return
}
i := r.Intn(len(data) - 7)
p := (*uint64)(unsafe.Pointer(&data[i]))
delta := uint64(r.rand(2*maxInc+1) - maxInc)
if delta == 0 {
delta = 1
}
if r.bin() {
*p += delta
} else {
*p = swap64(swap64(*p) + delta)
}
},
100, func() {
// Set byte to an interesting value.
if len(data) == 0 {
return
}
data[r.Intn(len(data))] = byte(r.randInt())
},
100, func() {
// Set uint16 to an interesting value.
if len(data) < 2 {
return
}
i := r.Intn(len(data) - 1)
value := uint16(r.randInt())
if r.bin() {
value = swap16(value)
}
*(*uint16)(unsafe.Pointer(&data[i])) = value
},
100, func() {
// Set uint32 to an interesting value.
if len(data) < 4 {
return
}
i := r.Intn(len(data) - 3)
value := uint32(r.randInt())
if r.bin() {
value = swap32(value)
}
*(*uint32)(unsafe.Pointer(&data[i])) = value
},
100, func() {
// Set uint64 to an interesting value.
if len(data) < 8 {
return
}
i := r.Intn(len(data) - 7)
value := uint64(r.randInt())
if r.bin() {
value = swap64(value)
}
*(*uint64)(unsafe.Pointer(&data[i])) = value
},
)
}
return data