Exemplo n.º 1
0
 public SingleThreadRunner(
     bool verbose,
     List <DiagnosticAnalyzer> analyzers,
     Func <ImmutableArray <Diagnostic>, ParsedOptions, ConcurrentDictionary <string, DiagnosticDescriptor>, SarifV2ErrorLogger, int> logDiagnostics,
     ParsedOptions parsedOptions,
     ConcurrentDictionary <string, DiagnosticDescriptor> descriptors,
     SarifV2ErrorLogger logger)
     : base(analyzers, logDiagnostics, parsedOptions, descriptors, logger)
 {
     _verbose = verbose;
 }
Exemplo n.º 2
0
 public Runner(
     List <DiagnosticAnalyzer> analyzers,
     Func <ImmutableArray <Diagnostic>, ParsedOptions, ConcurrentDictionary <string, DiagnosticDescriptor>, SarifV2ErrorLogger, int> logDiagnostics,
     ParsedOptions parsedOptions,
     ConcurrentDictionary <string, DiagnosticDescriptor> descriptors,
     SarifV2ErrorLogger logger)
 {
     _analyzers      = analyzers;
     _logDiagnostics = logDiagnostics;
     _parsedOptions  = parsedOptions;
     _descriptors    = descriptors;
     _logger         = logger;
 }
Exemplo n.º 3
0
        public MultiThreadRunner(
            bool verbose,
            List <DiagnosticAnalyzer> analyzers,
            Func <ImmutableArray <Diagnostic>, ParsedOptions, ConcurrentDictionary <string, DiagnosticDescriptor>, SarifV2ErrorLogger, int> logDiagnostics,
            ParsedOptions parsedOptions,
            ConcurrentDictionary <string, DiagnosticDescriptor> descriptors,
            SarifV2ErrorLogger logger,
            int threads)
            : base(analyzers, logDiagnostics, parsedOptions, descriptors, logger)
        {
            _scanBlock = new TransformBlock <Project, ImmutableArray <Diagnostic> >(async project =>
            {
                if (verbose)
                {
                    Console.WriteLine($"Starting: {project.FilePath}");
                }
                return(await GetDiagnostics(project).ConfigureAwait(false));
            },
                                                                                    new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = threads,
                EnsureOrdered          = false,
                BoundedCapacity        = 32
            });

            _resultsBlock = new ActionBlock <ImmutableArray <Diagnostic> >(diagnostics =>
            {
                _count += logDiagnostics(diagnostics, _parsedOptions, descriptors, logger);
            },
                                                                           new ExecutionDataflowBlockOptions
            {
                EnsureOrdered = false
            });

            _scanBlock.LinkTo(_resultsBlock, new DataflowLinkOptions {
                PropagateCompletion = true
            });
        }
Exemplo n.º 4
0
        private static int LogDiagnostics(
            ImmutableArray <Diagnostic> diagnostics,
            ParsedOptions parsedOptions,
            ConcurrentDictionary <string, DiagnosticDescriptor> descriptors,
            SarifV2ErrorLogger logger)
        {
            var count = 0;

            foreach (var diag in diagnostics)
            {
                var d = diag;
                // Second pass. Analyzers may support more than one diagnostic.
                // Filter excluded diagnostics.
                if (parsedOptions.excludeWarnings.Contains(d.Id))
                {
                    continue;
                }
                else if (parsedOptions.includeWarnings.Any() && !parsedOptions.includeWarnings.Contains(d.Id))
                {
                    continue;
                }

                ++count;

                // fix locations for diagnostics from additional files
                if (d.Location == Location.None)
                {
                    var match = WebConfigMessageRegex.Matches(d.GetMessage());
                    if (match.Count > 1)
                    {
                        throw new Exception("Unexpected");
                    }

                    if (match.Count != 0)
                    {
                        if (!descriptors.TryGetValue(d.Id, out var descr))
                        {
                            var msg = $"{match[0].Groups[1].Value}.";
                            descr = new DiagnosticDescriptor(d.Id, msg, msg, d.Descriptor.Category, d.Severity, d.Descriptor.IsEnabledByDefault);
                            descriptors.TryAdd(d.Id, descr);
                        }

                        var line    = new LinePosition(int.Parse(match[0].Groups[3].Value) - 1, 0);
                        var capture = match[0].Groups[4].Value.TrimEnd('.');
                        d = Diagnostic.Create(descr, Location.Create(match[0].Groups[2].Value, new TextSpan(0, capture.Length), new LinePositionSpan(line, line)));
                    }
                }

                if (parsedOptions.cwe)
                {
                    var cwe = LocaleUtil.GetLocalString($"{d.Id}_cwe");
                    var msg = d.ToString();
                    if (!cwe.ToString().StartsWith("??")) // overall all IDs must have corresponding CWE, but some are special like SCS0000
                    {
                        msg = msg.Replace($"{d.Id}:", $"{d.Id}: CWE-{cwe}:");
                    }

                    Console.WriteLine($"Found: {msg}");
                }
                else
                {
                    Console.WriteLine($"Found: {d}");
                }

                if (logger != null)
                {
                    logger.LogDiagnostic(d, null);
                }
            }

            return(count);
        }
Exemplo n.º 5
0
        private static async Task <int> GetDiagnostics(
            ParsedOptions parsedOptions,
            string versionString,
            Solution solution,
            List <DiagnosticAnalyzer> analyzers)
        {
            Stream             stream = null;
            SarifV2ErrorLogger logger = null;

            try
            {
                if (parsedOptions.sarifFile != null)
                {
                    if (File.Exists(parsedOptions.sarifFile))
                    {
                        File.Delete(parsedOptions.sarifFile);
                    }

                    stream = File.Open(parsedOptions.sarifFile, FileMode.CreateNew);
                }

                try
                {
                    if (stream != null)
                    {
                        var v = new Version(versionString);
                        logger = new SarifV2ErrorLogger(stream, "Security Code Scan", versionString, new Version($"{v.Major}.{v.Minor}.{v.Build}.0"), CultureInfo.CurrentCulture);
                    }

                    var descriptors = new ConcurrentDictionary <string, DiagnosticDescriptor>();

                    Runner runner;
                    if (parsedOptions.threads.HasValue)
                    {
                        runner = new MultiThreadRunner(parsedOptions.verbose, analyzers, LogDiagnostics, parsedOptions, descriptors, logger, Debugger.IsAttached ? 1 : parsedOptions.threads.Value);
                    }
                    else
                    {
                        runner = new SingleThreadRunner(parsedOptions.verbose, analyzers, LogDiagnostics, parsedOptions, descriptors, logger);
                    }

                    var solutionPath = Path.GetDirectoryName(solution.FilePath) + Path.DirectorySeparatorChar;
                    foreach (var project in solution.Projects)
                    {
                        var projectPath = project.FilePath;
                        if (projectPath.StartsWith(solutionPath))
                        {
                            projectPath = projectPath.Remove(0, solutionPath.Length);
                        }



                        if ((parsedOptions.includeProjects.Any() && !parsedOptions.includeProjects.Any(x => x.IsMatch(projectPath))) ||
                            parsedOptions.excludeProjects.Any(x => x.IsMatch(projectPath)))
                        {
                            Console.WriteLine($"Skipped: {project.FilePath} excluded from analysis");
                            continue;
                        }

                        await runner.Run(project).ConfigureAwait(false);
                    }

                    return(await runner.WaitForCompletion().ConfigureAwait(false));
                }
                finally
                {
                    if (logger != null)
                    {
                        logger.Dispose();
                    }
                }
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
        }