code-intelligence.com/cifuzz@v0.40.0/internal/bundler/opts.go (about) 1 package bundler 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "strings" 8 "time" 9 10 "github.com/pkg/errors" 11 12 "code-intelligence.com/cifuzz/internal/cmdutils" 13 "code-intelligence.com/cifuzz/internal/config" 14 "code-intelligence.com/cifuzz/pkg/log" 15 "code-intelligence.com/cifuzz/util/sliceutil" 16 ) 17 18 type Opts struct { 19 Branch string `mapstructure:"branch"` 20 BuildCommand string `mapstructure:"build-command"` 21 CleanCommand string `mapstructure:"clean-command"` 22 BuildSystem string `mapstructure:"build-system"` 23 NumBuildJobs uint `mapstructure:"build-jobs"` 24 Commit string `mapstructure:"commit"` 25 Dictionary string `mapstructure:"dict"` 26 DockerImage string `mapstructure:"docker-image"` 27 EngineArgs []string `mapstructure:"engine-args"` 28 Env []string `mapstructure:"env"` 29 SeedCorpusDirs []string `mapstructure:"seed-corpus-dirs"` 30 Timeout time.Duration `mapstructure:"timeout"` 31 ProjectDir string `mapstructure:"project-dir"` 32 ConfigDir string `mapstructure:"config-dir"` 33 AdditionalFiles []string `mapstructure:"add"` 34 35 // Fields which are not configurable via viper (i.e. via cifuzz.yaml 36 // and CIFUZZ_* environment variables), by setting 37 // mapstructure:"-" 38 FuzzTests []string `mapstructure:"-"` 39 OutputPath string `mapstructure:"-"` 40 BuildSystemArgs []string `mapstructure:"-"` 41 Stdout io.Writer `mapstructure:"-"` 42 Stderr io.Writer `mapstructure:"-"` 43 BuildStdout io.Writer `mapstructure:"-"` 44 BuildStderr io.Writer `mapstructure:"-"` 45 46 tempDir string `mapstructure:"-"` 47 48 ResolveSourceFilePath bool 49 BundleBuildLogFile string 50 } 51 52 func (opts *Opts) Validate() error { 53 var err error 54 55 // Ensure that the fuzz tests contain no duplicates 56 opts.FuzzTests = sliceutil.RemoveDuplicates(opts.FuzzTests) 57 58 opts.SeedCorpusDirs, err = cmdutils.ValidateSeedCorpusDirs(opts.SeedCorpusDirs) 59 if err != nil { 60 log.Error(err) 61 return cmdutils.ErrSilent 62 } 63 64 if opts.Dictionary != "" { 65 // Check if the dictionary exists and can be accessed 66 _, err := os.Stat(opts.Dictionary) 67 if err != nil { 68 err = errors.WithStack(err) 69 log.Error(err) 70 return cmdutils.ErrSilent 71 } 72 } 73 74 if opts.BuildSystem == config.BuildSystemBazel { 75 // We don't support building a bundle with bazel without any 76 // specified fuzz tests 77 if len(opts.FuzzTests) == 0 { 78 msg := `At least one <fuzz test> argument must be provided` 79 return cmdutils.WrapIncorrectUsageError(errors.New(msg)) 80 } 81 82 // Evaluate any target patterns which users might have provided 83 patterns := opts.FuzzTests 84 opts.FuzzTests, err = cmdutils.EvaluateBazelTargetPatterns(patterns) 85 if err != nil { 86 return err 87 } 88 89 if len(opts.FuzzTests) == 0 { 90 err := errors.Errorf("No valid targets found for patterns: %s", strings.Join(patterns, " ")) 91 log.Error(err) 92 return cmdutils.WrapSilentError(err) 93 } 94 } 95 96 if opts.BuildSystem == config.BuildSystemOther { 97 // To build with other build systems, a build command must be provided 98 if opts.BuildCommand == "" { 99 msg := "Flag \"build-command\" must be set when using build system type \"other\"" 100 return cmdutils.WrapIncorrectUsageError(errors.New(msg)) 101 } 102 // To build with other build systems, the fuzz tests need to be 103 // specified (because there is no way for us to figure out which 104 // fuzz tests exist). 105 if len(opts.FuzzTests) == 0 { 106 msg := `At least one <fuzz test> argument must be provided when using the build 107 system type "other"` 108 return cmdutils.WrapIncorrectUsageError(errors.New(msg)) 109 } 110 } 111 112 if opts.Timeout != 0 && opts.Timeout < time.Second { 113 msg := fmt.Sprintf("invalid argument %q for \"--timeout\" flag: timeout can't be less than a second", opts.Timeout) 114 return cmdutils.WrapIncorrectUsageError(errors.New(msg)) 115 } 116 117 // If an env var doesn't contain a "=", it means the user wants to 118 // use the value from the current environment 119 var env []string 120 for _, e := range opts.Env { 121 if strings.Contains(e, "=") { 122 // The environment variable contains a "=", so we use it 123 env = append(env, e) 124 continue 125 } 126 if os.Getenv(e) == "" { 127 // The variable does not contain a "=" and is not set in the 128 // current environment, so we ignore it 129 continue 130 } 131 // Use the variable with the value from the current environment 132 env = append(env, fmt.Sprintf("%s=%s", e, os.Getenv(e))) 133 } 134 opts.Env = env 135 136 return nil 137 }