Documentation
¶
Index ¶
Constants ¶
const ( AnalyzerName = "safelogging" JSONConfigFlagName = "json-config" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Analyzer ¶
type Analyzer struct {
// contains filtered or unexported fields
}
Analyzer is defined as its own struct to make it possible for an instance of analysis.Analyzer to track state across analysis runs but without using global variables/state. The "Run" function of analysis.Analyzer delegates to a method on Analyzer, which allows it to use state stored in the struct. Flag registration and config loading is also performed using member variables of the struct. This makes it easier to do things like running tests for analyzers using different flag configurations in the same run.
Clients that just want an analyzer can call "safelogging.NewAnalyzer().Analyzer()" to get an instance of an *analysis.Analyzer.
func NewAnalyzer ¶
func NewAnalyzer() *Analyzer
type CommentBasedLogSafetyTracker ¶
type CommentBasedLogSafetyTracker struct {
// contains filtered or unexported fields
}
func (*CommentBasedLogSafetyTracker) LogSafetyForIdentAtPos ¶
func (t *CommentBasedLogSafetyTracker) LogSafetyForIdentAtPos(pos token.Pos) (LogSafetyType, token.Position)
LogSafetyForIdentAtPos returns the LogSafetyType for the identifier at the given position based on comment-based annotations. Comment-based log safety annotations are defined/specified based on line number, and the provided token.Pos is used only to extract the line number. As such, different token.Pos values that refer to the same line will return the same LogSafetyType (which is the expected/desired behavior in the case where there are multiple identifiers that occur on the same line).
type Config ¶
type Config struct {
// TypeLogSafety is a map from fully qualified type name identifier to the log safety for that type.
// The safety value in this map can make a type less safe, but not more safe (for example, if a struct type is
// determined to be unsafe based on its fields, marking it as safe using this configuration will not make it safe).
// The values in this map are applied on top of the default.
TypeLogSafety *map[string]LogSafetyType `json:"type-log-safety,omitempty" mapstructure:"type-log-safety,omitempty"`
// If true, omits the default TypeLogSafety values and uses only those specified in the TypeLogSafety map.
TypeLogSafetyOmitDefaults bool `json:"type-log-safety-disable-defaults,omitempty" mapstructure:"type-log-safety-disable-defaults,omitempty"`
// StructFieldLogSafety is a map from fully qualified struct field identifier to the log safety for that field. The
// type safety for a struct is the "least safe" of all of its types/fields (recursively) and any markings or safety
// configured for the struct itself.
StructFieldLogSafety *map[string]LogSafetyType `json:"struct-field-log-safety,omitempty" mapstructure:"struct-field-log-safety,omitempty"`
// If true, omits the default StructFieldLogSafety values and uses only those specified in the StructFieldLogSafety map.
StructFieldLogSafetyOmitDefaults bool `json:"struct-field-log-safety-disable-defaults,omitempty" mapstructure:"struct-field-log-safety-disable-defaults,omitempty"`
// ConstMessageLoggingFunctions is a list of functions are checked to ensure that the parameter at a specified index
// is a constant string. Currently, the check only supports checking one parameter per function -- if the provided
// slice contains the same function multiple times, the last entry will take precedence. This configuration can add
// to the default set of functions, but cannot override them.
ConstMessageLoggingFunctions []ConstMessageLoggingFunction `json:"const-message-logging-functions,omitempty" mapstructure:"const-message-logging-functions,omitempty"`
}
type ConstMessageLoggingFunction ¶ added in v0.2.0
type FuncRef ¶
type FuncRef string
FuncRef is a reference to a specific function. Matches the string representation of *types.Func, which is of the form "func (*net/http.Client).Do(req *net/http.Request) (*net/http.Response, error)".
type FuncRefHandler ¶
type FuncRefHandler func( funcRef FuncRef, id *ast.Ident, call *ast.CallExpr, pass *analysis.Pass, logSafetyInfos *logSafetyInfoBundle, allTypesMapWithUnderlyingTypes map[types.Type]*ast.Ident, commentLogSafetyTracker *CommentBasedLogSafetyTracker, fileCommentRetriever filecomments.Retriever, param Param, )
type LogSafetyInfo ¶
type LogSafetyInfo struct {
// fully qualified identifier for entity that has safety specified
Identifier string
// Reason for safety level
Reason string
LogSafety LogSafetyType
}
func (*LogSafetyInfo) AFact ¶
func (l *LogSafetyInfo) AFact()
func (*LogSafetyInfo) String ¶
func (l *LogSafetyInfo) String() string
type LogSafetyType ¶
type LogSafetyType int
const ( LogSafetyTypeUnmarked LogSafetyType = iota LogSafetyTypeSafe LogSafetyTypeUnsafe LogSafetyTypeDoNotLog )
func (LogSafetyType) MarshalJSON ¶
func (t LogSafetyType) MarshalJSON() ([]byte, error)
func (LogSafetyType) String ¶
func (t LogSafetyType) String() string
func (*LogSafetyType) UnmarshalJSON ¶
func (t *LogSafetyType) UnmarshalJSON(data []byte) error
type PackageTypeLogSafetyInfo ¶
type PackageTypeLogSafetyInfo struct {
// TypeRepToTypeToLogSafety is a 2-level nested map. The outer map is a map from the fmt.Sprintf("%T", types.Type)
// to a map from the String() representation of a types.Type to its LogSafetyInfo.
//
// For the purposes of this check, the information that is most relevant is the log safety of a types.Type.
// It would be most straightforward to represent this as a map from types.Type to LogSafetyInfo.
//
// However, facts need to be serializable, and types.Type is an interface that is not serializable. As a proxy for
// this, the String() representation of the type is used as a key, which results in a map from string to
// LogSafetyInfo. An analysis pass has a collection of types.Type values for the pass, so it is possible to match
// the string representation back to a types.Type.
//
// This poses a different problem: computing the String() representation of a types.Type can be expensive.
// Furthermore, the total number of types in a pass can be quite large (10k+), as it includes all types that can be
// referenced by the package for the pass (including from all its dependencies). On the other hand, the number of
// types that declare type safety is usually much smaller (typically <100). Because of this, converting all of the
// types in a pass to their String() representation to match against the map keys can be quite inefficient.
//
// In order to reduce the search space, the types are bucketed based on the actual concrete type of the types.Type
// (for example, *types.Struct, *types.Named, *types.Pointer, etc.). In practice, most types with type safety are
// a *types.Named, but a pass can have many thousands of other types, so this bucketing can significantly reduce the
// search space.
TypeRepToTypeToLogSafety map[string]map[string]LogSafetyInfo
}
func (*PackageTypeLogSafetyInfo) AFact ¶
func (t *PackageTypeLogSafetyInfo) AFact()
func (*PackageTypeLogSafetyInfo) String ¶
func (t *PackageTypeLogSafetyInfo) String() string