From 8e7ca7c5ff18e17cab7b6b3ae569565224f95fcc Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 17 Dec 2015 16:06:33 +0100 Subject: remove master and naming overhaul Remove master process entirely, it is not useful in its current form. We first need to understand what we want from it, and them re-implement it. Prefix all binaries with syz- to avoid name clashes. --- tools/execprog/execprog.go | 169 ----------------------------------------- tools/mutate/mutate.go | 49 ------------ tools/prog2c/prog2c.go | 31 -------- tools/stress/stress.go | 153 ------------------------------------- tools/syz-execprog/execprog.go | 169 +++++++++++++++++++++++++++++++++++++++++ tools/syz-mutate/mutate.go | 49 ++++++++++++ tools/syz-prog2c/prog2c.go | 31 ++++++++ tools/syz-stress/stress.go | 153 +++++++++++++++++++++++++++++++++++++ 8 files changed, 402 insertions(+), 402 deletions(-) delete mode 100644 tools/execprog/execprog.go delete mode 100644 tools/mutate/mutate.go delete mode 100644 tools/prog2c/prog2c.go delete mode 100644 tools/stress/stress.go create mode 100644 tools/syz-execprog/execprog.go create mode 100644 tools/syz-mutate/mutate.go create mode 100644 tools/syz-prog2c/prog2c.go create mode 100644 tools/syz-stress/stress.go (limited to 'tools') diff --git a/tools/execprog/execprog.go b/tools/execprog/execprog.go deleted file mode 100644 index dcb2a0b8b..000000000 --- a/tools/execprog/execprog.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2015 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -// execprog executes a single program or a set of programs -// and optinally prints information about execution. -package main - -import ( - "bufio" - "bytes" - "encoding/binary" - "flag" - "fmt" - "io/ioutil" - "log" - "os" - "sync" - "time" - - "github.com/google/syzkaller/cover" - "github.com/google/syzkaller/ipc" - "github.com/google/syzkaller/prog" -) - -var ( - flagExecutor = flag.String("executor", "", "path to executor binary") - flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor") - flagCollide = flag.Bool("collide", true, "collide syscalls to provoke data races") - flagDebug = flag.Bool("debug", false, "debug output from executor") - flagStrace = flag.Bool("strace", false, "run executor under strace") - flagCover = flag.Bool("cover", true, "collect coverage") - flagCoverFile = flag.String("coverfile", "", "write coverage to the file") - flagNobody = flag.Bool("nobody", true, "impersonate into nobody") - flagDedup = flag.Bool("dedup", false, "deduplicate coverage in executor") - flagLoop = flag.Bool("loop", false, "execute programs in a loop") - flagProcs = flag.Int("procs", 1, "number of parallel processes to execute programs") - flagTimeout = flag.Duration("timeout", 10*time.Second, "execution timeout") -) - -func main() { - flag.Parse() - if len(flag.Args()) == 0 { - fmt.Fprintf(os.Stderr, "usage: execprog [flags] file-with-programs*\n") - flag.PrintDefaults() - os.Exit(1) - } - - var progs []*prog.Prog - for _, fn := range flag.Args() { - progs = append(progs, parseFile(fn)...) - } - log.Printf("parsed %v programs", len(progs)) - if len(progs) == 0 { - return - } - - var flags uint64 - if *flagThreaded { - flags |= ipc.FlagThreaded - } - if *flagCollide { - flags |= ipc.FlagCollide - } - if *flagDebug { - flags |= ipc.FlagDebug - } - if *flagStrace { - flags |= ipc.FlagStrace - } - if *flagCover || *flagCoverFile != "" { - flags |= ipc.FlagCover - } - if *flagDedup { - flags |= ipc.FlagDedupCover - } - if *flagNobody { - flags |= ipc.FlagDropPrivs - } - - var wg sync.WaitGroup - wg.Add(*flagProcs) - var posMu sync.Mutex - var pos int - var lastPrint time.Time - for p := 0; p < *flagProcs; p++ { - go func() { - env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags) - if err != nil { - log.Fatalf("failed to create ipc env: %v", err) - } - for { - posMu.Lock() - idx := pos - pos++ - if idx%len(progs) == 0 && time.Since(lastPrint) > 5*time.Second { - log.Printf("executed %v programs\n", idx) - lastPrint = time.Now() - } - posMu.Unlock() - if !*flagLoop && idx >= len(progs) { - env.Close() - wg.Done() - return - } - p := progs[idx%len(progs)] - output, strace, cov, failed, hanged, err := env.Exec(p) - if *flagDebug || err != nil { - fmt.Printf("result: failed=%v hanged=%v err=%v\n\n%s", failed, hanged, err, output) - } - if *flagStrace { - fmt.Printf("strace output:\n%s", strace) - } - if *flagCoverFile != "" { - // Coverage is dumped in sanitizer format. - // github.com/google/sanitizers/tools/sancov command can be used to dump PCs, - // then they can be piped via addr2line to symbolize. - for i, c := range cov { - fmt.Printf("call #%v: coverage %v\n", i, len(c)) - if len(c) == 0 { - continue - } - buf := new(bytes.Buffer) - binary.Write(buf, binary.LittleEndian, uint64(0xC0BFFFFFFFFFFF64)) - for _, pc := range c { - binary.Write(buf, binary.LittleEndian, cover.RestorePC(pc)) - } - err := ioutil.WriteFile(fmt.Sprintf("%v.%v", *flagCoverFile, i), buf.Bytes(), 0660) - if err != nil { - log.Fatalf("failed to write coverage file: %v", err) - } - } - } - } - }() - } - wg.Wait() -} - -func parseFile(fn string) []*prog.Prog { - logf, err := os.Open(fn) - if err != nil { - log.Fatalf("failed to open log file: %v", err) - } - log.Printf("parsing log %v", fn) - s := bufio.NewScanner(logf) - var cur []byte - var last *prog.Prog - var progs []*prog.Prog - for s.Scan() { - ln := s.Text() - tmp := append(cur, ln...) - tmp = append(tmp, '\n') - p, err := prog.Deserialize(tmp) - if err == nil { - cur = tmp - last = p - continue - } - if last != nil { - progs = append(progs, last) - last = nil - cur = cur[:0] - } - } - if last != nil { - progs = append(progs, last) - } - return progs -} diff --git a/tools/mutate/mutate.go b/tools/mutate/mutate.go deleted file mode 100644 index 353d60390..000000000 --- a/tools/mutate/mutate.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -// mutates mutates a given program and prints result. -package main - -import ( - "flag" - "fmt" - "io/ioutil" - "math/rand" - "os" - "time" - - "github.com/google/syzkaller/prog" -) - -var ( - flagSeed = flag.Int("seed", -1, "prng seed") -) - -func main() { - flag.Parse() - if flag.NArg() != 1 { - fmt.Fprintf(os.Stderr, "usage: mutate program\n") - os.Exit(1) - } - data, err := ioutil.ReadFile(flag.Arg(0)) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) - os.Exit(1) - } - p, err := prog.Deserialize(data) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) - os.Exit(1) - } - - prios := prog.CalculatePriorities(nil) - ct := prog.BuildChoiceTable(prios, nil) - - seed := time.Now().UnixNano() - if *flagSeed != -1 { - seed = int64(*flagSeed) - } - rs := rand.NewSource(seed) - p.Mutate(rs, len(p.Calls)+10, ct) - fmt.Printf("%s\n", p.Serialize()) -} diff --git a/tools/prog2c/prog2c.go b/tools/prog2c/prog2c.go deleted file mode 100644 index 9b8e58efa..000000000 --- a/tools/prog2c/prog2c.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2015 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -package main - -import ( - "fmt" - "io/ioutil" - "os" - - "github.com/google/syzkaller/prog" -) - -func main() { - if len(os.Args) != 2 { - fmt.Fprintf(os.Stderr, "usage: prog2c prog_file\n") - os.Exit(1) - } - data, err := ioutil.ReadFile(os.Args[1]) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) - os.Exit(1) - } - p, err := prog.Deserialize(data) - if err != nil { - fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) - os.Exit(1) - } - src := p.WriteCSource() - os.Stdout.Write(src) -} diff --git a/tools/stress/stress.go b/tools/stress/stress.go deleted file mode 100644 index e4f1a506c..000000000 --- a/tools/stress/stress.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2015 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. - -package main - -import ( - "archive/zip" - "flag" - "fmt" - "io/ioutil" - "log" - "math/rand" - "os" - "regexp" - "runtime" - "sync" - "sync/atomic" - "time" - - "github.com/google/syzkaller/ipc" - "github.com/google/syzkaller/prog" -) - -var ( - flagCorpus = flag.String("corpus", "", "corpus directory") - flagExecutor = flag.String("executor", "", "path to executor binary") - flagOutput = flag.Bool("output", false, "print executor output to console") - flagDebug = flag.Bool("debug", false, "executor debug output") - flagProcs = flag.Int("procs", 2*runtime.NumCPU(), "number of parallel processes") - flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor") - flagCollide = flag.Bool("collide", true, "collide syscalls to provoke data races") - flagNobody = flag.Bool("nobody", true, "impersonate into nobody") - flagTimeout = flag.Duration("timeout", 10*time.Second, "executor timeout") - flagLogProg = flag.Bool("logprog", false, "print programs before execution") - - failedRe = regexp.MustCompile("runtime error: |panic: |Panic: ") - - statExec uint64 - gate *ipc.Gate -) - -const programLength = 30 - -func main() { - flag.Parse() - corpus := readCorpus() - log.Printf("parsed %v programs", len(corpus)) - var flags uint64 - if *flagThreaded { - flags |= ipc.FlagThreaded - } - if *flagCollide { - flags |= ipc.FlagCollide - } - if *flagNobody { - flags |= ipc.FlagDropPrivs - } - if *flagDebug { - flags |= ipc.FlagDebug - } - - gate = ipc.NewGate(2 * *flagProcs) - for pid := 0; pid < *flagProcs; pid++ { - pid := pid - go func() { - env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags) - if err != nil { - failf("failed to create execution environment: %v", err) - } - rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12) - rnd := rand.New(rs) - for i := 0; ; i++ { - var p *prog.Prog - if len(corpus) == 0 || i%2 != 0 { - p = prog.Generate(rs, programLength, nil) - execute(pid, env, p) - p.Mutate(rs, programLength, nil) - execute(pid, env, p) - } else { - p = corpus[rnd.Intn(len(corpus))].Clone() - p.Mutate(rs, programLength, nil) - execute(pid, env, p) - p.Mutate(rs, programLength, nil) - execute(pid, env, p) - } - } - }() - } - for range time.NewTicker(5 * time.Second).C { - log.Printf("executed %v programs", atomic.LoadUint64(&statExec)) - } -} - -var outMu sync.Mutex - -func execute(pid int, env *ipc.Env, p *prog.Prog) { - if *flagExecutor == "" { - return - } - atomic.AddUint64(&statExec, 1) - if *flagLogProg { - ticket := gate.Enter() - defer gate.Leave(ticket, nil) - outMu.Lock() - fmt.Printf("executing program %v\n%s\n", pid, p.Serialize()) - outMu.Unlock() - } - - output, _, _, _, _, err := env.Exec(p) - if err != nil { - fmt.Printf("failed to execute executor: %v\n", err) - } - failed := failedRe.Match(output) - if failed { - fmt.Printf("PROGRAM:\n%s\n", p.Serialize()) - } - if failed || *flagOutput { - os.Stdout.Write(output) - } -} - -func readCorpus() []*prog.Prog { - if *flagCorpus == "" { - return nil - } - zipr, err := zip.OpenReader(*flagCorpus) - if err != nil { - failf("failed to open bin file: %v", err) - } - var progs []*prog.Prog - for _, zipf := range zipr.File { - r, err := zipf.Open() - if err != nil { - failf("failed to uzip file from input archive: %v", err) - } - data, err := ioutil.ReadAll(r) - if err != nil { - failf("failed to read corpus file: %v", err) - } - p, err := prog.Deserialize(data) - if err != nil { - failf("failed to deserialize corpus program: %v", err) - } - progs = append(progs, p) - r.Close() - } - zipr.Close() - return progs -} - -func failf(msg string, args ...interface{}) { - log.Fatalf(msg, args...) -} diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go new file mode 100644 index 000000000..dcb2a0b8b --- /dev/null +++ b/tools/syz-execprog/execprog.go @@ -0,0 +1,169 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// execprog executes a single program or a set of programs +// and optinally prints information about execution. +package main + +import ( + "bufio" + "bytes" + "encoding/binary" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "sync" + "time" + + "github.com/google/syzkaller/cover" + "github.com/google/syzkaller/ipc" + "github.com/google/syzkaller/prog" +) + +var ( + flagExecutor = flag.String("executor", "", "path to executor binary") + flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor") + flagCollide = flag.Bool("collide", true, "collide syscalls to provoke data races") + flagDebug = flag.Bool("debug", false, "debug output from executor") + flagStrace = flag.Bool("strace", false, "run executor under strace") + flagCover = flag.Bool("cover", true, "collect coverage") + flagCoverFile = flag.String("coverfile", "", "write coverage to the file") + flagNobody = flag.Bool("nobody", true, "impersonate into nobody") + flagDedup = flag.Bool("dedup", false, "deduplicate coverage in executor") + flagLoop = flag.Bool("loop", false, "execute programs in a loop") + flagProcs = flag.Int("procs", 1, "number of parallel processes to execute programs") + flagTimeout = flag.Duration("timeout", 10*time.Second, "execution timeout") +) + +func main() { + flag.Parse() + if len(flag.Args()) == 0 { + fmt.Fprintf(os.Stderr, "usage: execprog [flags] file-with-programs*\n") + flag.PrintDefaults() + os.Exit(1) + } + + var progs []*prog.Prog + for _, fn := range flag.Args() { + progs = append(progs, parseFile(fn)...) + } + log.Printf("parsed %v programs", len(progs)) + if len(progs) == 0 { + return + } + + var flags uint64 + if *flagThreaded { + flags |= ipc.FlagThreaded + } + if *flagCollide { + flags |= ipc.FlagCollide + } + if *flagDebug { + flags |= ipc.FlagDebug + } + if *flagStrace { + flags |= ipc.FlagStrace + } + if *flagCover || *flagCoverFile != "" { + flags |= ipc.FlagCover + } + if *flagDedup { + flags |= ipc.FlagDedupCover + } + if *flagNobody { + flags |= ipc.FlagDropPrivs + } + + var wg sync.WaitGroup + wg.Add(*flagProcs) + var posMu sync.Mutex + var pos int + var lastPrint time.Time + for p := 0; p < *flagProcs; p++ { + go func() { + env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags) + if err != nil { + log.Fatalf("failed to create ipc env: %v", err) + } + for { + posMu.Lock() + idx := pos + pos++ + if idx%len(progs) == 0 && time.Since(lastPrint) > 5*time.Second { + log.Printf("executed %v programs\n", idx) + lastPrint = time.Now() + } + posMu.Unlock() + if !*flagLoop && idx >= len(progs) { + env.Close() + wg.Done() + return + } + p := progs[idx%len(progs)] + output, strace, cov, failed, hanged, err := env.Exec(p) + if *flagDebug || err != nil { + fmt.Printf("result: failed=%v hanged=%v err=%v\n\n%s", failed, hanged, err, output) + } + if *flagStrace { + fmt.Printf("strace output:\n%s", strace) + } + if *flagCoverFile != "" { + // Coverage is dumped in sanitizer format. + // github.com/google/sanitizers/tools/sancov command can be used to dump PCs, + // then they can be piped via addr2line to symbolize. + for i, c := range cov { + fmt.Printf("call #%v: coverage %v\n", i, len(c)) + if len(c) == 0 { + continue + } + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint64(0xC0BFFFFFFFFFFF64)) + for _, pc := range c { + binary.Write(buf, binary.LittleEndian, cover.RestorePC(pc)) + } + err := ioutil.WriteFile(fmt.Sprintf("%v.%v", *flagCoverFile, i), buf.Bytes(), 0660) + if err != nil { + log.Fatalf("failed to write coverage file: %v", err) + } + } + } + } + }() + } + wg.Wait() +} + +func parseFile(fn string) []*prog.Prog { + logf, err := os.Open(fn) + if err != nil { + log.Fatalf("failed to open log file: %v", err) + } + log.Printf("parsing log %v", fn) + s := bufio.NewScanner(logf) + var cur []byte + var last *prog.Prog + var progs []*prog.Prog + for s.Scan() { + ln := s.Text() + tmp := append(cur, ln...) + tmp = append(tmp, '\n') + p, err := prog.Deserialize(tmp) + if err == nil { + cur = tmp + last = p + continue + } + if last != nil { + progs = append(progs, last) + last = nil + cur = cur[:0] + } + } + if last != nil { + progs = append(progs, last) + } + return progs +} diff --git a/tools/syz-mutate/mutate.go b/tools/syz-mutate/mutate.go new file mode 100644 index 000000000..353d60390 --- /dev/null +++ b/tools/syz-mutate/mutate.go @@ -0,0 +1,49 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// mutates mutates a given program and prints result. +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "math/rand" + "os" + "time" + + "github.com/google/syzkaller/prog" +) + +var ( + flagSeed = flag.Int("seed", -1, "prng seed") +) + +func main() { + flag.Parse() + if flag.NArg() != 1 { + fmt.Fprintf(os.Stderr, "usage: mutate program\n") + os.Exit(1) + } + data, err := ioutil.ReadFile(flag.Arg(0)) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) + os.Exit(1) + } + p, err := prog.Deserialize(data) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) + os.Exit(1) + } + + prios := prog.CalculatePriorities(nil) + ct := prog.BuildChoiceTable(prios, nil) + + seed := time.Now().UnixNano() + if *flagSeed != -1 { + seed = int64(*flagSeed) + } + rs := rand.NewSource(seed) + p.Mutate(rs, len(p.Calls)+10, ct) + fmt.Printf("%s\n", p.Serialize()) +} diff --git a/tools/syz-prog2c/prog2c.go b/tools/syz-prog2c/prog2c.go new file mode 100644 index 000000000..9b8e58efa --- /dev/null +++ b/tools/syz-prog2c/prog2c.go @@ -0,0 +1,31 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "io/ioutil" + "os" + + "github.com/google/syzkaller/prog" +) + +func main() { + if len(os.Args) != 2 { + fmt.Fprintf(os.Stderr, "usage: prog2c prog_file\n") + os.Exit(1) + } + data, err := ioutil.ReadFile(os.Args[1]) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read prog file: %v\n", err) + os.Exit(1) + } + p, err := prog.Deserialize(data) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to deserialize the program: %v\n", err) + os.Exit(1) + } + src := p.WriteCSource() + os.Stdout.Write(src) +} diff --git a/tools/syz-stress/stress.go b/tools/syz-stress/stress.go new file mode 100644 index 000000000..e4f1a506c --- /dev/null +++ b/tools/syz-stress/stress.go @@ -0,0 +1,153 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package main + +import ( + "archive/zip" + "flag" + "fmt" + "io/ioutil" + "log" + "math/rand" + "os" + "regexp" + "runtime" + "sync" + "sync/atomic" + "time" + + "github.com/google/syzkaller/ipc" + "github.com/google/syzkaller/prog" +) + +var ( + flagCorpus = flag.String("corpus", "", "corpus directory") + flagExecutor = flag.String("executor", "", "path to executor binary") + flagOutput = flag.Bool("output", false, "print executor output to console") + flagDebug = flag.Bool("debug", false, "executor debug output") + flagProcs = flag.Int("procs", 2*runtime.NumCPU(), "number of parallel processes") + flagThreaded = flag.Bool("threaded", true, "use threaded mode in executor") + flagCollide = flag.Bool("collide", true, "collide syscalls to provoke data races") + flagNobody = flag.Bool("nobody", true, "impersonate into nobody") + flagTimeout = flag.Duration("timeout", 10*time.Second, "executor timeout") + flagLogProg = flag.Bool("logprog", false, "print programs before execution") + + failedRe = regexp.MustCompile("runtime error: |panic: |Panic: ") + + statExec uint64 + gate *ipc.Gate +) + +const programLength = 30 + +func main() { + flag.Parse() + corpus := readCorpus() + log.Printf("parsed %v programs", len(corpus)) + var flags uint64 + if *flagThreaded { + flags |= ipc.FlagThreaded + } + if *flagCollide { + flags |= ipc.FlagCollide + } + if *flagNobody { + flags |= ipc.FlagDropPrivs + } + if *flagDebug { + flags |= ipc.FlagDebug + } + + gate = ipc.NewGate(2 * *flagProcs) + for pid := 0; pid < *flagProcs; pid++ { + pid := pid + go func() { + env, err := ipc.MakeEnv(*flagExecutor, *flagTimeout, flags) + if err != nil { + failf("failed to create execution environment: %v", err) + } + rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12) + rnd := rand.New(rs) + for i := 0; ; i++ { + var p *prog.Prog + if len(corpus) == 0 || i%2 != 0 { + p = prog.Generate(rs, programLength, nil) + execute(pid, env, p) + p.Mutate(rs, programLength, nil) + execute(pid, env, p) + } else { + p = corpus[rnd.Intn(len(corpus))].Clone() + p.Mutate(rs, programLength, nil) + execute(pid, env, p) + p.Mutate(rs, programLength, nil) + execute(pid, env, p) + } + } + }() + } + for range time.NewTicker(5 * time.Second).C { + log.Printf("executed %v programs", atomic.LoadUint64(&statExec)) + } +} + +var outMu sync.Mutex + +func execute(pid int, env *ipc.Env, p *prog.Prog) { + if *flagExecutor == "" { + return + } + atomic.AddUint64(&statExec, 1) + if *flagLogProg { + ticket := gate.Enter() + defer gate.Leave(ticket, nil) + outMu.Lock() + fmt.Printf("executing program %v\n%s\n", pid, p.Serialize()) + outMu.Unlock() + } + + output, _, _, _, _, err := env.Exec(p) + if err != nil { + fmt.Printf("failed to execute executor: %v\n", err) + } + failed := failedRe.Match(output) + if failed { + fmt.Printf("PROGRAM:\n%s\n", p.Serialize()) + } + if failed || *flagOutput { + os.Stdout.Write(output) + } +} + +func readCorpus() []*prog.Prog { + if *flagCorpus == "" { + return nil + } + zipr, err := zip.OpenReader(*flagCorpus) + if err != nil { + failf("failed to open bin file: %v", err) + } + var progs []*prog.Prog + for _, zipf := range zipr.File { + r, err := zipf.Open() + if err != nil { + failf("failed to uzip file from input archive: %v", err) + } + data, err := ioutil.ReadAll(r) + if err != nil { + failf("failed to read corpus file: %v", err) + } + p, err := prog.Deserialize(data) + if err != nil { + failf("failed to deserialize corpus program: %v", err) + } + progs = append(progs, p) + r.Close() + } + zipr.Close() + return progs +} + +func failf(msg string, args ...interface{}) { + log.Fatalf(msg, args...) +} -- cgit mrf-deployment