private void Verify(string analyzerPath, IEnumerable <string> expectedMessages, params string[] assemblyPaths)
        {
            var actualMessages = new List <string>();
            var analyzer       = ILDiagnosticsAnalyzer.Create(this.GetType().Assembly.Location);

            foreach (string assemblyPath in assemblyPaths)
            {
                analyzer.Analyze(assemblyPath, (d) => actualMessages.Add(d.GetMessage()));
            }

            try
            {
                actualMessages.ShouldBeEquivalentTo(expectedMessages);
            }
            catch
            {
                _testOutputHelper.WriteLine("Expected messages:");
                foreach (string message in expectedMessages)
                {
                    _testOutputHelper.WriteLine("\"" + message + "\",");
                }

                _testOutputHelper.WriteLine("Actual messages:");
                foreach (string message in actualMessages)
                {
                    _testOutputHelper.WriteLine("\"" + message + "\",");
                }

                throw;
            }
        }
Ejemplo n.º 2
0
        private void AnalyzeManagedAssembly(string assemblyFilePath, IEnumerable <string> roslynAnalyzerFilePaths, BinaryAnalyzerContext context)
        {
            if (roslynAnalyzerFilePaths == null)
            {
                return;
            }

            if (_globalRoslynAnalysisContext == null)
            {
                _globalRoslynAnalysisContext = new RoslynAnalysisContext();

                // We could use the ILDiagnosticsAnalyzer factory method that initializes
                // an object instance from an enumerable collection of analyzer paths. We
                // initialize a context object from each path one-by-one instead, in order
                // to make an attempt to load each specified analyzer. We will therefore
                // collect information on each analyzer that fails to load. We will also
                // proceed with performing as much analysis as possible. Ultimately, a
                // single analyzer load failure will return in BinSkim returning a non-zero
                // failure code from the run.
                foreach (string analyzerFilePath in roslynAnalyzerFilePaths)
                {
                    InvokeCatchingRelevantIOExceptions
                    (
                        action: () => { ILDiagnosticsAnalyzer.LoadAnalyzer(analyzerFilePath, _globalRoslynAnalysisContext); },
                        exceptionHandler: (ex) =>
                    {
                        Errors.LogExceptionLoadingPlugin(analyzerFilePath, context, ex);
                    }
                    );
                }
            }

            Debug.Assert(context.MimeType == Sarif.Writers.MimeType.Binary);

            ILDiagnosticsAnalyzer roslynAnalyzer = ILDiagnosticsAnalyzer.Create(_globalRoslynAnalysisContext);

            roslynAnalyzer.Analyze(assemblyFilePath, diagnostic =>
            {
                // 0. Populate various members
                var result     = new Result();
                result.Level   = diagnostic.Severity.ConvertToResultLevel();
                result.Message = new Message {
                    Text = diagnostic.GetMessage()
                };

                if (diagnostic.IsSuppressed)
                {
                    result.SuppressionStates = SuppressionStates.SuppressedInSource;
                }

                result.SetProperty("Severity", diagnostic.Severity.ToString());
                result.SetProperty("IsWarningAsError", diagnostic.IsWarningAsError.ToString());
                result.SetProperty("WarningLevel", diagnostic.WarningLevel.ToString());

                foreach (string key in diagnostic.Properties.Keys)
                {
                    string value;
                    if (result.TryGetProperty(key, out value))
                    {
                        // If the properties bag recapitulates one of the values set
                        // previously, we'll retain the already set value
                        continue;
                    }
                    result.SetProperty(key, diagnostic.Properties[key]);
                }

                result.Locations = new List <Sarif.Location>();

                // 1. Record the assembly under analysis
                result.AnalysisTarget = new ArtifactLocation {
                    Uri = new Uri(assemblyFilePath)
                };

                // 2. Record the actual location associated with the result
                var region = diagnostic.Location.ConvertToRegion();
                string filePath;
                PhysicalLocation resultFile = null;

                if (diagnostic.Location != Location.None)
                {
                    filePath = diagnostic.Location.GetLineSpan().Path;

                    resultFile = new PhysicalLocation
                    {
                        ArtifactLocation = { Uri = new Uri(filePath) },
                        Region           = region
                    };
                }

                result.Locations.Add(new Sarif.Location()
                {
                    PhysicalLocation = resultFile
                });


                // 3. If present, emit additional locations associated with diagnostic.
                //    According to docs, these locations typically reference related
                //    locations (i.e., they are not locations that specify other
                //    occurrences of a problem).

                if (diagnostic.AdditionalLocations != null && diagnostic.AdditionalLocations.Count > 0)
                {
                    result.RelatedLocations = new List <Sarif.Location>();

                    foreach (Location location in diagnostic.AdditionalLocations)
                    {
                        filePath = location.GetLineSpan().Path;
                        region   = location.ConvertToRegion();

                        result.RelatedLocations.Add(new Sarif.Location
                        {
                            Message = new Message {
                                Text = "Additional location"
                            },
                            PhysicalLocation = new PhysicalLocation
                            {
                                ArtifactLocation = new ArtifactLocation {
                                    Uri = new Uri(filePath)
                                },
                                Region = region
                            }
                        });
                    }
                }

                ReportingDescriptor rule = diagnostic.ConvertToRuleDescriptor();
                context.Logger.Log(null, result);
            });
        }
