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  }