Skip to content

Commit

Permalink
Restrict the maximum depth when tracking the slice bounds
Browse files Browse the repository at this point in the history
Signed-off-by: Cosmin Cojocar <[email protected]>
  • Loading branch information
ccojocar committed Oct 13, 2023
1 parent 7e2d8d3 commit f338a98
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 10 deletions.
2 changes: 1 addition & 1 deletion analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ func (gosec *Analyzer) CheckAnalyzers(pkg *packages.Package) {
// buildSSA runs the SSA pass which builds the SSA representation of the package. It handles gracefully any panic.
func (gosec *Analyzer) buildSSA(pkg *packages.Package) (interface{}, error) {
defer func() {
if r := recover(); r = nil {
if r := recover(); r != nil {
gosec.logger.Printf("Panic when running SSA analyser on package: %s", pkg.Name)
}
}()
Expand Down
28 changes: 19 additions & 9 deletions analyzers/slice_bounds.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const (
upperBounded
)

const maxDepth = 20

func newSliceBoundsAnalyzer(id string, description string) *analysis.Analyzer {
return &analysis.Analyzer{
Name: id,
Expand Down Expand Up @@ -75,7 +77,7 @@ func runSliceBounds(pass *analysis.Pass) (interface{}, error) {
l, h := extractSliceBounds(slice)
newCap := computeSliceNewCap(l, h, sliceCap)
violations := []ssa.Instruction{}
trackSliceBounds(newCap, slice, &violations, ifs)
trackSliceBounds(0, newCap, slice, &violations, ifs)
for _, s := range violations {
switch s := s.(type) {
case *ssa.Slice:
Expand Down Expand Up @@ -155,7 +157,11 @@ func runSliceBounds(pass *analysis.Pass) (interface{}, error) {
return nil, nil
}

func trackSliceBounds(sliceCap int, slice ssa.Node, violations *[]ssa.Instruction, ifs map[ssa.If]*ssa.BinOp) {
func trackSliceBounds(depth int, sliceCap int, slice ssa.Node, violations *[]ssa.Instruction, ifs map[ssa.If]*ssa.BinOp) {
if depth == maxDepth {
return
}
depth++
if violations == nil {
violations = &[]ssa.Instruction{}
}
Expand All @@ -164,12 +170,12 @@ func trackSliceBounds(sliceCap int, slice ssa.Node, violations *[]ssa.Instructio
for _, refinstr := range *referrers {
switch refinstr := refinstr.(type) {
case *ssa.Slice:
checkAllSlicesBounds(sliceCap, refinstr, violations, ifs)
checkAllSlicesBounds(depth, sliceCap, refinstr, violations, ifs)
switch refinstr.X.(type) {
case *ssa.Alloc, *ssa.Parameter:
l, h := extractSliceBounds(refinstr)
newCap := computeSliceNewCap(l, h, sliceCap)
trackSliceBounds(newCap, refinstr, violations, ifs)
trackSliceBounds(depth, newCap, refinstr, violations, ifs)
}
case *ssa.IndexAddr:
indexValue, err := extractIntValue(refinstr.Index.String())
Expand All @@ -189,7 +195,7 @@ func trackSliceBounds(sliceCap int, slice ssa.Node, violations *[]ssa.Instructio
if fn, ok := refinstr.Call.Value.(*ssa.Function); ok {
if len(fn.Params) > parPos && parPos > -1 {
param := fn.Params[parPos]
trackSliceBounds(sliceCap, param, violations, ifs)
trackSliceBounds(depth, sliceCap, param, violations, ifs)
}
}
}
Expand All @@ -198,7 +204,11 @@ func trackSliceBounds(sliceCap int, slice ssa.Node, violations *[]ssa.Instructio
}
}

func checkAllSlicesBounds(sliceCap int, slice *ssa.Slice, violations *[]ssa.Instruction, ifs map[ssa.If]*ssa.BinOp) {
func checkAllSlicesBounds(depth int, sliceCap int, slice *ssa.Slice, violations *[]ssa.Instruction, ifs map[ssa.If]*ssa.BinOp) {
if depth == maxDepth {
return
}
depth++
if violations == nil {
violations = &[]ssa.Instruction{}
}
Expand All @@ -210,7 +220,7 @@ func checkAllSlicesBounds(sliceCap int, slice *ssa.Slice, violations *[]ssa.Inst
case *ssa.Alloc, *ssa.Parameter, *ssa.Slice:
l, h := extractSliceBounds(slice)
newCap := computeSliceNewCap(l, h, sliceCap)
trackSliceBounds(newCap, slice, violations, ifs)
trackSliceBounds(depth, newCap, slice, violations, ifs)
}

references := slice.Referrers()
Expand All @@ -220,12 +230,12 @@ func checkAllSlicesBounds(sliceCap int, slice *ssa.Slice, violations *[]ssa.Inst
for _, ref := range *references {
switch s := ref.(type) {
case *ssa.Slice:
checkAllSlicesBounds(sliceCap, s, violations, ifs)
checkAllSlicesBounds(depth, sliceCap, s, violations, ifs)
switch s.X.(type) {
case *ssa.Alloc, *ssa.Parameter:
l, h := extractSliceBounds(s)
newCap := computeSliceNewCap(l, h, sliceCap)
trackSliceBounds(newCap, s, violations, ifs)
trackSliceBounds(depth, newCap, s, violations, ifs)
}
}
}
Expand Down

0 comments on commit f338a98

Please sign in to comment.