Ejemplo n.º 3
0
        private void AnalyzeManagedAssembly(string assemblyFilePath, IEnumerable <string> roslynAnalyzerFilePaths, BinaryAnalyzerContext context)
        {
            if (roslynAnalyzerFilePaths == null)
            {
                return;
            }

            if (_globalRoslynAnalysisContext == null)
            {
                _globalRoslynAnalysisContext = new RoslynAnalysisContext();

                // We could use the ILDiagnosticsAnalyzer factory method that initializes
                // an object instance from an enumerable collection of analyzer paths. We
                // initialize a context object from each path one-by-one instead, in order
                // to make an attempt to load each specified analyzer. We will therefore
                // collect information on each analyzer that fails to load. We will also
                // proceed with performing as much analysis as possible. Ultimately, a
                // single analyzer load failure will return in BinSkim returning a non-zero
                // failure code from the run.
                foreach (string analyzerFilePath in roslynAnalyzerFilePaths)
                {
                    InvokeCatchingRelevantIOExceptions
                    (
                        action: () => { ILDiagnosticsAnalyzer.LoadAnalyzer(analyzerFilePath, _globalRoslynAnalysisContext); },
                        exceptionHandler: (ex) =>
                    {
                        Errors.LogExceptionLoadingPlugIn(analyzerFilePath, context, ex);
                    }
                    );
                }
            }

            Debug.Assert(context.MimeType == Sarif.Writers.MimeType.Binary);

            ILDiagnosticsAnalyzer roslynAnalyzer = ILDiagnosticsAnalyzer.Create(_globalRoslynAnalysisContext);

            roslynAnalyzer.Analyze(assemblyFilePath, diagnostic =>
            {
                // 0. Populate various members
                var result         = new Result();
                result.Kind        = diagnostic.Severity.ConvertToMessageKind();
                result.FullMessage = diagnostic.GetMessage();

                // For Roslyn diagnostics, suppression information is always available (i.e., it
                // is not contingent on compilation with specific #define such as CODE_ANLAYSIS).
                // As a result, we always populate IsSuppressedInSource with this information.
                result.IsSuppressedInSource = diagnostic.IsSuppressed;

                result.Properties                     = new Dictionary <string, string>();
                result.Properties["Severity"]         = diagnostic.Severity.ToString();
                result.Properties["IsWarningAsError"] = diagnostic.IsWarningAsError.ToString();
                result.Properties["WarningLevel"]     = diagnostic.WarningLevel.ToString();

                foreach (string key in diagnostic.Properties.Keys)
                {
                    result.Properties[key] = diagnostic.Properties[key];
                }

                // 1. Record the assembly under analysis
                result.Locations = new[] {
                    new Sarif.Sdk.Location {
                        AnalysisTarget = new[]
                        {
                            new PhysicalLocationComponent
                            {
                                Uri      = assemblyFilePath.CreateUriForJsonSerialization(),
                                MimeType = context.MimeType,
                            }
                        }
                    }
                };

                // 2. Record the actual location associated with the result
                var region = diagnostic.Location.ConvertToRegion();
                string filePath;

                if (diagnostic.Location != Location.None)
                {
                    filePath = diagnostic.Location.GetLineSpan().Path;

                    result.Locations[0].ResultFile = new[]
                    {
                        new PhysicalLocationComponent
                        {
                            Uri      = filePath.CreateUriForJsonSerialization(),
                            MimeType = Sarif.Writers.MimeType.DetermineFromFileExtension(filePath),
                            Region   = region
                        }
                    };
                }

                // 3. If present, emit additional locations associated with diagnostic.\
                //    According to docs, these locations typically reference related
                //    locations (i.e., they are not locations that specify other
                //    occurrences of a problem).

                if (diagnostic.AdditionalLocations != null && diagnostic.AdditionalLocations.Count > 0)
                {
                    result.RelatedLocations = new List <AnnotatedCodeLocation>(diagnostic.AdditionalLocations.Count);

                    foreach (Location location in diagnostic.AdditionalLocations)
                    {
                        filePath = location.GetLineSpan().Path;
                        region   = location.ConvertToRegion();

                        result.RelatedLocations.Add(new AnnotatedCodeLocation
                        {
                            Message          = "Additional location",
                            PhysicalLocation = new[]
                            {
                                new PhysicalLocationComponent
                                {
                                    Uri      = filePath.CreateUriForJsonSerialization(),
                                    MimeType = Sarif.Writers.MimeType.DetermineFromFileExtension(filePath),
                                    Region   = region
                                }
                            }
                        });
                    }
                }

                IRuleDescriptor rule = diagnostic.ConvertToRuleDescriptor();
                context.Logger.Log(null, result);
            });
        }