@@ -57,6 +57,12 @@ const aliasOfAllRules = "*"
5757
5858var  generatedCodePattern  =  regexp .MustCompile (`^// Code generated .* DO NOT EDIT\.$` )
5959
60+ // ignoreLocation keeps the location of an ignored rule 
61+ type  ignoreLocation  struct  {
62+ 	file  string 
63+ 	line  string 
64+ }
65+ 
6066// The Context is populated with data parsed from the source code as it is scanned. 
6167// It is passed through to all rule functions as they are called. Rules may use 
6268// this data in conjunction with the encountered AST node. 
@@ -69,7 +75,7 @@ type Context struct {
6975	Root          * ast.File 
7076	Imports       * ImportTracker 
7177	Config        Config 
72- 	Ignores       [ ]map [string ][]issue.SuppressionInfo 
78+ 	Ignores       map [ ignoreLocation ]map [string ][]issue.SuppressionInfo 
7379	PassedValues  map [string ]interface {}
7480}
7581
@@ -360,7 +366,7 @@ func (gosec *Analyzer) CheckAnalyzers(pkg *packages.Package) {
360366		if  result  !=  nil  {
361367			if  passIssues , ok  :=  result .([]* issue.Issue ); ok  {
362368				for  _ , iss  :=  range  passIssues  {
363- 					gosec .updateIssues (iss ,  false , []issue. SuppressionInfo {} )
369+ 					gosec .updateIssues (iss )
364370				}
365371			}
366372		}
@@ -521,10 +527,8 @@ func (gosec *Analyzer) ignore(n ast.Node) map[string]issue.SuppressionInfo {
521527// Visit runs the gosec visitor logic over an AST created by parsing go code. 
522528// Rule methods added with AddRule will be invoked as necessary. 
523529func  (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 )
528532
529533	// Using ast.File instead of ast.ImportSpec, so that we can track all imports at once. 
530534	switch  i  :=  n .(type ) {
@@ -533,56 +537,55 @@ func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor {
533537	}
534538
535539	for  _ , rule  :=  range  gosec .ruleset .RegisteredFor (n ) {
536- 		suppressions , ignored  :=  gosec .updateSuppressions (rule .ID (), ignores )
537540		issue , err  :=  rule .Match (n , gosec .context )
538541		if  err  !=  nil  {
539542			file , line  :=  GetLocation (n , gosec .context )
540543			file  =  path .Base (file )
541544			gosec .logger .Printf ("Rule error: %v => %s (%s:%d)\n " , reflect .TypeOf (rule ), err , file , line )
542545		}
543- 		gosec .updateIssues (issue ,  ignored ,  suppressions )
546+ 		gosec .updateIssues (issue )
544547	}
545548	return  gosec 
546549}
547550
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 ) {
556552	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 {}
563565		}
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 
564573	}
574+ }
565575
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 )
568580	}
569581
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. 
578583	generalSuppressions , generalIgnored  :=  ignores [aliasOfAllRules ]
579- 	// Check if the specific rule is ignored 
580584	ruleSuppressions , ruleIgnored  :=  ignores [id ]
581- 
582585	ignored  :=  generalIgnored  ||  ruleIgnored 
583586	suppressions  :=  append (generalSuppressions , ruleSuppressions ... )
584587
585- 	// Track external suppressions. 
588+ 	// Track external suppressions of this rule . 
586589	if  gosec .ruleset .IsRuleSuppressed (id ) {
587590		ignored  =  true 
588591		suppressions  =  append (suppressions , issue.SuppressionInfo {
@@ -593,8 +596,9 @@ func (gosec *Analyzer) updateSuppressions(id string, ignores map[string][]issue.
593596	return  suppressions , ignored 
594597}
595598
596- func  (gosec  * Analyzer ) updateIssues (issue  * issue.Issue ,  ignored   bool ,  suppressions  []issue. SuppressionInfo ) {
599+ func  (gosec  * Analyzer ) updateIssues (issue  * issue.Issue ) {
597600	if  issue  !=  nil  {
601+ 		suppressions , ignored  :=  gosec .getSuppressionsAtLineInFile (issue .File , issue .Line , issue .RuleID )
598602		if  gosec .showIgnored  {
599603			issue .NoSec  =  ignored 
600604		}
0 commit comments