@@ -35,6 +35,8 @@ import (
3535
3636 "golang.org/x/tools/go/analysis"
3737 "golang.org/x/tools/go/analysis/passes/buildssa"
38+ "golang.org/x/tools/go/analysis/passes/ctrlflow"
39+ "golang.org/x/tools/go/analysis/passes/inspect"
3840 "golang.org/x/tools/go/packages"
3941
4042 "github.com/securego/gosec/v2/analyzers"
@@ -430,7 +432,7 @@ func (gosec *Analyzer) CheckAnalyzers(pkg *packages.Package) {
430432 buildssa .Analyzer : & analyzers.SSAAnalyzerResult {
431433 Config : gosec .Config (),
432434 Logger : gosec .logger ,
433- SSA : ssaResult .( * buildssa. SSA ) ,
435+ SSA : ssaResult ,
434436 },
435437 }
436438
@@ -491,7 +493,7 @@ func (gosec *Analyzer) generatedFiles(pkg *packages.Package) map[string]bool {
491493}
492494
493495// buildSSA runs the SSA pass which builds the SSA representation of the package. It handles gracefully any panic.
494- func (gosec * Analyzer ) buildSSA (pkg * packages.Package ) (interface {} , error ) {
496+ func (gosec * Analyzer ) buildSSA (pkg * packages.Package ) (* buildssa. SSA , error ) {
495497 defer func () {
496498 if r := recover (); r != nil {
497499 gosec .logger .Printf (
@@ -500,26 +502,62 @@ func (gosec *Analyzer) buildSSA(pkg *packages.Package) (interface{}, error) {
500502 )
501503 }
502504 }()
503- ssaPass := & analysis.Pass {
504- Analyzer : buildssa .Analyzer ,
505- Fset : pkg .Fset ,
506- Files : pkg .Syntax ,
507- OtherFiles : pkg .OtherFiles ,
508- IgnoredFiles : pkg .IgnoredFiles ,
509- Pkg : pkg .Types ,
510- TypesInfo : pkg .TypesInfo ,
511- TypesSizes : pkg .TypesSizes ,
512- ResultOf : nil ,
513- Report : nil ,
514- ImportObjectFact : nil ,
515- ExportObjectFact : nil ,
516- ImportPackageFact : nil ,
517- ExportPackageFact : nil ,
518- AllObjectFacts : nil ,
519- AllPackageFacts : nil ,
520- }
521-
522- return ssaPass .Analyzer .Run (ssaPass )
505+ if pkg == nil {
506+ return nil , errors .New ("nil package provided" )
507+ }
508+ if pkg .Types == nil {
509+ return nil , fmt .Errorf ("package %s has no type information (compilation failed?)" , pkg .Name )
510+ }
511+ if pkg .TypesInfo == nil {
512+ return nil , fmt .Errorf ("package %s has no type information" , pkg .Name )
513+ }
514+ // The SSA and CtrlFlow builders require architecture sizing (WordSize/MaxAlign).
515+ // If go/packages didn't provide it, we MUST provide a default to prevent panics.
516+ typesSizes := pkg .TypesSizes
517+ if typesSizes == nil {
518+ // Fallback to standard 64-bit sizes (WordSize: 8, MaxAlign: 8)
519+ // This is safe for most analysis contexts.
520+ typesSizes = & types.StdSizes {WordSize : 8 , MaxAlign : 8 }
521+ }
522+ pass := & analysis.Pass {
523+ Fset : pkg .Fset ,
524+ Files : pkg .Syntax ,
525+ OtherFiles : pkg .OtherFiles ,
526+ IgnoredFiles : pkg .IgnoredFiles ,
527+ Pkg : pkg .Types ,
528+ TypesInfo : pkg .TypesInfo ,
529+ TypesSizes : pkg .TypesSizes ,
530+ ResultOf : make (map [* analysis.Analyzer ]interface {}),
531+ Report : func (d analysis.Diagnostic ) {},
532+ ImportObjectFact : func (obj types.Object , fact analysis.Fact ) bool { return false },
533+ ExportObjectFact : func (obj types.Object , fact analysis.Fact ) {},
534+ }
535+
536+ pass .Analyzer = inspect .Analyzer
537+ i , err := inspect .Analyzer .Run (pass )
538+ if err != nil {
539+ return nil , fmt .Errorf ("running inspect analysis: %w" , err )
540+ }
541+ pass .ResultOf [inspect .Analyzer ] = i
542+
543+ pass .Analyzer = ctrlflow .Analyzer
544+ cf , err := ctrlflow .Analyzer .Run (pass )
545+ if err != nil {
546+ return nil , fmt .Errorf ("running control flow analysis: %w" , err )
547+ }
548+ pass .ResultOf [ctrlflow .Analyzer ] = cf
549+
550+ pass .Analyzer = buildssa .Analyzer
551+ result , err := buildssa .Analyzer .Run (pass )
552+ if err != nil {
553+ return nil , fmt .Errorf ("running SSA analysis: %w" , err )
554+ }
555+
556+ ssaResult , ok := result .(* buildssa.SSA )
557+ if ! ok {
558+ return nil , fmt .Errorf ("unexpected SSA analysis result type: %T" , result )
559+ }
560+ return ssaResult , nil
523561}
524562
525563// ParseErrors parses the errors from given package
0 commit comments