@@ -33,7 +33,7 @@ public static class AttackSurfaceAnalyzerClient
3333 private static readonly List < BaseMonitor > monitors = new List < BaseMonitor > ( ) ;
3434 private static List < BaseCompare > comparators = new List < BaseCompare > ( ) ;
3535
36- public static DatabaseManager DatabaseManager { get ; private set ; }
36+ public static DatabaseManager ? DatabaseManager { get ; private set ; }
3737
3838 private static void SetupLogging ( CommandOptions opts )
3939 {
@@ -197,7 +197,12 @@ private static ASA_ERROR RunGuidedModeCommand(GuidedModeCommandOptions opts)
197197
198198 public static ConcurrentDictionary < ( RESULT_TYPE , CHANGE_TYPE ) , List < CompareResult > > AnalyzeMonitored ( CompareCommandOptions opts )
199199 {
200- if ( opts is null ) { return new ConcurrentDictionary < ( RESULT_TYPE , CHANGE_TYPE ) , List < CompareResult > > ( ) ; }
200+ if ( DatabaseManager is null )
201+ {
202+ Log . Error ( "Err_DatabaseManagerNull" , "InsertCompareResults" ) ;
203+ return new ConcurrentDictionary < ( RESULT_TYPE , CHANGE_TYPE ) , List < CompareResult > > ( ) ;
204+ }
205+ if ( opts is null || opts . SecondRunId is null ) { return new ConcurrentDictionary < ( RESULT_TYPE , CHANGE_TYPE ) , List < CompareResult > > ( ) ; }
201206 var analyzer = new AsaAnalyzer ( new AnalyzerOptions ( opts . RunScripts ) ) ;
202207 return AnalyzeMonitored ( opts , analyzer , DatabaseManager . GetMonitorResults ( opts . SecondRunId ) , opts . AnalysesFile ?? throw new ArgumentNullException ( nameof ( opts . AnalysesFile ) ) ) ;
203208 }
@@ -257,6 +262,11 @@ private static ASA_ERROR RunVerifyRulesCommand(VerifyOptions opts)
257262
258263 internal static void InsertCompareResults ( ConcurrentDictionary < ( RESULT_TYPE , CHANGE_TYPE ) , List < CompareResult > > results , string ? FirstRunId , string SecondRunId , string AnalysesHash )
259264 {
265+ if ( DatabaseManager is null )
266+ {
267+ Log . Error ( "Err_DatabaseManagerNull" , "InsertCompareResults" ) ;
268+ return ;
269+ }
260270 DatabaseManager . InsertCompareRun ( FirstRunId , SecondRunId , AnalysesHash , RUN_STATUS . RUNNING ) ;
261271 foreach ( var key in results . Keys )
262272 {
@@ -331,7 +341,11 @@ private static ASA_ERROR RunConfigCommand(ConfigCommandOptions opts)
331341 else
332342 {
333343 SetupDatabase ( opts ) ;
334-
344+ if ( DatabaseManager is null )
345+ {
346+ Log . Error ( "Err_DatabaseManagerNull" , "RunConfigCommand" ) ;
347+ return ASA_ERROR . DATABASE_NULL ;
348+ }
335349 if ( opts . ListRuns )
336350 {
337351 if ( DatabaseManager . FirstRun )
@@ -408,6 +422,11 @@ private static ASA_ERROR RunConfigCommand(ConfigCommandOptions opts)
408422
409423 private static ASA_ERROR RunExportCollectCommand ( ExportCollectCommandOptions opts )
410424 {
425+ if ( DatabaseManager is null )
426+ {
427+ Log . Error ( "Err_DatabaseManagerNull" , "RunExportCollectCommand" ) ;
428+ return ASA_ERROR . DATABASE_NULL ;
429+ }
411430 if ( opts . OutputPath != null && ! Directory . Exists ( opts . OutputPath ) )
412431 {
413432 Log . Fatal ( Strings . Get ( "Err_OutputPathNotExist" ) , opts . OutputPath ) ;
@@ -611,6 +630,11 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
611630
612631 private static ASA_ERROR RunExportMonitorCommand ( ExportMonitorCommandOptions opts )
613632 {
633+ if ( DatabaseManager is null )
634+ {
635+ Log . Error ( "Err_DatabaseManagerNull" , "RunExportMonitorCommand" ) ;
636+ return ASA_ERROR . DATABASE_NULL ;
637+ }
614638 if ( opts . RunId is null )
615639 {
616640 var runIds = DatabaseManager . GetLatestRunIds ( 1 , RUN_TYPE . MONITOR ) ;
@@ -644,6 +668,11 @@ private static ASA_ERROR RunExportMonitorCommand(ExportMonitorCommandOptions opt
644668
645669 public static void WriteMonitorJson ( string RunId , int ResultType , string OutputPath )
646670 {
671+ if ( DatabaseManager is null )
672+ {
673+ Log . Error ( "Err_DatabaseManagerNull" , "WriteMonitorJson" ) ;
674+ return ;
675+ }
647676 var invalidFileNameChars = Path . GetInvalidPathChars ( ) . ToList ( ) ;
648677 OutputPath = new string ( OutputPath . Select ( ch => invalidFileNameChars . Contains ( ch ) ? Convert . ToChar ( invalidFileNameChars . IndexOf ( ch ) + 65 ) : ch ) . ToArray ( ) ) ;
649678
@@ -672,6 +701,11 @@ public static void WriteMonitorJson(string RunId, int ResultType, string OutputP
672701
673702 private static ASA_ERROR RunMonitorCommand ( MonitorCommandOptions opts )
674703 {
704+ if ( DatabaseManager is null )
705+ {
706+ Log . Error ( "Err_DatabaseManagerNull" , "RunMonitorCommand" ) ;
707+ return ASA_ERROR . DATABASE_NULL ;
708+ }
675709 if ( opts . RunId is string )
676710 {
677711 opts . RunId = opts . RunId . Trim ( ) ;
@@ -742,7 +776,7 @@ private static ASA_ERROR RunMonitorCommand(MonitorCommandOptions opts)
742776 }
743777 }
744778
745- void consoleCancelDelegate ( object sender , ConsoleCancelEventArgs args )
779+ void consoleCancelDelegate ( object ? sender , ConsoleCancelEventArgs args )
746780 {
747781 args . Cancel = true ;
748782 exitEvent . Set ( ) ;
@@ -804,7 +838,11 @@ public static List<BaseCompare> GetComparators()
804838 {
805839 throw new ArgumentNullException ( nameof ( opts ) ) ;
806840 }
807-
841+ if ( DatabaseManager is null )
842+ {
843+ Log . Error ( "Err_DatabaseManagerNull" , "CompareRuns" ) ;
844+ return new ConcurrentDictionary < ( RESULT_TYPE , CHANGE_TYPE ) , List < CompareResult > > ( ) ;
845+ }
808846 comparators = new List < BaseCompare > ( ) ;
809847
810848 Dictionary < string , string > EndEvent = new Dictionary < string , string > ( ) ;
@@ -827,58 +865,70 @@ public static List<BaseCompare> GetComparators()
827865
828866 if ( ! opts . DisableAnalysis )
829867 {
830- watch = Stopwatch . StartNew ( ) ;
831- var analyzer = new AsaAnalyzer ( new AnalyzerOptions ( opts . RunScripts ) ) ;
832- var platform = DatabaseManager . RunIdToPlatform ( opts . SecondRunId ) ;
833- var violations = analyzer . EnumerateRuleIssues ( opts . AnalysesFile . GetRules ( ) ) ;
834- OAT . Utils . Strings . Setup ( ) ;
835- OAT . Utils . Helpers . PrintViolations ( violations ) ;
836- if ( violations . Any ( ) )
837- {
838- Log . Error ( "Encountered {0} issues with rules in {1}. Skipping analysis." , violations . Count ( ) , opts . AnalysesFile . Source ?? "Embedded" ) ;
839- }
840- else
868+ if ( opts . AnalysesFile is not null )
841869 {
842- if ( c . Results . Count > 0 )
870+ watch = Stopwatch . StartNew ( ) ;
871+ var analyzer = new AsaAnalyzer ( new AnalyzerOptions ( opts . RunScripts ) ) ;
872+ var platform = DatabaseManager . RunIdToPlatform ( opts . SecondRunId ) ;
873+ var violations = analyzer . EnumerateRuleIssues ( opts . AnalysesFile . GetRules ( ) ) ;
874+ OAT . Utils . Strings . Setup ( ) ;
875+ OAT . Utils . Helpers . PrintViolations ( violations ) ;
876+ if ( violations . Any ( ) )
877+ {
878+ Log . Error ( "Encountered {0} issues with rules in {1}. Skipping analysis." , violations . Count ( ) , opts . AnalysesFile ? . Source ?? "Embedded" ) ;
879+ }
880+ else
843881 {
844- foreach ( var key in c . Results . Keys )
882+ if ( c . Results . Count > 0 )
845883 {
846- if ( c . Results [ key ] is List < CompareResult > queue )
884+ foreach ( var key in c . Results . Keys )
847885 {
848- queue . AsParallel ( ) . ForAll ( res =>
886+ if ( c . Results [ key ] is List < CompareResult > queue )
849887 {
850- // Select rules with the appropriate change type, platform and target
851- // - Target is also checked inside Analyze, but this shortcuts repeatedly
852- // checking rules which don't apply
853- var selectedRules = opts . AnalysesFile . Rules . Where ( ( rule ) =>
854- ( rule . ChangeTypes == null || rule . ChangeTypes . Contains ( res . ChangeType ) )
855- && ( rule . Platforms == null || rule . Platforms . Contains ( platform ) )
856- && ( rule . ResultType == res . ResultType ) ) ;
857- res . Rules = analyzer . Analyze ( selectedRules , res . Base , res . Compare ) . ToList ( ) ;
858- res . Analysis = res . Rules . Count
859- > 0 ? res . Rules . Max ( x => ( ( AsaRule ) x ) . Flag ) : opts . AnalysesFile . DefaultLevels [ res . ResultType ] ;
860- res . AnalysesHash = opts . AnalysesFile . GetHash ( ) ;
861- } ) ;
888+ queue . AsParallel ( ) . ForAll ( res =>
889+ {
890+ // Select rules with the appropriate change type, platform and target
891+ // - Target is also checked inside Analyze, but this shortcuts repeatedly
892+ // checking rules which don't apply
893+ var selectedRules = opts . AnalysesFile . Rules . Where ( ( rule ) =>
894+ ( rule . ChangeTypes == null || rule . ChangeTypes . Contains ( res . ChangeType ) )
895+ && ( rule . Platforms == null || rule . Platforms . Contains ( platform ) )
896+ && ( rule . ResultType == res . ResultType ) ) ;
897+ res . Rules = analyzer . Analyze ( selectedRules , res . Base , res . Compare ) . ToList ( ) ;
898+ res . Analysis = res . Rules . Count
899+ > 0 ? res . Rules . Max ( x => ( ( AsaRule ) x ) . Flag ) : opts . AnalysesFile . DefaultLevels [ res . ResultType ] ;
900+ res . AnalysesHash = opts . AnalysesFile . GetHash ( ) ;
901+ } ) ;
902+ }
862903 }
863904 }
864905 }
865- }
866906
867- watch . Stop ( ) ;
868- t = TimeSpan . FromMilliseconds ( watch . ElapsedMilliseconds ) ;
869- answer = string . Format ( CultureInfo . InvariantCulture , "{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms" ,
870- t . Hours ,
871- t . Minutes ,
872- t . Seconds ,
873- t . Milliseconds ) ;
874- Log . Information ( Strings . Get ( "Completed" ) , "Analysis" , answer ) ;
907+ watch . Stop ( ) ;
908+ t = TimeSpan . FromMilliseconds ( watch . ElapsedMilliseconds ) ;
909+ answer = string . Format ( CultureInfo . InvariantCulture , "{0:D2}h:{1:D2}m:{2:D2}s:{3:D3}ms" ,
910+ t . Hours ,
911+ t . Minutes ,
912+ t . Seconds ,
913+ t . Milliseconds ) ;
914+ Log . Information ( Strings . Get ( "Completed" ) , "Analysis" , answer ) ;
915+ }
916+ else
917+ {
918+ Log . Error ( Strings . Get ( "Err_AnalysisNull" ) ) ;
919+ }
875920 }
876921
877922 return c . Results ;
878923 }
879924
880925 public static ASA_ERROR RunGuiMonitorCommand ( MonitorCommandOptions opts )
881926 {
927+ if ( DatabaseManager is null )
928+ {
929+ Log . Error ( "Err_DatabaseManagerNull" , "RunGuiMonitorCommand" ) ;
930+ return ASA_ERROR . DATABASE_NULL ;
931+ }
882932 if ( opts is null )
883933 {
884934 return ASA_ERROR . NO_COLLECTORS ;
@@ -894,7 +944,7 @@ public static ASA_ERROR RunGuiMonitorCommand(MonitorCommandOptions opts)
894944 {
895945 Log . Warning ( Strings . Get ( "Err_NoMonitors" ) ) ;
896946 }
897- var run = new AsaRun ( RunId : opts . RunId , Timestamp : DateTime . Now , Version : AsaHelpers . GetVersionString ( ) , Platform : AsaHelpers . GetPlatform ( ) , ResultTypes : setResultTypes , Type : RUN_TYPE . MONITOR ) ;
947+ var run = new AsaRun ( RunId : opts ? . RunId ?? string . Empty , Timestamp : DateTime . Now , Version : AsaHelpers . GetVersionString ( ) , Platform : AsaHelpers . GetPlatform ( ) , ResultTypes : setResultTypes , Type : RUN_TYPE . MONITOR ) ;
898948
899949 DatabaseManager . InsertRun ( run ) ;
900950 foreach ( var c in monitors )
@@ -907,6 +957,7 @@ public static ASA_ERROR RunGuiMonitorCommand(MonitorCommandOptions opts)
907957
908958 public static int StopMonitors ( )
909959 {
960+
910961 foreach ( var c in monitors )
911962 {
912963 Log . Information ( Strings . Get ( "End" ) , c . GetType ( ) . Name ) ;
@@ -916,6 +967,12 @@ public static int StopMonitors()
916967
917968 FlushResults ( ) ;
918969
970+ if ( DatabaseManager is null )
971+ {
972+ Log . Error ( "Err_DatabaseManagerNull" , "RunGuiMonitorCommand" ) ;
973+ return ( int ) ASA_ERROR . DATABASE_NULL ;
974+ }
975+
919976 DatabaseManager . Commit ( ) ;
920977
921978 return 0 ;
@@ -948,6 +1005,11 @@ public static void AdminOrWarn()
9481005
9491006 public static ASA_ERROR RunCollectCommand ( CollectCommandOptions opts )
9501007 {
1008+ if ( DatabaseManager is null )
1009+ {
1010+ Log . Error ( "Err_DatabaseManagerNull" , "RunCollectCommand" ) ;
1011+ return ASA_ERROR . DATABASE_NULL ;
1012+ }
9511013 if ( opts == null ) { return ASA_ERROR . NO_COLLECTORS ; }
9521014 collectors . Clear ( ) ;
9531015 AdminOrWarn ( ) ;
@@ -1123,11 +1185,19 @@ public static ASA_ERROR RunCollectCommand(CollectCommandOptions opts)
11231185 using CancellationTokenSource source = new CancellationTokenSource ( ) ;
11241186 CancellationToken token = source . Token ;
11251187
1126- void cancelKeyDelegate ( object sender , ConsoleCancelEventArgs args )
1188+ void cancelKeyDelegate ( object ? sender , ConsoleCancelEventArgs args )
11271189 {
11281190 Log . Information ( "Cancelling collection. Rolling back transaction. Please wait to avoid corrupting database." ) ;
11291191 source . Cancel ( ) ;
1130- DatabaseManager . CloseDatabase ( ) ;
1192+
1193+ if ( DatabaseManager is null )
1194+ {
1195+ Log . Error ( "Err_DatabaseManagerNull" , "InsertCompareResults" ) ;
1196+ }
1197+ else
1198+ {
1199+ DatabaseManager . CloseDatabase ( ) ;
1200+ }
11311201 Environment . Exit ( ( int ) ASA_ERROR . CANCELLED ) ;
11321202 }
11331203 Console . CancelKeyPress += cancelKeyDelegate ;
@@ -1163,6 +1233,10 @@ void cancelKeyDelegate(object sender, ConsoleCancelEventArgs args)
11631233
11641234 private static void FlushResults ( )
11651235 {
1236+ if ( DatabaseManager is null )
1237+ {
1238+ return ;
1239+ }
11661240 var prevFlush = DatabaseManager . QueueSize ;
11671241 var totFlush = prevFlush ;
11681242
0 commit comments