Documentation ¶
Overview ¶
Package config provides a simple way to manage configuration files.
Use Load(filename) to load a configuration from a specific filename.
Use SetGlobalConfig(filename) to set filename as the global config, and then LoadGlobal() to load the global config.
A config file should be in yaml or json format. The top-level fields can be any of the fields defined in the Config struct type. The other fields are defined by the types of the fields of Config and nested struct types. For example, a valid config file is as follows: options:
log-level: 5
taint-tracking-problems:
- sinks: - package: fmt method: Printf sources: - method: Read
Identifying code elements ¶
The config uses CodeIdentifier to identify specific code entities. For example, sinks and sources are CodeIdentifiers which identifies specific functions in specific packages, or types, etc.. An important feature of the code identifiers is that the string specifications are seen as regexes if they can be compiled to regexes, otherwise they are strings.
Unsafe options ¶
All the options that might affect the soundness of the results are prefixed by `unsafe-`, except for the configuration options where the user provides function summaries (where it is assumed the user have soundly summarized the functions).
Index ¶
- Constants
- func ExistsCid(a []CodeIdentifier, f func(identifier CodeIdentifier) bool) bool
- func LoadEscape(c *Config, escapeConfigBytes []byte) error
- func ParseXMLConfigFormat(c *Config, b []byte) error
- func SetGlobalConfig(filename string)
- func SetOption(c *Config, name, value string) (string, error)
- type CodeIdentifier
- type Config
- func (c Config) ExceedsMaxDepth(d int) bool
- func (c Config) IsPathSensitiveFunc(funcName string) bool
- func (c Config) IsSomeBacktracePoint(cid CodeIdentifier) bool
- func (c Config) IsSomeSanitizer(cid CodeIdentifier) bool
- func (c Config) IsSomeSink(cid CodeIdentifier) bool
- func (c Config) IsSomeSource(cid CodeIdentifier) bool
- func (c Config) IsSomeValidator(cid CodeIdentifier) bool
- func (c Config) MatchCoverageFilter(filename string) bool
- func (c Config) MatchPkgFilter(pkgname string) bool
- func (c Config) RelPath(filename string) string
- func (c Config) ReportNoCalleeFile() string
- func (c Config) Verbose() bool
- type EscapeConfig
- type LogGroup
- func (l *LogGroup) Debugf(format string, v ...any)
- func (l *LogGroup) Errorf(format string, v ...any)
- func (l *LogGroup) GetDebug() *log.Logger
- func (l *LogGroup) GetError() *log.Logger
- func (l *LogGroup) Infof(format string, v ...any)
- func (l *LogGroup) LogsDebug() bool
- func (l *LogGroup) LogsError() bool
- func (l *LogGroup) LogsInfo() bool
- func (l *LogGroup) LogsTrace() bool
- func (l *LogGroup) LogsWarning() bool
- func (l *LogGroup) SetAllFlags(x int)
- func (l *LogGroup) SetAllOutput(w io.Writer)
- func (l *LogGroup) SetError(w io.Writer)
- func (l *LogGroup) Tracef(format string, v ...any)
- func (l *LogGroup) Warnf(format string, v ...any)
- type LogLevel
- type MxFile
- type Object
- type Options
- type PointerConfig
- type SlicingSpec
- type StaticCommandsSpec
- type TaintSpec
Constants ¶
const ( // DefaultSafeMaxDepth is the default maximum call stack value that will be considered by the analyses using it // -1 means that depth limit is ignored DefaultSafeMaxDepth = -1 // DefaultSafeMaxEntrypointContextSize sets a context depth value that is usually safe in terms of algorithm performance. DefaultSafeMaxEntrypointContextSize = 5 // EscapeBehaviorSummarize specifies that the function should be summarized in the escape analysis EscapeBehaviorSummarize = "summarize" // EscapeBehaviorNoop specifies that the function is a noop in the escape analysis EscapeBehaviorNoop = "noop" // EscapeBehaviorUnknown specifies that the function is "unknown" in the escape analysis EscapeBehaviorUnknown = "unknown" )
Variables ¶
This section is empty.
Functions ¶
func ExistsCid ¶
func ExistsCid(a []CodeIdentifier, f func(identifier CodeIdentifier) bool) bool
ExistsCid is true if there is some x in a such that f(x) is true. O(len(a))
func LoadEscape ¶
LoadEscape adds the escape configuration settings from escapeConfigBytes into c.
func ParseXMLConfigFormat ¶
ParseXMLConfigFormat parses the bytes as xml, expecting a drawio file representing a diagram of dataflow problems where the options of the config are specified in the metadata.
func SetGlobalConfig ¶
func SetGlobalConfig(filename string)
SetGlobalConfig sets the global config filename
Types ¶
type CodeIdentifier ¶
type CodeIdentifier struct { // Context stores an additional string that can be used depending on context by analyses. Typically, one can use // Context to match the parent function name when matching a code identifier. Context string `xml:"context,attr"` // Package identifies the package of the code identifier. Package string `xml:"package,attr"` // in drawio input, package is an attribute // Interface identifies the interface name of the code identifier. Interface string `xml:"interface,attr"` // Package identifies the method/function of the code identifier. Method is used loosely here to mean function // or actual method Method string `xml:"method,attr"` // Receiver identified the receiver object of a method call Receiver string `xml:"receiver,attr"` // Field identifies a specific field Field string `xml:"field,attr"` // Type identifies a specific type, which can be used for example to identify allocation of a given type Type string `xml:"type,attr"` // Label can be used to store user-defined information about the code identifier. Label string `xml:"label,attr"` // Kind can be used to give additional semantic meaning to the code identifier. For example, it can be used // to tag a code identifier as a specific "channel receive" Kind string `xml:"kind,attr"` // contains filtered or unexported fields }
A CodeIdentifier identifies a code element that is a source, sink, sanitizer, etc.. A code identifier can be identified from its package, method, receiver, field or type, or any combination of those This is meant to replicate functionality in go-flow-levee and gokart, and can be extended as needed
func NewCodeIdentifier ¶
func NewCodeIdentifier(cid CodeIdentifier) CodeIdentifier
NewCodeIdentifier properly intializes cid.
func (*CodeIdentifier) FullMethodName ¶
func (cid *CodeIdentifier) FullMethodName() string
FullMethodName returns the fully qualified name of the code identifier.
func (*CodeIdentifier) MatchInterface ¶
func (cid *CodeIdentifier) MatchInterface(f *ssa.Function) bool
MatchInterface matches a function to a code identifier by looking whether that function implements an interface's method, and using that method information to match against the code identifier
func (*CodeIdentifier) MatchPackageAndMethod ¶
func (cid *CodeIdentifier) MatchPackageAndMethod(f *ssa.Function) bool
MatchPackageAndMethod checks whether the function f matches the code identifier on the package and method fields. It is safe to call with nil values.
type Config ¶
type Config struct { Options // DataFlowSpecs is a path to a json file that contains the data flows specs for the interfaces in the dataflow // analyses DataflowSpecs []string `yaml:"dataflow-specs" json:"dataflow-specs"` // EscapeConfig contains the escape-analysis specific configuration parameters EscapeConfig *EscapeConfig // PointerConfig contains the pointer-analysis specific configuration parameters PointerConfig *PointerConfig `yaml:"pointer-config" json:"pointer-config"` // TaintTrackingProblems lists the taint tracking specifications TaintTrackingProblems []TaintSpec `yaml:"taint-tracking-problems" json:"taint-tracking-problems"` // SlicingProblems lists the program slicing specifications SlicingProblems []SlicingSpec `yaml:"slicing-problems" json:"slicing-problems"` // StaticCommandsProblems lists the static commands problems StaticCommandsProblems []StaticCommandsSpec `yaml:"static-commands-problems" json:"static-commands-problems"` // contains filtered or unexported fields }
Config contains lists of sanitizers, sinks, sources, static commands to identify ... To add elements to a config file, add fields to this struct. If some field is not defined in the config file, it will be empty/zero in the struct. private fields are not populated from a yaml file, but computed after initialization
func LoadFromFiles ¶
LoadFromFiles loads a full config from configFileName and the config file's specified escape config file name, reading the files from disk. If the escape config file name is empty, there will be no escape configuration.
func LoadGlobal ¶
LoadGlobal loads the config file that has been set by SetGlobalConfig
func (Config) ExceedsMaxDepth ¶
ExceedsMaxDepth returns true if the input exceeds the maximum depth parameter of the configuration. (this implements the logic for using maximum depth; if the configuration setting is < 0, then this returns false)
func (Config) IsPathSensitiveFunc ¶
IsPathSensitiveFunc returns true if funcName matches any regex in c.Options.PathSensitiveFuncs.
func (Config) IsSomeBacktracePoint ¶
func (c Config) IsSomeBacktracePoint(cid CodeIdentifier) bool
IsSomeBacktracePoint returns true if the code identifier matches any backtrace point in the slicing problems
func (Config) IsSomeSanitizer ¶
func (c Config) IsSomeSanitizer(cid CodeIdentifier) bool
IsSomeSanitizer returns true if the code identifier matches any sanitizer in the config
func (Config) IsSomeSink ¶
func (c Config) IsSomeSink(cid CodeIdentifier) bool
IsSomeSink returns true if the code identifier matches any sink in the config
func (Config) IsSomeSource ¶
func (c Config) IsSomeSource(cid CodeIdentifier) bool
IsSomeSource returns true if the code identifier matches any source in the config
func (Config) IsSomeValidator ¶
func (c Config) IsSomeValidator(cid CodeIdentifier) bool
IsSomeValidator returns true if the code identifier matches any validator in the config
func (Config) MatchCoverageFilter ¶
MatchCoverageFilter returns true if the file name matches the coverageFilterRegex, if specified
func (Config) MatchPkgFilter ¶
MatchPkgFilter returns true if the package name pkgname matches the package filter set in the config file. If no package filter has been set in the config file, the regex will match anything and return true. This function safely considers the case where a filter has been specified by the user, but it could not be compiled to a regex. The safe case is to check whether the package filter string is a prefix of the pkgname
func (Config) ReportNoCalleeFile ¶
ReportNoCalleeFile return the file name that will contain the list of locations that have no callee
type EscapeConfig ¶
type EscapeConfig struct { // Functions controls behavior override, keyed by .String() (e.g. command-line-arguments.main, // (*package.Type).Method, etc). A value of "summarize" means process normally, "unknown" is // treat as unanalyzed, and "noop" means calls are assumed to have no escape effect (and return // nil if they have a pointer-like return). Functions map[string]string `json:"functions"` // The maximum size of an escape summary. If a function attempts to compute a larger summary, it // will be replaced by a conservative, unsummarized stub. SummaryMaximumSize int `json:"summary-maximum-size"` // Allow/blocklist of packages, keyed by package path. A value of true means allow, false is // block, and not present is default behavior. PkgFilter string `json:"pkg-filter"` // contains filtered or unexported fields }
EscapeConfig holds the options relative to the escape analysis configuration
func NewEscapeConfig ¶
func NewEscapeConfig() *EscapeConfig
NewEscapeConfig returns a new escape config with a preset summary maximum size and initialized Functions map.
func (*EscapeConfig) MatchPkgFilter ¶
func (c *EscapeConfig) MatchPkgFilter(pkgname string) bool
MatchPkgFilter matches a package name against a configuration. Returns true if the package name matches the filter.
type LogGroup ¶
type LogGroup struct { Level LogLevel // contains filtered or unexported fields }
LogGroup holds a set of loggers that will be called depending on the logging kind
func NewLogGroup ¶
NewLogGroup returns a log group that is configured to the logging settings stored inside the config
func (*LogGroup) Debugf ¶
Debugf calls Debug.Printf to print to the trace logger. Arguments are handled in the manner of Printf
func (*LogGroup) Errorf ¶
Errorf calls Error.Printf to print to the trace logger. Arguments are handled in the manner of Printf
func (*LogGroup) GetDebug ¶
GetDebug returns the debug level logger, for applications that need a logger as input
func (*LogGroup) GetError ¶
GetError returns the error logger, for applications that need a logger as input
func (*LogGroup) Infof ¶
Infof calls Info.Printf to print to the trace logger. Arguments are handled in the manner of Printf
func (*LogGroup) LogsError ¶
LogsError returns true if the log group logs error messages. Note that this is the lowest logging level, and if this returns false, it implies that the log group does not log anything.
func (*LogGroup) LogsWarning ¶
LogsWarning returns true if the log group logs warning messages
func (*LogGroup) SetAllFlags ¶
SetAllFlags sets the flag of all loggers in the log group to the argument provided
func (*LogGroup) SetAllOutput ¶
SetAllOutput sets all the output writers to the writer provided
type LogLevel ¶
type LogLevel int
LogLevel represents a logging level
const ( // ErrLevel =1 - the minimum level of logging. ErrLevel LogLevel = iota + 1 // WarnLevel =2 - the level for logging warnings, and errors WarnLevel // InfoLevel =3 - the level for logging high-level information, results InfoLevel // DebugLevel =4 - the level for debugging information. The tool will run properly on large programs with // that level of debug information. DebugLevel // TraceLevel =5 - the level for tracing. The tool will not run properly on large programs with that level // of information, but this is useful on smaller testing programs. TraceLevel )
type MxFile ¶
type MxFile struct { Object []Object `xml:"diagram>mxGraphModel>root>object"` Cells []mxCell `xml:"diagram>mxGraphModel>root>mxCell"` Modified string `xml:"modified,attr"` Host string `xml:"host,attr"` }
MxFile is the toplevel file representation in a draio diagram
type Object ¶
type Object struct { ID string `xml:"id,attr"` CodeIdentifier Options Forbidden bool `xml:"forbidden,attr"` Cell mxCell `xml:"mxCell"` IsSource bool `xml:"taint-source,attr"` IsSink bool `xml:"taint-sink,attr"` IsSanitizer bool `xml:"taint-sanitizer,attr"` IsValidator bool `xml:"taint-validator,attr"` DataflowSpecs string `xml:"dataflow-specs,attr"` Filters string `xml:"filters,attr"` }
Object represents an object in the drawio diagram
type Options ¶
type Options struct { // Path to a JSON file that has the escape configuration (allow/blocklist) EscapeConfigFile string `xml:"escape-config,attr" yaml:"escape-config" json:"escape-config"` // CoverageFilter can be used to filter which packages will be reported in the coverage. If non-empty, // coverage will only for those packages that match CoverageFilter CoverageFilter string `xml:"coverage-filter,attr" yaml:"coverage-filter" json:"coverage-filter"` // Loglevel controls the verbosity of the tool LogLevel int `xml:"log-level,attr" yaml:"log-level" json:"log-level"` // MaxAlarms sets a limit for the number of alarms reported by an analysis. If MaxAlarms > 0, then at most // MaxAlarms will be reported. Otherwise, if MaxAlarms <= 0, it is ignored. // // This setting does not affect soundness, since event with max-alarms:1, at least one path will be reported if // there is some potential alarm-causing result. MaxAlarms int `xml:"max-alarms,attr" yaml:"max-alarms" json:"max-alarms"` // MaxEntrypointContextSize sets the maximum context (call stack) size used when searching for entry points with context. // This only impacts precision of the returned results. // // If MaxEntrypointContextSize is < 0, it is ignored. // If MaxEntrypointContextSize is 0 is specified by the user, the value is ignored, and a default internal value is used. // If MaxEntrypointContextSize is > 0, then the limit in the callstack size for the context is used. MaxEntrypointContextSize int `xml:"max-entrypoint-context-size,attr" yaml:"max-entrypoint-context-size" json:"max-entrypoint-context-size"` // PathSensitive is a boolean indicating whether the analysis should be run with access path sensitivity on // (will change to include more filtering in the future) // // Note that the configuration option name is "field-sensitive" because this is the name that will be more // recognizable for users. // // TODO deprecate since this case is covered by `"field-sensitive-funcs": [".*"]`? PathSensitive bool `xml:"field-sensitive" yaml:"field-sensitive" json:"field-sensitive"` // PkgFilter is a filter for the taint analysis to build summaries only for the function whose package match the // prefix. This is a global option because it is used during the first intra-procedural passes of the analysis. PkgFilter string `xml:"pkg-filter,attr" yaml:"pkg-filter" json:"pkg-filter"` // ReportCoverage specifies whether coverage should be reported. If true, then a file names coverage-*.out will // be created in the report directory, containing the coverage data generated by the analysis ReportCoverage bool `xml:"report-coverage,attr" yaml:"report-coverage" json:"report-coverage"` // ReportNoCalleeSites specifies whether the tool should report where it does not find any callee. ReportNoCalleeSites bool `xml:"report-no-callee-sites,attr" yaml:"report-no-callee-sites" json:"report-no-callee-sites"` // ReportPaths specifies whether the taint flows should be reported in separate files. For each taint flow, a new // file named taint-*.out will be generated with the trace from source to sink ReportPaths bool `xml:"report-paths,attr" yaml:"report-paths" json:"report-paths"` // ReportSummaries can be set to true, in which case summaries will be reported in a file names summaries-*.out in // the reports directory ReportSummaries bool `xml:"report-summaries,attr" yaml:"report-summaries" json:"report-summaries"` // ReportsDir is the directory where all the reports will be stored. If the yaml config file this config struct has // been loaded does not specify a ReportsDir but sets any Report* option to true, then ReportsDir will be created // in the folder the binary is called. ReportsDir string `xml:"reports-dir,attr" yaml:"reports-dir" json:"reports-dir"` // PathSensitiveFuncs is a list of regexes indicating which functions should be path-sensitive. // This allows the analysis to scale yet still maintain a degree of precision where it matters. PathSensitiveFuncs []string `xml:"field-sensitive-funcs" yaml:"field-sensitive-funcs" json:"field-sensitive-funcs"` // SkipInterprocedural can be set to true to skip the interprocedural (inter-procedural analysis) step SkipInterprocedural bool `xml:"skip-interprocedural,attr" yaml:"skip-interprocedural" json:"skip-interprocedural"` // Suppress warnings SilenceWarn bool `xml:"silence-warn,attr" json:"silence-warn" yaml:"silence-warn"` // SourceTaintsArgs specifies whether calls to a source function also taints the argument. This is usually not // the case, but might be useful for some users or for source functions that do not return anything. SourceTaintsArgs bool `xml:"source-taints-args,attr" yaml:"source-taints-args" json:"source-taints-args"` // SummarizeOnDemand specifies whether the graph should build summaries on-demand instead of all at once SummarizeOnDemand bool `xml:"summarize-on-demand,attr" yaml:"summarize-on-demand" json:"summarize-on-demand"` // UnsafeMaxDepth sets a limit for the number of function call depth explored during the analysis. // The default is -1, and any value less or equal than 0 is safe: the analysis will be sound and explore call depth // without bounds. // // Setting UnsafeMaxDepth to a limit larger than 0 will yield unsound results, but can be useful to use the tool // as a checking mechanism. Limiting the call depth will usually yield fewer false positives. UnsafeMaxDepth int `xml:"unsafe-max-depth,attr" yaml:"unsafe-max-depth" json:"unsafe-max-depth"` // UnsafeIgnoreNonSummarized allows the analysis to ignore when the summary of a function has not been built in // the first analysis phase. This is only for experimentation, since the results may be unsound. // This has no effect when SummarizeOnDemand is true. UnsafeIgnoreNonSummarized bool `xml:"unsafeIgnoreNonSummarized,attr" yaml:"unsafe-ignore-non-summarized" json:"unsafe-ignore-non-summarized"` // Run and use the escape analysis for analyses that have the option to use the escape analysis results. UseEscapeAnalysis bool `xml:"use-escape-analysis,attr" yaml:"use-escape-analysis" json:"use-escape-analysis"` // contains filtered or unexported fields }
Options holds the global options for analyses
type PointerConfig ¶
type PointerConfig struct { // UnsafeNoEffectFunctions is a list of function names that produce no constraints in the pointer analysis. // Use at your own risk: using this option *may* make the analysis unsound. However, if you are confident // that the listed function does not have any effect on aliasing, adding it here may reduce false positives. UnsafeNoEffectFunctions []string `yaml:"unsafe-no-effect-functions" json:"unsafe-no-effect-functions"` // Reflection is the reflection option of the pointer analysis: when true, reflection aperators are handled // soundly, but analysis time will increase dramatically. Reflection bool }
PointerConfig is the pointer analysis specific configuration.
func NewPointerConfig ¶
func NewPointerConfig() *PointerConfig
NewPointerConfig returns a new escape config with default parameters: - the filter of no-effect functions is nil.
type SlicingSpec ¶
type SlicingSpec struct { // BacktracePoints is the list of identifiers to be considered as entrypoint functions for the backwards // dataflow analysis. BacktracePoints []CodeIdentifier // Filters contains a list of filters that can be used by analyses Filters []CodeIdentifier // SkipBoundLabels indicates whether to skip flows that go through "bound labels", i.e. aliases of the variables // bound by a closure. This can be useful to test data flows because bound labels generate a lot of false positives. SkipBoundLabels bool `yaml:"unsafe-skip-bound-labels" json:"unsafe-skip-bound-labels"` }
SlicingSpec contains code identifiers that identify a specific program slicing / backwards dataflow analysis spec.
func (SlicingSpec) IsBacktracePoint ¶
func (ss SlicingSpec) IsBacktracePoint(cid CodeIdentifier) bool
IsBacktracePoint returns true if the code identifier matches a backtrace point according to the SlicingSpec
type StaticCommandsSpec ¶
type StaticCommandsSpec struct { // StaticCommands is the list of identifiers to be considered as command execution for the static commands analysis // (not used) StaticCommands []CodeIdentifier `yaml:"static-commands" json:"static-commands"` }
StaticCommandsSpec contains code identifiers for the problem of identifying which commands are static
func (StaticCommandsSpec) IsStaticCommand ¶
func (scs StaticCommandsSpec) IsStaticCommand(cid CodeIdentifier) bool
IsStaticCommand returns true if the code identifier matches a static command specification in the config file
type TaintSpec ¶
type TaintSpec struct { // Sanitizers is the list of sanitizers for the taint analysis Sanitizers []CodeIdentifier // Validators is the list of validators for the dataflow analyses Validators []CodeIdentifier // Sinks is the list of sinks for the taint analysis Sinks []CodeIdentifier // Sources is the list of sources for the taint analysis Sources []CodeIdentifier // Filters contains a list of filters that can be used by analyses Filters []CodeIdentifier // Tag identifies a group of annotations when used with annotations Tag string // FailOnImplicitFlow indicates whether the taint analysis should fail when tainted data implicitly changes // the control flow of a program. This should be set to false when proving a data flow property, // and set to true when proving an information flow property. FailOnImplicitFlow bool `yaml:"fail-on-implicit-flow" json:"fail-on-implicit-flow"` // SkipBoundLabels indicates whether to skip flows that go through "bound labels", i.e. aliases of the variables // bound by a closure. This can be useful to test data flows because bound labels generate a lot of false positives. SkipBoundLabels bool `yaml:"unsafe-skip-bound-labels" json:"unsafe-skip-bound-labels"` }
TaintSpec contains code identifiers that identify a specific taint tracking problem, or contains a code that can differentiate groups of annotations
func (TaintSpec) IsSanitizer ¶
func (ts TaintSpec) IsSanitizer(cid CodeIdentifier) bool
IsSanitizer returns true if the code identifier matches a sanitizer specification in the config file
func (TaintSpec) IsSink ¶
func (ts TaintSpec) IsSink(cid CodeIdentifier) bool
IsSink returns true if the code identifier matches a sink specification in the config file
func (TaintSpec) IsSource ¶
func (ts TaintSpec) IsSource(cid CodeIdentifier) bool
IsSource returns true if the code identifier matches a source specification in the config file
func (TaintSpec) IsValidator ¶
func (ts TaintSpec) IsValidator(cid CodeIdentifier) bool
IsValidator returns true if the code identifier matches a validator specification in the config file