private static void Analyze(CSharpSyntaxNode declarationBody, ISymbol symbol, Action <CSharpExplodedGraph, SyntaxNodeAnalysisContext> analyze, SyntaxNodeAnalysisContext context) { if (declarationBody == null || declarationBody.ContainsDiagnostics) { return; } if (!CSharpControlFlowGraph.TryGet(declarationBody, context.SemanticModel, out var cfg)) { return; } var lva = CSharpLiveVariableAnalysis.Analyze(cfg, symbol, context.SemanticModel); try { var explodedGraph = new CSharpExplodedGraph(cfg, symbol, context.SemanticModel, lva); analyze(explodedGraph, context); } catch (Exception e) { // Roslyn/MSBuild is currently cutting exception message at the end of the line instead // of displaying the full message. As a workaround, we replace the line ending with ' ## '. // See https://github.com/dotnet/roslyn/issues/1455 and https://github.com/dotnet/roslyn/issues/24346 var sb = new StringBuilder(); sb.AppendLine($"Error processing method: {symbol?.Name ?? "{unknown}"}"); sb.AppendLine($"Method file: {declarationBody.GetLocation()?.GetLineSpan().Path ?? "{unknown}"}"); sb.AppendLine($"Method line: {declarationBody.GetLocation()?.GetLineSpan().StartLinePosition.ToString() ?? "{unknown}"}"); sb.AppendLine($"Inner exception: {e.ToString()}"); throw new SymbolicExecutionException(sb.ToString().Replace(Environment.NewLine, " ## "), e); } }
private static void CheckForNullDereference(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { var methodSymbol = context.SemanticModel.GetSymbolInfo(context.Node).Symbol ?? context.SemanticModel.GetDeclaredSymbol(context.Node); if (!methodSymbol.IsPubliclyAccessible()) { return; } var nullPointerCheck = new NullPointerDereference.NullPointerCheck(explodedGraph); explodedGraph.AddExplodedGraphCheck(nullPointerCheck); var identifiers = new HashSet <IdentifierNameSyntax>(); void memberAccessingHandler(object sender, MemberAccessingEventArgs args) => CollectMemberAccesses(args, identifiers, context.SemanticModel); nullPointerCheck.MemberAccessing += memberAccessingHandler; try { explodedGraph.Walk(); } finally { nullPointerCheck.MemberAccessing -= memberAccessingHandler; } foreach (var identifier in identifiers) { context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, identifier.GetLocation(), identifier.Identifier.ValueText)); } }
private static void CheckForRedundantConditions(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { var conditionTrue = new HashSet <SyntaxNode>(); var conditionFalse = new HashSet <SyntaxNode>(); void collectConditions(object sender, ConditionEvaluatedEventArgs args) => CollectConditions(args, conditionTrue, conditionFalse, context.SemanticModel); void explorationEnded(object sender, EventArgs args) => Enumerable.Empty <Diagnostic>() .Union(conditionTrue .Except(conditionFalse) .Where(c => !IsConditionOfLoopWithBreak((ExpressionSyntax)c)) .Where(c => !IsInsideCatchOrFinallyBlock(c)) .Select(node => GetDiagnostics(node, true))) .Union(conditionFalse .Except(conditionTrue) .Where(c => !IsInsideCatchOrFinallyBlock(c)) .Select(node => GetDiagnostics(node, false))) .ToList() .ForEach(d => context.ReportDiagnosticWhenActive(d)); explodedGraph.ExplorationEnded += explorationEnded; explodedGraph.ConditionEvaluated += collectConditions; try { explodedGraph.Walk(); } finally { explodedGraph.ExplorationEnded -= explorationEnded; explodedGraph.ConditionEvaluated -= collectConditions; } }
public AnalysisContext(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { this.explodedGraph = explodedGraph; this.context = context; explodedGraph.InstructionProcessed += InstructionProcessed; explodedGraph.ConditionEvaluated += ConditionEvaluatedHandler; }
public AnalysisContext(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { if (!GetMethodSymbol(context).IsPubliclyAccessible()) { return; } syntaxNodeAnalysisContext = context; nullPointerCheck = explodedGraph.NullPointerCheck; nullPointerCheck.MemberAccessing += MemberAccessingHandler; }
public AnalysisContext(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { if (!GetMethodSymbol(context).IsPubliclyAccessible()) { return; } this.syntaxNodeAnalysisContext = context; this.nullPointerCheck = new NullPointerDereference.NullPointerCheck(explodedGraph); this.nullPointerCheck.MemberAccessing += MemberAccessingHandler; explodedGraph.AddExplodedGraphCheck(this.nullPointerCheck); }
private static void CheckForRedundantConditions(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { var conditionTrue = new HashSet <SyntaxNode>(); var conditionFalse = new HashSet <SyntaxNode>(); var hasYieldStatement = false; void instructionProcessed(object sender, InstructionProcessedEventArgs args) { hasYieldStatement = hasYieldStatement || IsYieldNode(args.ProgramPoint.Block); } void collectConditions(object sender, ConditionEvaluatedEventArgs args) => CollectConditions(args, conditionTrue, conditionFalse, context.SemanticModel); void explorationEnded(object sender, EventArgs args) { // Do not raise issue in generator functions (See #1295) if (hasYieldStatement) { return; } Enumerable.Empty <Diagnostic>() .Union(conditionTrue .Except(conditionFalse) .Where(c => !IsConditionOfLoopWithBreak((ExpressionSyntax)c)) .Where(c => !IsInsideCatchOrFinallyBlock(c)) .Select(node => GetDiagnostics(node, true))) .Union(conditionFalse .Except(conditionTrue) .Where(c => !IsInsideCatchOrFinallyBlock(c)) .Select(node => GetDiagnostics(node, false))) .ToList() .ForEach(d => context.ReportDiagnosticWhenActive(d)); } explodedGraph.InstructionProcessed += instructionProcessed; explodedGraph.ExplorationEnded += explorationEnded; explodedGraph.ConditionEvaluated += collectConditions; try { explodedGraph.Walk(); } finally { explodedGraph.InstructionProcessed -= instructionProcessed; explodedGraph.ExplorationEnded -= explorationEnded; explodedGraph.ConditionEvaluated -= collectConditions; } }
private static void Analyze(CSharpSyntaxNode declarationBody, ISymbol symbol, Action <CSharpExplodedGraph, SyntaxNodeAnalysisContext> analyze, SyntaxNodeAnalysisContext context) { if (declarationBody == null || declarationBody.ContainsDiagnostics) { return; } if (!CSharpControlFlowGraph.TryGet(declarationBody, context.SemanticModel, out var cfg)) { return; } var lva = CSharpLiveVariableAnalysis.Analyze(cfg, symbol, context.SemanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, symbol, context.SemanticModel, lva); analyze(explodedGraph, context); }
public ISymbolicExecutionAnalysisContext AddChecks(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) => new AnalysisContext(explodedGraph, context);