// Copyright 2017 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 csource import ( "bytes" "errors" "fmt" ) // Options control various aspects of source generation. // Dashboard also provides serialized Options along with syzkaller reproducers. type Options struct { Threaded bool Collide bool Repeat bool Procs int Sandbox string Fault bool // inject fault into FaultCall/FaultNth FaultCall int FaultNth int // These options allow for a more fine-tuned control over the generated C code. EnableTun bool UseTmpDir bool HandleSegv bool WaitRepeat bool Debug bool // Generate code for use with repro package to prints log messages, // which allows to distinguish between a hang and an absent crash. Repro bool } // Check checks if the opts combination is valid or not. // For example, Collide without Threaded is not valid. // Invalid combinations must not be passed to Write. func (opts Options) Check() error { if !opts.Threaded && opts.Collide { // Collide requires threaded. return errors.New("Collide without Threaded") } if !opts.Repeat && opts.Procs > 1 { // This does not affect generated code. return errors.New("Procs>1 without Repeat") } if opts.Sandbox == "namespace" && !opts.UseTmpDir { // This is borken and never worked. // This tries to create syz-tmp dir in cwd, // which will fail if procs>1 and on second run of the program. return errors.New("Sandbox=namespace without UseTmpDir") } return nil } func (opts Options) Serialize() []byte { return []byte(fmt.Sprintf("%+v", opts)) } func DeserializeOptions(data []byte) (Options, error) { data = bytes.Replace(data, []byte("Sandbox: "), []byte("Sandbox:empty "), -1) var opts Options n, err := fmt.Sscanf(string(data), "{Threaded:%t Collide:%t Repeat:%t Procs:%d Sandbox:%s"+ " Fault:%t FaultCall:%d FaultNth:%d EnableTun:%t UseTmpDir:%t"+ " HandleSegv:%t WaitRepeat:%t Debug:%t Repro:%t}", &opts.Threaded, &opts.Collide, &opts.Repeat, &opts.Procs, &opts.Sandbox, &opts.Fault, &opts.FaultCall, &opts.FaultNth, &opts.EnableTun, &opts.UseTmpDir, &opts.HandleSegv, &opts.WaitRepeat, &opts.Debug, &opts.Repro) if err != nil { return opts, fmt.Errorf("failed to parse repro options: %v", err) } if want := 14; n != want { return opts, fmt.Errorf("failed to parse repro options: got %v fields, want %v", n, want) } if opts.Sandbox == "empty" { opts.Sandbox = "" } return opts, nil }