code-intelligence.com/cifuzz@v0.40.0/internal/cmdutils/pflag.go (about)

     1  package cmdutils
     2  
     3  import (
     4  	"runtime"
     5  
     6  	"github.com/spf13/cobra"
     7  	"github.com/spf13/pflag"
     8  	"github.com/spf13/viper"
     9  )
    10  
    11  var BundleFlags = []string{
    12  	"branch",
    13  	"build-command",
    14  	"build-jobs",
    15  	"commit",
    16  	"dict",
    17  	"docker-image",
    18  	"engine-arg",
    19  	"env",
    20  	"seed-corpus",
    21  	"timeout",
    22  }
    23  
    24  func MarkFlagsRequired(cmd *cobra.Command, flags ...string) {
    25  	for _, flag := range flags {
    26  		err := cmd.MarkFlagRequired(flag)
    27  		if err != nil {
    28  			panic(err)
    29  		}
    30  	}
    31  }
    32  
    33  func ViperMustBindPFlag(key string, flag *pflag.Flag) {
    34  	err := viper.BindPFlag(key, flag)
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  }
    39  
    40  // AddFlags executes the specified Add*Flag functions and returns a
    41  // function which binds all those flags to viper
    42  func AddFlags(cmd *cobra.Command, funcs ...func(cmd *cobra.Command) func()) (bindFlags func()) { // nolint:nonamedreturns
    43  	var bindFlagFuncs []func()
    44  	for _, f := range funcs {
    45  		bindFlagFunc := f(cmd)
    46  		bindFlagFuncs = append(bindFlagFuncs, bindFlagFunc)
    47  	}
    48  	return func() {
    49  		for _, f := range bindFlagFuncs {
    50  			f()
    51  		}
    52  	}
    53  }
    54  
    55  func AddAdditionalFilesFlag(cmd *cobra.Command) func() {
    56  	cmd.Flags().StringArray("add", nil,
    57  		"Add a file or directory to the bundle, defined in the format '--add=<source-path>;<target-path>'.\n"+
    58  			"If <target-path> is missing the file gets copied to 'work_dir'.\n"+
    59  			"This flag can be used multiple times.")
    60  	return func() {
    61  		ViperMustBindPFlag("add", cmd.Flags().Lookup("add"))
    62  	}
    63  }
    64  
    65  func AddBranchFlag(cmd *cobra.Command) func() {
    66  	cmd.Flags().String("branch", "",
    67  		"Branch name to use in the bundle config.\n"+
    68  			"By default, the currently checked out git branch is used.")
    69  	return func() {
    70  		ViperMustBindPFlag("branch", cmd.Flags().Lookup("branch"))
    71  	}
    72  }
    73  
    74  func AddBuildCommandFlag(cmd *cobra.Command) func() {
    75  	cmd.Flags().String("build-command", "",
    76  		"The `command` to build the fuzz test for other build systems.")
    77  	return func() {
    78  		ViperMustBindPFlag("build-command", cmd.Flags().Lookup("build-command"))
    79  	}
    80  }
    81  
    82  func AddCleanCommandFlag(cmd *cobra.Command) func() {
    83  	cmd.Flags().String("clean-command", "",
    84  		"The `command` to clean the fuzz test and its dependencies for other build systems.")
    85  	return func() {
    86  		ViperMustBindPFlag("clean-command", cmd.Flags().Lookup("clean-command"))
    87  	}
    88  }
    89  
    90  func AddBuildJobsFlag(cmd *cobra.Command) func() {
    91  	cmd.Flags().Uint("build-jobs", 0,
    92  		"Maximum number of concurrent processes to use when building.\n"+
    93  			"If argument is omitted the native build tool's default number is used.")
    94  	cmd.Flags().Lookup("build-jobs").NoOptDefVal = "0"
    95  	return func() {
    96  		ViperMustBindPFlag("build-jobs", cmd.Flags().Lookup("build-jobs"))
    97  	}
    98  }
    99  
   100  func AddBuildOnlyFlag(cmd *cobra.Command) func() {
   101  	cmd.Flags().Bool("build-only", false,
   102  		"Only build the fuzz test and don't execute it.")
   103  	return func() {
   104  		ViperMustBindPFlag("build-only", cmd.Flags().Lookup("build-only"))
   105  	}
   106  }
   107  
   108  func AddCommitFlag(cmd *cobra.Command) func() {
   109  	cmd.Flags().String("commit", "",
   110  		"Commit to use in the bundle config.\n"+
   111  			"By default, the head of the currently checked out git branch is used.")
   112  	return func() {
   113  		ViperMustBindPFlag("commit", cmd.Flags().Lookup("commit"))
   114  	}
   115  }
   116  
   117  func AddDictFlag(cmd *cobra.Command) func() {
   118  	// TODO(afl): Also link to https://github.com/AFLplusplus/AFLplusplus/blob/stable/dictionaries/README.md
   119  	cmd.Flags().String("dict", "",
   120  		"A `file` containing input language keywords or other interesting byte sequences.\n"+
   121  			"See https://llvm.org/docs/LibFuzzer.html#dictionaries.")
   122  	return func() {
   123  		ViperMustBindPFlag("dict", cmd.Flags().Lookup("dict"))
   124  	}
   125  }
   126  
   127  func AddDockerImageFlag(cmd *cobra.Command) func() {
   128  	// Default was originally set to "ubuntu:rolling", but this is not correct
   129  	// It will be set by the bundle command depending on the build system, unless user overrides it
   130  	cmd.Flags().String("docker-image", "",
   131  		"Docker image to use in the bundle config. This image will be used when\n"+
   132  			"the bundle is executed on CI Sense.\n"+
   133  			"By default, the image is chosen automatically based on the build system.")
   134  	return func() {
   135  		ViperMustBindPFlag("docker-image", cmd.Flags().Lookup("docker-image"))
   136  	}
   137  }
   138  
   139  func AddEngineArgFlag(cmd *cobra.Command) func() {
   140  	// TODO(afl): Also link to https://www.mankier.com/8/afl-fuzz
   141  	cmd.Flags().StringArray("engine-arg", nil,
   142  		"Command-line `argument` to pass to the fuzzing engine.\n"+
   143  			"See https://llvm.org/docs/LibFuzzer.html#options.\n"+
   144  			"This flag can be used multiple times.\n"+
   145  			"Not supported for Node.js projects.")
   146  	return func() {
   147  		ViperMustBindPFlag("engine-args", cmd.Flags().Lookup("engine-arg"))
   148  	}
   149  }
   150  
   151  func AddEnvFlag(cmd *cobra.Command) func() {
   152  	cmd.Flags().StringArray("env", nil,
   153  		"Set environment variable when executing fuzz tests, e.g. '--env `VAR=value`'.\n"+
   154  			"To use the value of VAR in the local environment, use '--env VAR'.\n"+
   155  			"This flag can be used multiple times.")
   156  	return func() {
   157  		ViperMustBindPFlag("env", cmd.Flags().Lookup("env"))
   158  	}
   159  }
   160  
   161  func AddInteractiveFlag(cmd *cobra.Command) func() {
   162  	cmd.Flags().Bool("interactive", true, "Toggle interactive prompting in the terminal")
   163  	return func() {
   164  		ViperMustBindPFlag("interactive", cmd.Flags().Lookup("interactive"))
   165  	}
   166  }
   167  
   168  func AddPresetFlag(cmd *cobra.Command) func() {
   169  	cmd.Flags().String("preset", "", "Preset for a given environment to execute coverage with necessary flags.\n"+
   170  		"We recommend not using this flag with '--format' or '--output' because the preset will set these accordingly.\n"+
   171  		"If '--format' or '--output' are set, they will overwrite the preset.")
   172  	return func() {
   173  		ViperMustBindPFlag("preset", cmd.Flags().Lookup("preset"))
   174  	}
   175  }
   176  
   177  func AddPrintJSONFlag(cmd *cobra.Command) func() {
   178  	cmd.Flags().Bool("json", false, "Print output as JSON")
   179  	return func() {
   180  		ViperMustBindPFlag("print-json", cmd.Flags().Lookup("json"))
   181  	}
   182  }
   183  
   184  func AddProjectDirFlag(cmd *cobra.Command) func() {
   185  	cmd.Flags().String("project-dir", "",
   186  		"The project root which is the parent for all the project sources.\n"+
   187  			"Defaults to the directory containing the cifuzz.yaml.")
   188  	return func() {
   189  		ViperMustBindPFlag("project-dir", cmd.Flags().Lookup("project-dir"))
   190  	}
   191  }
   192  
   193  func AddResolveSourceFileFlag(cmd *cobra.Command) func() {
   194  	cmd.Flags().BoolP("resolve", "r", false,
   195  		"Argument of the command is a path to a source file instead of a test identifier.\n"+
   196  			"The path can be either absolute or relative to the current working directory and \n"+
   197  			"will be resolved to the identifier of the corresponding fuzz test.")
   198  	return func() {
   199  		ViperMustBindPFlag("resolveSourceFilePath", cmd.Flags().Lookup("resolve"))
   200  	}
   201  }
   202  
   203  func AddProjectFlag(cmd *cobra.Command) func() {
   204  	// TODO: Make the project name more accessible in the web app (currently
   205  	//       it's only shown in the URL)
   206  	cmd.Flags().StringP("project", "p", "", `The name of the CI Fuzz project you want to start a fuzzing run for,
   207  e.g. "my-project-c170bc17".`)
   208  	return func() {
   209  		ViperMustBindPFlag("project", cmd.Flags().Lookup("project"))
   210  	}
   211  }
   212  
   213  func AddSeedCorpusFlag(cmd *cobra.Command) func() {
   214  	// TODO(afl): Also link to https://aflplus.plus/docs/fuzzing_in_depth/#a-collecting-inputs
   215  	cmd.Flags().StringArrayP("seed-corpus", "s", nil,
   216  		"A `directory` containing sample inputs for the code under test,\n"+
   217  			"which is used in addition to inputs found in the inputs\n"+
   218  			"directory of the fuzz test.\n"+
   219  			"See https://github.com/CodeIntelligenceTesting/cifuzz/blob/main/docs/Glossary.md#seed-corpus.\n"+
   220  			"This flag can be used multiple times.")
   221  	return func() {
   222  		ViperMustBindPFlag("seed-corpus-dirs", cmd.Flags().Lookup("seed-corpus"))
   223  	}
   224  }
   225  
   226  func AddServerFlag(cmd *cobra.Command) func() {
   227  	cmd.PersistentFlags().String("server", "https://app.code-intelligence.com", "Address of CI Sense")
   228  	return func() {
   229  		ViperMustBindPFlag("server", cmd.Flags().Lookup("server"))
   230  	}
   231  }
   232  
   233  func AddTimeoutFlag(cmd *cobra.Command) func() {
   234  	cmd.Flags().Duration("timeout", 0,
   235  		"Maximum time to run the fuzz test, e.g. \"30m\", \"1h\". The default is to run indefinitely.")
   236  	return func() {
   237  		ViperMustBindPFlag("timeout", cmd.Flags().Lookup("timeout"))
   238  	}
   239  }
   240  
   241  func AddUseSandboxFlag(cmd *cobra.Command) func() {
   242  	cmd.Flags().Bool("use-sandbox", false,
   243  		"By default, fuzz tests are executed in a sandbox to prevent accidental damage to the system.\n"+
   244  			"Use --use-sandbox=false to run the fuzz test unsandboxed.\n"+
   245  			"Only supported for c/c++ projects on Linux.")
   246  	viper.SetDefault("use-sandbox", runtime.GOOS == "linux")
   247  	return func() {
   248  		ViperMustBindPFlag("use-sandbox", cmd.Flags().Lookup("use-sandbox"))
   249  	}
   250  }