mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-26 21:00:30 +00:00
parent
58ae5e1862
commit
a4d38b39a8
@ -62,7 +62,7 @@ func testTarget(t *testing.T, target *prog.Target, full bool) {
|
|||||||
}
|
}
|
||||||
rs := rand.NewSource(seed)
|
rs := rand.NewSource(seed)
|
||||||
t.Logf("seed=%v", seed)
|
t.Logf("seed=%v", seed)
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, target.DefaultChoiceTable())
|
||||||
// Turns out that fully minimized program can trigger new interesting warnings,
|
// Turns out that fully minimized program can trigger new interesting warnings,
|
||||||
// e.g. about NULL arguments for functions that require non-NULL arguments in syz_ functions.
|
// e.g. about NULL arguments for functions that require non-NULL arguments in syz_ functions.
|
||||||
// We could append both AllSyzProg as-is and a minimized version of it,
|
// We could append both AllSyzProg as-is and a minimized version of it,
|
||||||
@ -166,7 +166,7 @@ func TestSysTests(t *testing.T) {
|
|||||||
func TestExecutorMacros(t *testing.T) {
|
func TestExecutorMacros(t *testing.T) {
|
||||||
// Ensure that executor does not mis-spell any of the SYZ_* macros.
|
// Ensure that executor does not mis-spell any of the SYZ_* macros.
|
||||||
target, _ := prog.GetTarget("test", "64")
|
target, _ := prog.GetTarget("test", "64")
|
||||||
p := target.Generate(rand.NewSource(0), 1, nil)
|
p := target.Generate(rand.NewSource(0), 1, target.DefaultChoiceTable())
|
||||||
expected := commonDefines(p, Options{})
|
expected := commonDefines(p, Options{})
|
||||||
expected["SYZ_EXECUTOR"] = true
|
expected["SYZ_EXECUTOR"] = true
|
||||||
expected["SYZ_HAVE_SETUP_LOOP"] = true
|
expected["SYZ_HAVE_SETUP_LOOP"] = true
|
||||||
|
@ -21,38 +21,44 @@ func DetectSupportedSyscalls(target *prog.Target, sandbox string) (
|
|||||||
for _, c := range target.Syscalls {
|
for _, c := range target.Syscalls {
|
||||||
supported[c] = true
|
supported[c] = true
|
||||||
}
|
}
|
||||||
return supported, unsupported, nil
|
} else {
|
||||||
}
|
for _, c := range target.Syscalls {
|
||||||
for _, c := range target.Syscalls {
|
ok, reason := false, ""
|
||||||
ok, reason := false, ""
|
switch c.CallName {
|
||||||
switch c.CallName {
|
case "syz_execute_func":
|
||||||
case "syz_execute_func":
|
// syz_execute_func caused multiple problems:
|
||||||
// syz_execute_func caused multiple problems:
|
// 1. First it lead to corpus exploision. The program used existing values in registers
|
||||||
// 1. First it lead to corpus exploision. The program used existing values in registers
|
// to pollute output area. We tried to zero registers (though, not reliably).
|
||||||
// to pollute output area. We tried to zero registers (though, not reliably).
|
// 2. It lead to explosion again. The exact mechanics are unknown, here is one sample:
|
||||||
// 2. It lead to explosion again. The exact mechanics are unknown, here is one sample:
|
// syz_execute_func(&(0x7f0000000440)="f2af91930f0124eda133fa20430fbafce842f66188d0d4
|
||||||
// syz_execute_func(&(0x7f0000000440)="f2af91930f0124eda133fa20430fbafce842f66188d0d4
|
// 430fc7f314c1ab5bf9e2f9660f3a0fae5e090000ba023c1fb63ac4817d73d74ec482310d46f44
|
||||||
// 430fc7f314c1ab5bf9e2f9660f3a0fae5e090000ba023c1fb63ac4817d73d74ec482310d46f44
|
// 9f216c863fa438036a91bdbae95aaaa420f383c02c401405c6bfd49d768d768f833fefbab6464
|
||||||
// 9f216c863fa438036a91bdbae95aaaa420f383c02c401405c6bfd49d768d768f833fefbab6464
|
// 660f38323c8f26dbc1a1fe5ff6f6df0804f4c4efa59c0f01c4288ba6452e000054c4431d5cc100")
|
||||||
// 660f38323c8f26dbc1a1fe5ff6f6df0804f4c4efa59c0f01c4288ba6452e000054c4431d5cc100")
|
// 3. The code can also execute syscalls (and it is know to), but it's not subject to
|
||||||
// 3. The code can also execute syscalls (and it is know to), but it's not subject to
|
// target.SanitizeCall. As the result it can do things that programs are not supposed to do.
|
||||||
// target.SanitizeCall. As the result it can do things that programs are not supposed to do.
|
// 4. Besides linux, corpus explosion also happens on freebsd and is clearly attributable
|
||||||
// 4. Besides linux, corpus explosion also happens on freebsd and is clearly attributable
|
// to syz_execute_func based on corpus contents. Mechanics are also not known.
|
||||||
// to syz_execute_func based on corpus contents. Mechanics are also not known.
|
// It also did not cause finding of any new bugs (at least not that I know of).
|
||||||
// It also did not cause finding of any new bugs (at least not that I know of).
|
// Let's disable it for now until we figure out how to resolve all these problems.
|
||||||
// Let's disable it for now until we figure out how to resolve all these problems.
|
ok = false
|
||||||
ok = false
|
reason = "always disabled for now"
|
||||||
reason = "always disabled for now"
|
default:
|
||||||
default:
|
ok, reason = isSupported(c, target, sandbox)
|
||||||
ok, reason = isSupported(c, target, sandbox)
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
supported[c] = true
|
|
||||||
} else {
|
|
||||||
if reason == "" {
|
|
||||||
reason = "unknown"
|
|
||||||
}
|
}
|
||||||
unsupported[c] = reason
|
if ok {
|
||||||
|
supported[c] = true
|
||||||
|
} else {
|
||||||
|
if reason == "" {
|
||||||
|
reason = "unknown"
|
||||||
|
}
|
||||||
|
unsupported[c] = reason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for c := range supported {
|
||||||
|
if c.Attrs.Disabled {
|
||||||
|
delete(supported, c)
|
||||||
|
unsupported[c] = "has disabled attribute in descriptions"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return supported, unsupported, nil
|
return supported, unsupported, nil
|
||||||
|
@ -216,6 +216,11 @@ func ParseEnabledSyscalls(target *prog.Target, enabled, disabled []string) ([]in
|
|||||||
syscalls[call.ID] = true
|
syscalls[call.ID] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for call := range syscalls {
|
||||||
|
if target.Syscalls[call].Attrs.Disabled {
|
||||||
|
delete(syscalls, call)
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, c := range disabled {
|
for _, c := range disabled {
|
||||||
n := 0
|
n := 0
|
||||||
for _, call := range target.Syscalls {
|
for _, call := range target.Syscalls {
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
func TestIsComplexPtr(t *testing.T) {
|
func TestIsComplexPtr(t *testing.T) {
|
||||||
target, rs, _ := initRandomTargetTest(t, "linux", "amd64")
|
target, rs, _ := initRandomTargetTest(t, "linux", "amd64")
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
iters := 10
|
iters := 10
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
iters = 1
|
iters = 1
|
||||||
@ -19,8 +20,11 @@ func TestIsComplexPtr(t *testing.T) {
|
|||||||
r := newRand(target, rs)
|
r := newRand(target, rs)
|
||||||
compl := make(map[string]bool)
|
compl := make(map[string]bool)
|
||||||
for _, meta := range target.Syscalls {
|
for _, meta := range target.Syscalls {
|
||||||
|
if meta.Attrs.Disabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
s := newState(target, nil, nil)
|
s := newState(target, ct, nil)
|
||||||
calls := r.generateParticularCall(s, meta)
|
calls := r.generateParticularCall(s, meta)
|
||||||
p := &Prog{Target: target, Calls: calls}
|
p := &Prog{Target: target, Calls: calls}
|
||||||
for _, arg := range p.complexPtrs() {
|
for _, arg := range p.complexPtrs() {
|
||||||
|
@ -12,13 +12,14 @@ import (
|
|||||||
|
|
||||||
func TestChecksumCalcRandom(t *testing.T) {
|
func TestChecksumCalcRandom(t *testing.T) {
|
||||||
target, rs, iters := InitTest(t)
|
target, rs, iters := InitTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
for _, call := range p.Calls {
|
for _, call := range p.Calls {
|
||||||
CalcChecksumsCall(call)
|
CalcChecksumsCall(call)
|
||||||
}
|
}
|
||||||
for try := 0; try <= 10; try++ {
|
for try := 0; try <= 10; try++ {
|
||||||
p.Mutate(rs, 10, nil, nil)
|
p.Mutate(rs, 10, ct, nil)
|
||||||
for _, call := range p.Calls {
|
for _, call := range p.Calls {
|
||||||
CalcChecksumsCall(call)
|
CalcChecksumsCall(call)
|
||||||
}
|
}
|
||||||
|
@ -114,9 +114,10 @@ func TestCallSet(t *testing.T) {
|
|||||||
|
|
||||||
func TestCallSetRandom(t *testing.T) {
|
func TestCallSetRandom(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
const ncalls = 10
|
const ncalls = 10
|
||||||
p := target.Generate(rs, ncalls, nil)
|
p := target.Generate(rs, ncalls, ct)
|
||||||
calls0 := make(map[string]struct{})
|
calls0 := make(map[string]struct{})
|
||||||
for _, c := range p.Calls {
|
for _, c := range p.Calls {
|
||||||
calls0[c.Meta.Name] = struct{}{}
|
calls0[c.Meta.Name] = struct{}{}
|
||||||
@ -328,10 +329,11 @@ func TestSerializeDeserialize(t *testing.T) {
|
|||||||
|
|
||||||
func TestSerializeDeserializeRandom(t *testing.T) {
|
func TestSerializeDeserializeRandom(t *testing.T) {
|
||||||
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
data0 := make([]byte, ExecBufferSize)
|
data0 := make([]byte, ExecBufferSize)
|
||||||
data1 := make([]byte, ExecBufferSize)
|
data1 := make([]byte, ExecBufferSize)
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p0 := target.Generate(rs, 10, nil)
|
p0 := target.Generate(rs, 10, ct)
|
||||||
if ok, _, _ := testSerializeDeserialize(t, p0, data0, data1); ok {
|
if ok, _, _ := testSerializeDeserialize(t, p0, data0, data1); ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,10 @@ import (
|
|||||||
|
|
||||||
func TestSerializeForExecRandom(t *testing.T) {
|
func TestSerializeForExecRandom(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
buf := make([]byte, ExecBufferSize)
|
buf := make([]byte, ExecBufferSize)
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
n, err := p.SerializeForExec(buf)
|
n, err := p.SerializeForExec(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to serialize: %v", err)
|
t.Fatalf("failed to serialize: %v", err)
|
||||||
|
@ -478,10 +478,11 @@ func TestHintsShrinkExpand(t *testing.T) {
|
|||||||
|
|
||||||
func TestHintsRandom(t *testing.T) {
|
func TestHintsRandom(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
iters /= 10 // the test takes long
|
iters /= 10 // the test takes long
|
||||||
r := newRand(target, rs)
|
r := newRand(target, rs)
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 5, nil)
|
p := target.Generate(rs, 5, ct)
|
||||||
for i, c := range p.Calls {
|
for i, c := range p.Calls {
|
||||||
vals := extractValues(c)
|
vals := extractValues(c)
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
@ -570,7 +571,8 @@ func BenchmarkHints(b *testing.B) {
|
|||||||
defer cleanup()
|
defer cleanup()
|
||||||
rs := rand.NewSource(0)
|
rs := rand.NewSource(0)
|
||||||
r := newRand(target, rs)
|
r := newRand(target, rs)
|
||||||
p := target.Generate(rs, 30, nil)
|
ct := target.DefaultChoiceTable()
|
||||||
|
p := target.Generate(rs, 30, ct)
|
||||||
comps := make([]CompMap, len(p.Calls))
|
comps := make([]CompMap, len(p.Calls))
|
||||||
for i, c := range p.Calls {
|
for i, c := range p.Calls {
|
||||||
vals := extractValues(c)
|
vals := extractValues(c)
|
||||||
|
@ -176,10 +176,11 @@ func TestMinimize(t *testing.T) {
|
|||||||
func TestMinimizeRandom(t *testing.T) {
|
func TestMinimizeRandom(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
iters /= 10 // Long test.
|
iters /= 10 // Long test.
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
r := rand.New(rs)
|
r := rand.New(rs)
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
for _, crash := range []bool{false, true} {
|
for _, crash := range []bool{false, true} {
|
||||||
p := target.Generate(rs, 5, nil)
|
p := target.Generate(rs, 5, ct)
|
||||||
copyP := p.Clone()
|
copyP := p.Clone()
|
||||||
minP, _ := Minimize(p, len(p.Calls)-1, crash, func(p1 *Prog, callIndex int) bool {
|
minP, _ := Minimize(p, len(p.Calls)-1, crash, func(p1 *Prog, callIndex int) bool {
|
||||||
if r.Intn(2) == 0 {
|
if r.Intn(2) == 0 {
|
||||||
@ -199,9 +200,10 @@ func TestMinimizeRandom(t *testing.T) {
|
|||||||
|
|
||||||
func TestMinimizeCallIndex(t *testing.T) {
|
func TestMinimizeCallIndex(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
r := rand.New(rs)
|
r := rand.New(rs)
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 5, nil)
|
p := target.Generate(rs, 5, ct)
|
||||||
ci := r.Intn(len(p.Calls))
|
ci := r.Intn(len(p.Calls))
|
||||||
p1, ci1 := Minimize(p, ci, r.Intn(2) == 0, func(p1 *Prog, callIndex int) bool {
|
p1, ci1 := Minimize(p, ci, r.Intn(2) == 0, func(p1 *Prog, callIndex int) bool {
|
||||||
return r.Intn(2) == 0
|
return r.Intn(2) == 0
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -155,9 +154,9 @@ func TestMutateArgument(t *testing.T) {
|
|||||||
func TestSizeMutateArg(t *testing.T) {
|
func TestSizeMutateArg(t *testing.T) {
|
||||||
target, rs, iters := initRandomTargetTest(t, "test", "64")
|
target, rs, iters := initRandomTargetTest(t, "test", "64")
|
||||||
r := newRand(target, rs)
|
r := newRand(target, rs)
|
||||||
ct := target.BuildChoiceTable(nil, nil)
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
for it := 0; it < iters; it++ {
|
for it := 0; it < iters; it++ {
|
||||||
p1 := p.Clone()
|
p1 := p.Clone()
|
||||||
ctx := &mutator{
|
ctx := &mutator{
|
||||||
@ -217,8 +216,9 @@ func TestRandomChoice(t *testing.T) {
|
|||||||
|
|
||||||
func TestClone(t *testing.T) {
|
func TestClone(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
p1 := p.Clone()
|
p1 := p.Clone()
|
||||||
data := p.Serialize()
|
data := p.Serialize()
|
||||||
data1 := p1.Serialize()
|
data1 := p1.Serialize()
|
||||||
@ -230,15 +230,16 @@ func TestClone(t *testing.T) {
|
|||||||
|
|
||||||
func TestMutateRandom(t *testing.T) {
|
func TestMutateRandom(t *testing.T) {
|
||||||
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
next:
|
next:
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
data0 := p.Serialize()
|
data0 := p.Serialize()
|
||||||
p1 := p.Clone()
|
p1 := p.Clone()
|
||||||
// There is a chance that mutation will produce the same program.
|
// There is a chance that mutation will produce the same program.
|
||||||
// So we check that at least 1 out of 20 mutations actually change the program.
|
// So we check that at least 1 out of 20 mutations actually change the program.
|
||||||
for try := 0; try < 20; try++ {
|
for try := 0; try < 20; try++ {
|
||||||
p1.Mutate(rs, 10, nil, nil)
|
p1.Mutate(rs, 10, ct, nil)
|
||||||
data := p.Serialize()
|
data := p.Serialize()
|
||||||
if !bytes.Equal(data0, data) {
|
if !bytes.Equal(data0, data) {
|
||||||
t.Fatalf("program changed after mutate\noriginal:\n%s\n\nnew:\n%s\n",
|
t.Fatalf("program changed after mutate\noriginal:\n%s\n\nnew:\n%s\n",
|
||||||
@ -260,14 +261,15 @@ func TestMutateRandom(t *testing.T) {
|
|||||||
|
|
||||||
func TestMutateCorpus(t *testing.T) {
|
func TestMutateCorpus(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
var corpus []*Prog
|
var corpus []*Prog
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
corpus = append(corpus, p)
|
corpus = append(corpus, p)
|
||||||
}
|
}
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p1 := target.Generate(rs, 10, nil)
|
p1 := target.Generate(rs, 10, ct)
|
||||||
p1.Mutate(rs, 10, nil, corpus)
|
p1.Mutate(rs, 10, ct, corpus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,9 +404,9 @@ mutate_rangedbuffer(&(0x7f00000000c0)=""/11)
|
|||||||
func BenchmarkMutate(b *testing.B) {
|
func BenchmarkMutate(b *testing.B) {
|
||||||
target, cleanup := initBench(b)
|
target, cleanup := initBench(b)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
ct := linuxAmd64ChoiceTable(target)
|
ct := target.DefaultChoiceTable()
|
||||||
const progLen = 30
|
const progLen = 30
|
||||||
p := target.Generate(rand.NewSource(0), progLen, nil)
|
p := target.Generate(rand.NewSource(0), progLen, ct)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
rs := rand.NewSource(0)
|
rs := rand.NewSource(0)
|
||||||
@ -417,7 +419,7 @@ func BenchmarkMutate(b *testing.B) {
|
|||||||
func BenchmarkGenerate(b *testing.B) {
|
func BenchmarkGenerate(b *testing.B) {
|
||||||
target, cleanup := initBench(b)
|
target, cleanup := initBench(b)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
ct := linuxAmd64ChoiceTable(target)
|
ct := target.DefaultChoiceTable()
|
||||||
const progLen = 30
|
const progLen = 30
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
@ -428,18 +430,6 @@ func BenchmarkGenerate(b *testing.B) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
linuxCTOnce sync.Once
|
|
||||||
linuxCT *ChoiceTable
|
|
||||||
)
|
|
||||||
|
|
||||||
func linuxAmd64ChoiceTable(target *Target) *ChoiceTable {
|
|
||||||
linuxCTOnce.Do(func() {
|
|
||||||
linuxCT = target.BuildChoiceTable(target.CalculatePriorities(nil), nil)
|
|
||||||
})
|
|
||||||
return linuxCT
|
|
||||||
}
|
|
||||||
|
|
||||||
func runMutationTests(t *testing.T, tests [][2]string, valid bool) {
|
func runMutationTests(t *testing.T, tests [][2]string, valid bool) {
|
||||||
target := initTargetTest(t, "test", "64")
|
target := initTargetTest(t, "test", "64")
|
||||||
for ti, test := range tests {
|
for ti, test := range tests {
|
||||||
|
77
prog/prio.go
77
prog/prio.go
@ -26,13 +26,15 @@ import (
|
|||||||
|
|
||||||
func (target *Target) CalculatePriorities(corpus []*Prog) [][]float32 {
|
func (target *Target) CalculatePriorities(corpus []*Prog) [][]float32 {
|
||||||
static := target.calcStaticPriorities()
|
static := target.calcStaticPriorities()
|
||||||
dynamic := target.calcDynamicPrio(corpus)
|
if len(corpus) != 0 {
|
||||||
for i, prios := range static {
|
dynamic := target.calcDynamicPrio(corpus)
|
||||||
for j, p := range prios {
|
for i, prios := range dynamic {
|
||||||
dynamic[i][j] *= p
|
for j, p := range prios {
|
||||||
|
static[i][j] *= p
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dynamic
|
return static
|
||||||
}
|
}
|
||||||
|
|
||||||
func (target *Target) calcStaticPriorities() [][]float32 {
|
func (target *Target) calcStaticPriorities() [][]float32 {
|
||||||
@ -200,29 +202,41 @@ func normalizePrio(prios [][]float32) {
|
|||||||
// ChooseTable allows to do a weighted choice of a syscall for a given syscall
|
// ChooseTable allows to do a weighted choice of a syscall for a given syscall
|
||||||
// based on call-to-call priorities and a set of enabled syscalls.
|
// based on call-to-call priorities and a set of enabled syscalls.
|
||||||
type ChoiceTable struct {
|
type ChoiceTable struct {
|
||||||
target *Target
|
target *Target
|
||||||
run [][]int
|
runs [][]int
|
||||||
enabledCalls []*Syscall
|
calls []*Syscall
|
||||||
enabled map[*Syscall]bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (target *Target) BuildChoiceTable(prios [][]float32, enabled map[*Syscall]bool) *ChoiceTable {
|
func (target *Target) BuildChoiceTable(corpus []*Prog, enabled map[*Syscall]bool) *ChoiceTable {
|
||||||
if enabled == nil {
|
if enabled == nil {
|
||||||
enabled = make(map[*Syscall]bool)
|
enabled = make(map[*Syscall]bool)
|
||||||
for _, c := range target.Syscalls {
|
for _, c := range target.Syscalls {
|
||||||
enabled[c] = true
|
enabled[c] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for call := range enabled {
|
||||||
|
if call.Attrs.Disabled {
|
||||||
|
delete(enabled, call)
|
||||||
|
}
|
||||||
|
}
|
||||||
var enabledCalls []*Syscall
|
var enabledCalls []*Syscall
|
||||||
for c := range enabled {
|
for c := range enabled {
|
||||||
enabledCalls = append(enabledCalls, c)
|
enabledCalls = append(enabledCalls, c)
|
||||||
}
|
}
|
||||||
if len(enabledCalls) == 0 {
|
if len(enabledCalls) == 0 {
|
||||||
panic(fmt.Sprintf("empty enabledCalls, len(target.Syscalls)=%v", len(target.Syscalls)))
|
panic("no syscalls enabled")
|
||||||
}
|
}
|
||||||
sort.Slice(enabledCalls, func(i, j int) bool {
|
sort.Slice(enabledCalls, func(i, j int) bool {
|
||||||
return enabledCalls[i].ID < enabledCalls[j].ID
|
return enabledCalls[i].ID < enabledCalls[j].ID
|
||||||
})
|
})
|
||||||
|
for _, p := range corpus {
|
||||||
|
for _, call := range p.Calls {
|
||||||
|
if !enabled[call.Meta] {
|
||||||
|
panic(fmt.Sprintf("corpus contains disabled syscall %v", call.Meta.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prios := target.CalculatePriorities(corpus)
|
||||||
run := make([][]int, len(target.Syscalls))
|
run := make([][]int, len(target.Syscalls))
|
||||||
for i := range run {
|
for i := range run {
|
||||||
if !enabled[target.Syscalls[i]] {
|
if !enabled[target.Syscalls[i]] {
|
||||||
@ -232,31 +246,30 @@ func (target *Target) BuildChoiceTable(prios [][]float32, enabled map[*Syscall]b
|
|||||||
sum := 0
|
sum := 0
|
||||||
for j := range run[i] {
|
for j := range run[i] {
|
||||||
if enabled[target.Syscalls[j]] {
|
if enabled[target.Syscalls[j]] {
|
||||||
w := 1
|
sum += int(prios[i][j] * 1000)
|
||||||
if prios != nil {
|
|
||||||
w = int(prios[i][j] * 1000)
|
|
||||||
}
|
|
||||||
sum += w
|
|
||||||
}
|
}
|
||||||
run[i][j] = sum
|
run[i][j] = sum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &ChoiceTable{target, run, enabledCalls, enabled}
|
return &ChoiceTable{target, run, enabledCalls}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *ChoiceTable) Choose(r *rand.Rand, call int) int {
|
func (ct *ChoiceTable) enabled(call int) bool {
|
||||||
if call < 0 {
|
return ct.runs[call] != nil
|
||||||
return ct.enabledCalls[r.Intn(len(ct.enabledCalls))].ID
|
}
|
||||||
}
|
|
||||||
run := ct.run[call]
|
func (ct *ChoiceTable) choose(r *rand.Rand, bias int) int {
|
||||||
if run == nil {
|
if bias < 0 {
|
||||||
return ct.enabledCalls[r.Intn(len(ct.enabledCalls))].ID
|
bias = ct.calls[r.Intn(len(ct.calls))].ID
|
||||||
}
|
}
|
||||||
for {
|
if !ct.enabled(bias) {
|
||||||
x := r.Intn(run[len(run)-1]) + 1
|
panic("bias to disabled syscall")
|
||||||
i := sort.SearchInts(run, x)
|
}
|
||||||
if ct.enabled[ct.target.Syscalls[i]] {
|
run := ct.runs[bias]
|
||||||
return i
|
x := r.Intn(run[len(run)-1]) + 1
|
||||||
}
|
res := sort.SearchInts(run, x)
|
||||||
}
|
if !ct.enabled(res) {
|
||||||
|
panic("selected disabled syscall")
|
||||||
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ import (
|
|||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNormalizePrio(t *testing.T) {
|
func TestNormalizePrio(t *testing.T) {
|
||||||
@ -30,36 +28,6 @@ func TestNormalizePrio(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestPrioChoice tests that we select all syscalls with equal probability.
|
|
||||||
func TestPrioChoice(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
target := &Target{
|
|
||||||
Syscalls: []*Syscall{
|
|
||||||
{ID: 0},
|
|
||||||
{ID: 1},
|
|
||||||
{ID: 2},
|
|
||||||
{ID: 3},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
prios := [][]float32{
|
|
||||||
{1, 1, 1, 1},
|
|
||||||
{1, 1, 1, 1},
|
|
||||||
{1, 1, 1, 1},
|
|
||||||
{1, 1, 1, 1},
|
|
||||||
}
|
|
||||||
ct := target.BuildChoiceTable(prios, nil)
|
|
||||||
r := rand.New(rand.NewSource(0))
|
|
||||||
var res [4]int
|
|
||||||
for i := 0; i < 10000; i++ {
|
|
||||||
res[ct.Choose(r, 0)]++
|
|
||||||
}
|
|
||||||
// If this fails too frequently we can do some ranges, but for now it's just hardcoded.
|
|
||||||
want := [4]int{2552, 2459, 2491, 2498}
|
|
||||||
if diff := cmp.Diff(res, want); diff != "" {
|
|
||||||
t.Fatal(diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test static priorities assigned based on argument direction.
|
// Test static priorities assigned based on argument direction.
|
||||||
func TestStaticPriorities(t *testing.T) {
|
func TestStaticPriorities(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
@ -73,7 +41,7 @@ func TestStaticPriorities(t *testing.T) {
|
|||||||
{"open", "read", "write", "mmap"},
|
{"open", "read", "write", "mmap"},
|
||||||
{"socket", "listen", "setsockopt"},
|
{"socket", "listen", "setsockopt"},
|
||||||
}
|
}
|
||||||
ct := target.BuildChoiceTable(target.CalculatePriorities(nil), nil)
|
ct := target.DefaultChoiceTable()
|
||||||
r := rand.New(rs)
|
r := rand.New(rs)
|
||||||
for _, syscalls := range tests {
|
for _, syscalls := range tests {
|
||||||
// Counts the number of times a call is chosen after a call that creates a resource (referenceCall).
|
// Counts the number of times a call is chosen after a call that creates a resource (referenceCall).
|
||||||
@ -82,7 +50,7 @@ func TestStaticPriorities(t *testing.T) {
|
|||||||
for _, call := range syscalls {
|
for _, call := range syscalls {
|
||||||
count := 0
|
count := 0
|
||||||
for it := 0; it < iters*10000; it++ {
|
for it := 0; it < iters*10000; it++ {
|
||||||
chosenCall := target.Syscalls[ct.Choose(r, target.SyscallMap[call].ID)].Name
|
chosenCall := target.Syscalls[ct.choose(r, target.SyscallMap[call].ID)].Name
|
||||||
if call == referenceCall {
|
if call == referenceCall {
|
||||||
counter[chosenCall]++
|
counter[chosenCall]++
|
||||||
} else if chosenCall == referenceCall {
|
} else if chosenCall == referenceCall {
|
||||||
|
@ -13,8 +13,9 @@ import (
|
|||||||
|
|
||||||
func TestGeneration(t *testing.T) {
|
func TestGeneration(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
target.Generate(rs, 20, nil)
|
target.Generate(rs, 20, ct)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +33,9 @@ func TestDefault(t *testing.T) {
|
|||||||
func TestDefaultCallArgs(t *testing.T) {
|
func TestDefaultCallArgs(t *testing.T) {
|
||||||
target, _, _ := initTest(t)
|
target, _, _ := initTest(t)
|
||||||
for _, meta := range target.SyscallMap {
|
for _, meta := range target.SyscallMap {
|
||||||
|
if meta.Attrs.Disabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
// Ensure that we can restore all arguments of all calls.
|
// Ensure that we can restore all arguments of all calls.
|
||||||
prog := fmt.Sprintf("%v()", meta.Name)
|
prog := fmt.Sprintf("%v()", meta.Name)
|
||||||
p, err := target.Deserialize([]byte(prog), NonStrict)
|
p, err := target.Deserialize([]byte(prog), NonStrict)
|
||||||
@ -46,8 +50,9 @@ func TestDefaultCallArgs(t *testing.T) {
|
|||||||
|
|
||||||
func testSerialize(t *testing.T, verbose bool) {
|
func testSerialize(t *testing.T, verbose bool) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
var data []byte
|
var data []byte
|
||||||
mode := NonStrict
|
mode := NonStrict
|
||||||
if verbose {
|
if verbose {
|
||||||
@ -88,11 +93,12 @@ func TestSerializeVerbose(t *testing.T) {
|
|||||||
|
|
||||||
func TestVmaType(t *testing.T) {
|
func TestVmaType(t *testing.T) {
|
||||||
target, rs, iters := initRandomTargetTest(t, "test", "64")
|
target, rs, iters := initRandomTargetTest(t, "test", "64")
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
meta := target.SyscallMap["test$vma0"]
|
meta := target.SyscallMap["test$vma0"]
|
||||||
r := newRand(target, rs)
|
r := newRand(target, rs)
|
||||||
pageSize := target.PageSize
|
pageSize := target.PageSize
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
s := newState(target, nil, nil)
|
s := newState(target, ct, nil)
|
||||||
calls := r.generateParticularCall(s, meta)
|
calls := r.generateParticularCall(s, meta)
|
||||||
c := calls[len(calls)-1]
|
c := calls[len(calls)-1]
|
||||||
if c.Meta.Name != "test$vma0" {
|
if c.Meta.Name != "test$vma0" {
|
||||||
@ -161,20 +167,21 @@ func TestCrossTarget(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCrossTarget(t *testing.T, target *Target, crossTargets []*Target) {
|
func testCrossTarget(t *testing.T, target *Target, crossTargets []*Target) {
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
rs := randSource(t)
|
rs := randSource(t)
|
||||||
iters := 100
|
iters := 100
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
iters /= 10
|
iters /= 10
|
||||||
}
|
}
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 20, nil)
|
p := target.Generate(rs, 20, ct)
|
||||||
testCrossArchProg(t, p, crossTargets)
|
testCrossArchProg(t, p, crossTargets)
|
||||||
p, err := target.Deserialize(p.Serialize(), NonStrict)
|
p, err := target.Deserialize(p.Serialize(), NonStrict)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
testCrossArchProg(t, p, crossTargets)
|
testCrossArchProg(t, p, crossTargets)
|
||||||
p.Mutate(rs, 20, nil, nil)
|
p.Mutate(rs, 20, ct, nil)
|
||||||
testCrossArchProg(t, p, crossTargets)
|
testCrossArchProg(t, p, crossTargets)
|
||||||
p, _ = Minimize(p, -1, false, func(*Prog, int) bool {
|
p, _ = Minimize(p, -1, false, func(*Prog, int) bool {
|
||||||
return rs.Int63()%2 == 0
|
return rs.Int63()%2 == 0
|
||||||
@ -197,6 +204,8 @@ func testCrossArchProg(t *testing.T, p *Prog, crossTargets []*Target) {
|
|||||||
|
|
||||||
func TestSpecialStructs(t *testing.T) {
|
func TestSpecialStructs(t *testing.T) {
|
||||||
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
||||||
|
_ = target.GenerateAllSyzProg(rs)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for special, gen := range target.SpecialTypes {
|
for special, gen := range target.SpecialTypes {
|
||||||
t.Run(special, func(t *testing.T) {
|
t.Run(special, func(t *testing.T) {
|
||||||
var typ Type
|
var typ Type
|
||||||
@ -216,7 +225,7 @@ func TestSpecialStructs(t *testing.T) {
|
|||||||
if typ == nil {
|
if typ == nil {
|
||||||
t.Fatal("can't find struct description")
|
t.Fatal("can't find struct description")
|
||||||
}
|
}
|
||||||
g := &Gen{newRand(target, rs), newState(target, nil, nil)}
|
g := &Gen{newRand(target, rs), newState(target, ct, nil)}
|
||||||
for i := 0; i < iters/len(target.SpecialTypes); i++ {
|
for i := 0; i < iters/len(target.SpecialTypes); i++ {
|
||||||
var arg Arg
|
var arg Arg
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
@ -441,8 +450,9 @@ fallback$0()
|
|||||||
|
|
||||||
func TestSanitizeRandom(t *testing.T) {
|
func TestSanitizeRandom(t *testing.T) {
|
||||||
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
testEachTargetRandom(t, func(t *testing.T, target *Target, rs rand.Source, iters int) {
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
s0 := string(p.Serialize())
|
s0 := string(p.Serialize())
|
||||||
p.sanitizeFix()
|
p.sanitizeFix()
|
||||||
s1 := string(p.Serialize())
|
s1 := string(p.Serialize())
|
||||||
|
24
prog/rand.go
24
prog/rand.go
@ -379,10 +379,9 @@ func (r *randGen) createResource(s *state, res *ResourceType, dir Dir) (arg Arg,
|
|||||||
// TODO: reduce priority of less specialized ctors.
|
// TODO: reduce priority of less specialized ctors.
|
||||||
var metas []*Syscall
|
var metas []*Syscall
|
||||||
for _, meta := range metas0 {
|
for _, meta := range metas0 {
|
||||||
if s.ct == nil || s.ct.run[meta.ID] == nil {
|
if s.ct.enabled(meta.ID) {
|
||||||
continue
|
metas = append(metas, meta)
|
||||||
}
|
}
|
||||||
metas = append(metas, meta)
|
|
||||||
}
|
}
|
||||||
if len(metas) == 0 {
|
if len(metas) == 0 {
|
||||||
return res.DefaultArg(dir), nil
|
return res.DefaultArg(dir), nil
|
||||||
@ -537,19 +536,12 @@ func (r *randGen) nOutOf(n, outOf int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *randGen) generateCall(s *state, p *Prog, insertionPoint int) []*Call {
|
func (r *randGen) generateCall(s *state, p *Prog, insertionPoint int) []*Call {
|
||||||
idx := 0
|
biasCall := -1
|
||||||
if s.ct == nil {
|
if insertionPoint > 0 {
|
||||||
idx = r.Intn(len(r.target.Syscalls))
|
// Choosing the base call is based on the insertion point of the new calls sequence.
|
||||||
} else if insertionPoint <= 0 {
|
biasCall = p.Calls[r.Intn(insertionPoint)].Meta.ID
|
||||||
idx = s.ct.enabledCalls[r.Intn(len(s.ct.enabledCalls))].ID
|
|
||||||
} else {
|
|
||||||
call := -1
|
|
||||||
if len(p.Calls) != 0 {
|
|
||||||
// Choosing the base call is based on the insertion point of the new calls sequence.
|
|
||||||
call = p.Calls[r.Intn(insertionPoint)].Meta.ID
|
|
||||||
}
|
|
||||||
idx = s.ct.Choose(r.Rand, call)
|
|
||||||
}
|
}
|
||||||
|
idx := s.ct.choose(r.Rand, biasCall)
|
||||||
meta := r.target.Syscalls[idx]
|
meta := r.target.Syscalls[idx]
|
||||||
return r.generateParticularCall(s, meta)
|
return r.generateParticularCall(s, meta)
|
||||||
}
|
}
|
||||||
@ -573,7 +565,7 @@ func (target *Target) GenerateAllSyzProg(rs rand.Source) *Prog {
|
|||||||
Target: target,
|
Target: target,
|
||||||
}
|
}
|
||||||
r := newRand(target, rs)
|
r := newRand(target, rs)
|
||||||
s := newState(target, nil, nil)
|
s := newState(target, target.DefaultChoiceTable(), nil)
|
||||||
handled := make(map[string]bool)
|
handled := make(map[string]bool)
|
||||||
for _, meta := range target.Syscalls {
|
for _, meta := range target.Syscalls {
|
||||||
if !strings.HasPrefix(meta.CallName, "syz_") || handled[meta.CallName] {
|
if !strings.HasPrefix(meta.CallName, "syz_") || handled[meta.CallName] {
|
||||||
|
@ -31,13 +31,14 @@ func TestNotEscaping(t *testing.T) {
|
|||||||
func TestDeterminism(t *testing.T) {
|
func TestDeterminism(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
iters /= 10 // takes too long
|
iters /= 10 // takes too long
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
var corpus []*Prog
|
var corpus []*Prog
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
seed := rs.Int63()
|
seed := rs.Int63()
|
||||||
rs1 := rand.NewSource(seed)
|
rs1 := rand.NewSource(seed)
|
||||||
p1 := generateProg(t, target, rs1, corpus)
|
p1 := generateProg(t, target, rs1, ct, corpus)
|
||||||
rs2 := rand.NewSource(seed)
|
rs2 := rand.NewSource(seed)
|
||||||
p2 := generateProg(t, target, rs2, corpus)
|
p2 := generateProg(t, target, rs2, ct, corpus)
|
||||||
ps1 := string(p1.Serialize())
|
ps1 := string(p1.Serialize())
|
||||||
ps2 := string(p2.Serialize())
|
ps2 := string(p2.Serialize())
|
||||||
r1 := rs1.Int63()
|
r1 := rs1.Int63()
|
||||||
@ -49,9 +50,9 @@ func TestDeterminism(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateProg(t *testing.T, target *Target, rs rand.Source, corpus []*Prog) *Prog {
|
func generateProg(t *testing.T, target *Target, rs rand.Source, ct *ChoiceTable, corpus []*Prog) *Prog {
|
||||||
p := target.Generate(rs, 5, nil)
|
p := target.Generate(rs, 5, ct)
|
||||||
p.Mutate(rs, 10, nil, corpus)
|
p.Mutate(rs, 10, ct, corpus)
|
||||||
for i, c := range p.Calls {
|
for i, c := range p.Calls {
|
||||||
comps := make(CompMap)
|
comps := make(CompMap)
|
||||||
for v := range extractValues(c) {
|
for v := range extractValues(c) {
|
||||||
|
@ -10,8 +10,9 @@ import (
|
|||||||
|
|
||||||
func TestAssignSizeRandom(t *testing.T) {
|
func TestAssignSizeRandom(t *testing.T) {
|
||||||
target, rs, iters := initTest(t)
|
target, rs, iters := initTest(t)
|
||||||
|
ct := target.DefaultChoiceTable()
|
||||||
for i := 0; i < iters; i++ {
|
for i := 0; i < iters; i++ {
|
||||||
p := target.Generate(rs, 10, nil)
|
p := target.Generate(rs, 10, ct)
|
||||||
data0 := p.Serialize()
|
data0 := p.Serialize()
|
||||||
for _, call := range p.Calls {
|
for _, call := range p.Calls {
|
||||||
target.assignSizesCall(call)
|
target.assignSizesCall(call)
|
||||||
@ -19,7 +20,7 @@ func TestAssignSizeRandom(t *testing.T) {
|
|||||||
if data1 := p.Serialize(); !bytes.Equal(data0, data1) {
|
if data1 := p.Serialize(); !bytes.Equal(data0, data1) {
|
||||||
t.Fatalf("different lens assigned, initial:\n%s\nnew:\n%s\n", data0, data1)
|
t.Fatalf("different lens assigned, initial:\n%s\nnew:\n%s\n", data0, data1)
|
||||||
}
|
}
|
||||||
p.Mutate(rs, 10, nil, nil)
|
p.Mutate(rs, 10, ct, nil)
|
||||||
p.Serialize()
|
p.Serialize()
|
||||||
for _, call := range p.Calls {
|
for _, call := range p.Calls {
|
||||||
target.assignSizesCall(call)
|
target.assignSizesCall(call)
|
||||||
|
@ -65,6 +65,10 @@ type Target struct {
|
|||||||
// Maps resource name to a list of calls that can create the resource.
|
// Maps resource name to a list of calls that can create the resource.
|
||||||
resourceCtors map[string][]*Syscall
|
resourceCtors map[string][]*Syscall
|
||||||
any anyTypes
|
any anyTypes
|
||||||
|
|
||||||
|
// The default ChoiceTable is used only by tests and utilities, so we initialize it lazily.
|
||||||
|
defaultOnce sync.Once
|
||||||
|
defaultChoiceTable *ChoiceTable
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxSpecialPointers = 16
|
const maxSpecialPointers = 16
|
||||||
@ -195,6 +199,13 @@ func restoreLinks(syscalls []*Syscall, resources []*ResourceDesc, types []Type)
|
|||||||
return resourceMap
|
return resourceMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (target *Target) DefaultChoiceTable() *ChoiceTable {
|
||||||
|
target.defaultOnce.Do(func() {
|
||||||
|
target.defaultChoiceTable = target.BuildChoiceTable(nil, nil)
|
||||||
|
})
|
||||||
|
return target.defaultChoiceTable
|
||||||
|
}
|
||||||
|
|
||||||
type Gen struct {
|
type Gen struct {
|
||||||
r *randGen
|
r *randGen
|
||||||
s *state
|
s *state
|
||||||
|
@ -52,7 +52,7 @@ func FuzzDeserialize(data []byte) int {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p3.Mutate(rand.NewSource(0), 3, nil, nil)
|
p3.Mutate(rand.NewSource(0), 3, fuzzChoiceTable, nil)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,11 +64,11 @@ func FuzzParseLog(data []byte) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fuzzBuffer = make([]byte, prog.ExecBufferSize)
|
var fuzzBuffer = make([]byte, prog.ExecBufferSize)
|
||||||
var fuzzTarget = func() *prog.Target {
|
var fuzzTarget, fuzzChoiceTable = func() (*prog.Target, *prog.ChoiceTable) {
|
||||||
prog.Debug()
|
prog.Debug()
|
||||||
target, err := prog.GetTarget("test", "64")
|
target, err := prog.GetTarget("test", "64")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return target
|
return target, target.DefaultChoiceTable()
|
||||||
}()
|
}()
|
||||||
|
@ -50,6 +50,9 @@ func (p *Prog) validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *validCtx) validateCall(c *Call) error {
|
func (ctx *validCtx) validateCall(c *Call) error {
|
||||||
|
if c.Meta.Attrs.Disabled {
|
||||||
|
return fmt.Errorf("use of a disabled call")
|
||||||
|
}
|
||||||
if len(c.Args) != len(c.Meta.Args) {
|
if len(c.Args) != len(c.Meta.Args) {
|
||||||
return fmt.Errorf("wrong number of arguments, want %v, got %v",
|
return fmt.Errorf("wrong number of arguments, want %v, got %v",
|
||||||
len(c.Meta.Args), len(c.Args))
|
len(c.Meta.Args), len(c.Args))
|
||||||
|
@ -797,3 +797,11 @@ auto_struct0 {
|
|||||||
f1 const[0x43, int32]
|
f1 const[0x43, int32]
|
||||||
f2 int32
|
f2 int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Attributes
|
||||||
|
|
||||||
|
resource disabled_resource[int32]
|
||||||
|
|
||||||
|
disabled0() (disabled)
|
||||||
|
disabled1() disabled_resource (disabled)
|
||||||
|
disabled2(a disabled_resource) (disabled)
|
||||||
|
@ -247,8 +247,7 @@ func main() {
|
|||||||
for _, id := range r.CheckResult.EnabledCalls[sandbox] {
|
for _, id := range r.CheckResult.EnabledCalls[sandbox] {
|
||||||
calls[target.Syscalls[id]] = true
|
calls[target.Syscalls[id]] = true
|
||||||
}
|
}
|
||||||
prios := target.CalculatePriorities(fuzzer.corpus)
|
fuzzer.choiceTable = target.BuildChoiceTable(fuzzer.corpus, calls)
|
||||||
fuzzer.choiceTable = target.BuildChoiceTable(prios, calls)
|
|
||||||
|
|
||||||
for pid := 0; pid < *flagProcs; pid++ {
|
for pid := 0; pid < *flagProcs; pid++ {
|
||||||
proc, err := newProc(fuzzer, pid)
|
proc, err := newProc(fuzzer, pid)
|
||||||
|
@ -79,7 +79,7 @@ func TestAddInputConcurrency(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateInput(target *prog.Target, rs rand.Source, ncalls int, sizeSig int) (inp InputTest) {
|
func generateInput(target *prog.Target, rs rand.Source, ncalls int, sizeSig int) (inp InputTest) {
|
||||||
inp.p = target.Generate(rs, ncalls, nil)
|
inp.p = target.Generate(rs, ncalls, target.DefaultChoiceTable())
|
||||||
var raw []uint32
|
var raw []uint32
|
||||||
for i := 1; i <= sizeSig; i++ {
|
for i := 1; i <= sizeSig; i++ {
|
||||||
raw = append(raw, uint32(i))
|
raw = append(raw, uint32(i))
|
||||||
|
@ -64,8 +64,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
rs := rand.NewSource(seed)
|
rs := rand.NewSource(seed)
|
||||||
prios := target.CalculatePriorities(corpus)
|
ct := target.BuildChoiceTable(corpus, syscalls)
|
||||||
ct := target.BuildChoiceTable(prios, syscalls)
|
|
||||||
var p *prog.Prog
|
var p *prog.Prog
|
||||||
if flag.NArg() == 0 {
|
if flag.NArg() == 0 {
|
||||||
p = target.Generate(rs, *flagLen, ct)
|
p = target.Generate(rs, *flagLen, ct)
|
||||||
|
@ -74,8 +74,7 @@ func main() {
|
|||||||
syscalls = strings.Split(*flagSyscalls, ",")
|
syscalls = strings.Split(*flagSyscalls, ",")
|
||||||
}
|
}
|
||||||
calls := buildCallList(target, syscalls)
|
calls := buildCallList(target, syscalls)
|
||||||
prios := target.CalculatePriorities(corpus)
|
ct := target.BuildChoiceTable(corpus, calls)
|
||||||
ct := target.BuildChoiceTable(prios, calls)
|
|
||||||
|
|
||||||
config, execOpts, err := createIPCConfig(target, features, featuresFlags)
|
config, execOpts, err := createIPCConfig(target, features, featuresFlags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user