@@ -57,6 +57,12 @@ const aliasOfAllRules = "*"
57
57
58
58
var generatedCodePattern = regexp .MustCompile (`^// Code generated .* DO NOT EDIT\.$` )
59
59
60
+ // ignoreLocation keeps the location of an ignored rule
61
+ type ignoreLocation struct {
62
+ file string
63
+ line string
64
+ }
65
+
60
66
// The Context is populated with data parsed from the source code as it is scanned.
61
67
// It is passed through to all rule functions as they are called. Rules may use
62
68
// this data in conjunction with the encountered AST node.
@@ -69,7 +75,7 @@ type Context struct {
69
75
Root * ast.File
70
76
Imports * ImportTracker
71
77
Config Config
72
- Ignores [ ]map [string ][]issue.SuppressionInfo
78
+ Ignores map [ ignoreLocation ]map [string ][]issue.SuppressionInfo
73
79
PassedValues map [string ]interface {}
74
80
}
75
81
@@ -360,7 +366,7 @@ func (gosec *Analyzer) CheckAnalyzers(pkg *packages.Package) {
360
366
if result != nil {
361
367
if passIssues , ok := result .([]* issue.Issue ); ok {
362
368
for _ , iss := range passIssues {
363
- gosec .updateIssues (iss , false , []issue. SuppressionInfo {} )
369
+ gosec .updateIssues (iss )
364
370
}
365
371
}
366
372
}
@@ -521,10 +527,8 @@ func (gosec *Analyzer) ignore(n ast.Node) map[string]issue.SuppressionInfo {
521
527
// Visit runs the gosec visitor logic over an AST created by parsing go code.
522
528
// Rule methods added with AddRule will be invoked as necessary.
523
529
func (gosec * Analyzer ) Visit (n ast.Node ) ast.Visitor {
524
- ignores , ok := gosec .updateIgnoredRules (n )
525
- if ! ok {
526
- return gosec
527
- }
530
+ // Update any potentially ignored rules at the node location
531
+ gosec .updateIgnoredRules (n )
528
532
529
533
// Using ast.File instead of ast.ImportSpec, so that we can track all imports at once.
530
534
switch i := n .(type ) {
@@ -533,56 +537,55 @@ func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor {
533
537
}
534
538
535
539
for _ , rule := range gosec .ruleset .RegisteredFor (n ) {
536
- suppressions , ignored := gosec .updateSuppressions (rule .ID (), ignores )
537
540
issue , err := rule .Match (n , gosec .context )
538
541
if err != nil {
539
542
file , line := GetLocation (n , gosec .context )
540
543
file = path .Base (file )
541
544
gosec .logger .Printf ("Rule error: %v => %s (%s:%d)\n " , reflect .TypeOf (rule ), err , file , line )
542
545
}
543
- gosec .updateIssues (issue , ignored , suppressions )
546
+ gosec .updateIssues (issue )
544
547
}
545
548
return gosec
546
549
}
547
550
548
- func (gosec * Analyzer ) updateIgnoredRules (n ast.Node ) (map [string ][]issue.SuppressionInfo , bool ) {
549
- if n == nil {
550
- if len (gosec .context .Ignores ) > 0 {
551
- gosec .context .Ignores = gosec .context .Ignores [1 :]
552
- }
553
- return nil , false
554
- }
555
- // Get any new rule exclusions.
551
+ func (gosec * Analyzer ) updateIgnoredRules (n ast.Node ) {
556
552
ignoredRules := gosec .ignore (n )
557
-
558
- // Now create the union of exclusions.
559
- ignores := map [string ][]issue.SuppressionInfo {}
560
- if len (gosec .context .Ignores ) > 0 {
561
- for k , v := range gosec .context .Ignores [0 ] {
562
- ignores [k ] = v
553
+ if len (ignoredRules ) > 0 {
554
+ if gosec .context .Ignores == nil {
555
+ gosec .context .Ignores = make (map [ignoreLocation ]map [string ][]issue.SuppressionInfo )
556
+ }
557
+ line := issue .GetLine (gosec .context .FileSet .File (n .Pos ()), n )
558
+ ignoreLocation := ignoreLocation {
559
+ file : gosec .context .FileSet .File (n .Pos ()).Name (),
560
+ line : line ,
561
+ }
562
+ current , ok := gosec .context .Ignores [ignoreLocation ]
563
+ if ! ok {
564
+ current = map [string ][]issue.SuppressionInfo {}
563
565
}
566
+ for r , s := range ignoredRules {
567
+ if current [r ] == nil {
568
+ current [r ] = []issue.SuppressionInfo {}
569
+ }
570
+ current [r ] = append (current [r ], s )
571
+ }
572
+ gosec .context .Ignores [ignoreLocation ] = current
564
573
}
574
+ }
565
575
566
- for ruleID , suppression := range ignoredRules {
567
- ignores [ruleID ] = append (ignores [ruleID ], suppression )
576
+ func (gosec * Analyzer ) getSuppressionsAtLineInFile (file string , line string , id string ) ([]issue.SuppressionInfo , bool ) {
577
+ ignores , ok := gosec .context .Ignores [ignoreLocation {file : file , line : line }]
578
+ if ! ok {
579
+ ignores = make (map [string ][]issue.SuppressionInfo )
568
580
}
569
581
570
- // Push the new set onto the stack.
571
- gosec .context .Ignores = append ([]map [string ][]issue.SuppressionInfo {ignores }, gosec .context .Ignores ... )
572
-
573
- return ignores , true
574
- }
575
-
576
- func (gosec * Analyzer ) updateSuppressions (id string , ignores map [string ][]issue.SuppressionInfo ) ([]issue.SuppressionInfo , bool ) {
577
- // Check if all rules are ignored.
582
+ // Check if the rule was specifically suppressed at this location.
578
583
generalSuppressions , generalIgnored := ignores [aliasOfAllRules ]
579
- // Check if the specific rule is ignored
580
584
ruleSuppressions , ruleIgnored := ignores [id ]
581
-
582
585
ignored := generalIgnored || ruleIgnored
583
586
suppressions := append (generalSuppressions , ruleSuppressions ... )
584
587
585
- // Track external suppressions.
588
+ // Track external suppressions of this rule .
586
589
if gosec .ruleset .IsRuleSuppressed (id ) {
587
590
ignored = true
588
591
suppressions = append (suppressions , issue.SuppressionInfo {
@@ -593,8 +596,9 @@ func (gosec *Analyzer) updateSuppressions(id string, ignores map[string][]issue.
593
596
return suppressions , ignored
594
597
}
595
598
596
- func (gosec * Analyzer ) updateIssues (issue * issue.Issue , ignored bool , suppressions []issue. SuppressionInfo ) {
599
+ func (gosec * Analyzer ) updateIssues (issue * issue.Issue ) {
597
600
if issue != nil {
601
+ suppressions , ignored := gosec .getSuppressionsAtLineInFile (issue .File , issue .Line , issue .RuleID )
598
602
if gosec .showIgnored {
599
603
issue .NoSec = ignored
600
604
}
0 commit comments