Esempio n. 1
0
        public void ExplodedGraph_SingleBranchVisited_If()
        {
            var testInput      = "var a = false; bool b; if (a) { b = true; } else { b = false; } a = b;";
            var method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel);
            var methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfLastInstructionVisits = 0;
            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = false")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = true")
                {
                    Execute.Assertion.FailWith("We should never get into this branch");
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    args.ProgramState.GetSymbolValue(bSymbol).Should().Be(SymbolicValue.False);
                    args.ProgramState.GetSymbolValue(aSymbol)
                    .Should().BeNull("a is dead, so there should be no associated value to it.");
                }
                if (args.Instruction.ToString() == "a = b")
                {
                    numberOfLastInstructionVisits++;
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfProcessedInstructions.Should().Be(8);
            numberOfExitBlockReached.Should().Be(1);
            numberOfLastInstructionVisits.Should().Be(1);
        }
Esempio n. 2
0
        public void ExplodedGraph_SequentialInput()
        {
            string        testInput = "var a = true; var b = false; b = !b; a = (b);";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var           aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var           bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = true")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    args.ProgramState.GetSymbolValue(bSymbol).Should().Be(SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = !b")
                {
                    args.ProgramState.GetSymbolValue(bSymbol).Should().NotBe(SymbolicValue.False);
                    args.ProgramState.GetSymbolValue(bSymbol).Should().NotBe(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "a = (b)")
                {
                    args.ProgramState.GetSymbolValue(bSymbol)
                    .Should().Be(args.ProgramState.GetSymbolValue(aSymbol));
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfProcessedInstructions.Should().Be(9);
            numberOfExitBlockReached.Should().Be(1);
        }
Esempio n. 3
0
            private static void ReportOnAssignment(AssignmentExpressionSyntax assignment, ExpressionSyntax left, ISymbol symbol,
                                                   ISymbol declaration, HashSet <SyntaxNode> assignmentLhs, HashSet <ISymbol> outState, SyntaxNodeAnalysisContext context)
            {
                if (CSharpLiveVariableAnalysis.IsLocalScoped(symbol, declaration) &&
                    !outState.Contains(symbol))
                {
                    var location = GetFirstLineLocationFromToken(assignment.OperatorToken, assignment.Right);
                    context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, location, symbol.Name));
                }

                assignmentLhs.Add(left);
            }
Esempio n. 4
0
 private ExplodedGraphContext(MethodDeclarationSyntax mainMethod, SemanticModel semanticModel)
 {
     this.MainMethod           = mainMethod;
     this.SemanticModel        = semanticModel;
     this.MainMethodSymbol     = semanticModel.GetDeclaredSymbol(this.MainMethod) as IMethodSymbol;
     this.ControlFlowGraph     = CSharpControlFlowGraph.Create(this.MainMethod.Body, semanticModel);
     this.LiveVariableAnalysis = CSharpLiveVariableAnalysis.Analyze(this.ControlFlowGraph, this.MainMethodSymbol, semanticModel);
     this.ExplodedGraph        = new CSharpExplodedGraph(this.ControlFlowGraph, this.MainMethodSymbol, semanticModel, this.LiveVariableAnalysis);
     this.ExplodedGraph.InstructionProcessed += (sender, args) => { this.NumberOfProcessedInstructions++; };
     this.ExplodedGraph.ExplorationEnded     += (sender, args) => { this.ExplorationEnded = true; };
     this.ExplodedGraph.MaxStepCountReached  += (sender, args) => { this.MaxStepCountReached = true; };
     this.ExplodedGraph.ExitBlockReached     += (sender, args) => { this.NumberOfExitBlockReached++; };
 }
Esempio n. 5
0
        private static void CheckForDeadStores(CSharpSyntaxNode node, ISymbol declaration, SyntaxNodeAnalysisContext context)
        {
            if (declaration == null || !CSharpControlFlowGraph.TryGet(node, context.SemanticModel, out var cfg))
            {
                return;
            }

            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, declaration, context.SemanticModel);

            foreach (var block in cfg.Blocks)
            {
                CheckCfgBlockForDeadStores(block, lva.GetLiveOut(block), lva.CapturedVariables, node, declaration, context);
            }
        }
Esempio n. 6
0
            private void ProcessPostfixExpression(SyntaxNode instruction, HashSet <ISymbol> liveOut)
            {
                var postfixExpression = (PostfixUnaryExpressionSyntax)instruction;
                var operand           = postfixExpression.Operand.RemoveParentheses();

                if (operand.IsKind(SyntaxKind.IdentifierName) &&
                    context.SemanticModel.GetSymbolInfo(operand).Symbol is { } symbol &&
                    IsSymbolRelevant(symbol) &&
                    CSharpLiveVariableAnalysis.IsLocalScoped(symbol, declaration) &&
                    !liveOut.Contains(symbol) &&
                    !IsMuted(operand))
                {
                    context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, postfixExpression.GetLocation(), symbol.Name));
                }
            }
Esempio n. 7
0
        public void ExplodedGraph_AllBranchesVisited()
        {
            string        testInput = "int i = 1; switch (i) { case 1: default: cw1(); break; case 2: cw2(); break; }";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfCw1InstructionVisits  = 0;
            var numberOfCw2InstructionVisits  = 0;
            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "cw1()")
                {
                    numberOfCw1InstructionVisits++;
                }
                if (args.Instruction.ToString() == "cw2()")
                {
                    numberOfCw2InstructionVisits++;
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfExitBlockReached.Should().Be(1);
            numberOfCw1InstructionVisits.Should().Be(1);
            numberOfCw2InstructionVisits.Should().Be(1);
        }
Esempio n. 8
0
        public void ExplodedGraph_SingleBranchVisited_And()
        {
            string        testInput = "var a = false; if (a && !a) { a = true; }";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var           aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = !true")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);     // Roslyn is clever !true has const value.
                }
                if (args.Instruction.ToString() == "!a")
                {
                    Execute.Assertion.FailWith("We should never get into this branch");
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfExitBlockReached.Should().Be(1);
        }
Esempio n. 9
0
        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);
        }
Esempio n. 10
0
            public LiveVariableAnalysisContext(string methodBody, string localFunctionName = null)
            {
                var              method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, methodBody), "Main", out var semanticModel);
                IMethodSymbol    symbol;
                CSharpSyntaxNode body;

                if (localFunctionName == null)
                {
                    symbol = semanticModel.GetDeclaredSymbol(method);
                    body   = method.Body;
                }
                else
                {
                    var function = (LocalFunctionStatementSyntaxWrapper)method.DescendantNodes().Single(x => x.Kind() == SyntaxKindEx.LocalFunctionStatement && ((LocalFunctionStatementSyntaxWrapper)x).Identifier.Text == localFunctionName);
                    symbol = semanticModel.GetDeclaredSymbol(function) as IMethodSymbol;
                    body   = (CSharpSyntaxNode)function.Body ?? function.ExpressionBody;
                }
                this.CFG = CSharpControlFlowGraph.Create(body, semanticModel);
                this.LVA = CSharpLiveVariableAnalysis.Analyze(this.CFG, symbol, semanticModel);
            }
Esempio n. 11
0
        public void ExplodedGraph_BothBranchesVisited_StateMerge()
        {
            var testInput    = "var a = !true; bool b; if (inParameter) { b = false; } else { b = false; } a = b;";
            var method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel);
            var methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfLastInstructionVisits = 0;
            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = b")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);
                    numberOfLastInstructionVisits++;
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfExitBlockReached.Should().Be(1);
            numberOfLastInstructionVisits.Should().Be(1);
        }
Esempio n. 12
0
        private static void CheckForDeadStores(CSharpSyntaxNode node, ISymbol declaration, SyntaxNodeAnalysisContext context)
        {
            if (declaration == null ||
                node == null ||
                // Currently the tuple expressions are not supported and this is known to cause false positives.
                // Please check:
                // - community feedback: https://github.com/SonarSource/sonar-dotnet/issues/3094
                // - implementation ticket: https://github.com/SonarSource/sonar-dotnet/issues/2933
                node.DescendantNodes().AnyOfKind(SyntaxKindEx.TupleExpression) ||
                !CSharpControlFlowGraph.TryGet(node, context.SemanticModel, out var cfg))
            {
                return;
            }

            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, declaration, context.SemanticModel);

            foreach (var block in cfg.Blocks)
            {
                CheckCfgBlockForDeadStores(block, lva.GetLiveOut(block), lva.CapturedVariables, node, declaration, context);
            }
        }
Esempio n. 13
0
            private void ProcessPrefixExpression(SyntaxNode instruction, HashSet<ISymbol> liveOut)
            {
                var prefixExpression = (PrefixUnaryExpressionSyntax)instruction;
                var parent = prefixExpression.GetSelfOrTopParenthesizedExpression();
                var operand = prefixExpression.Operand.RemoveParentheses();
                if (parent.Parent is ExpressionStatementSyntax &&
                    operand.IsKind(SyntaxKind.IdentifierName))
                {
                    var symbol = context.SemanticModel.GetSymbolInfo(operand).Symbol;
                    if (!IsSymbolRelevant(symbol))
                    {
                        return;
                    }

                    if (CSharpLiveVariableAnalysis.IsLocalScoped(symbol, declaration) &&
                        !liveOut.Contains(symbol))
                    {
                        context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, prefixExpression.GetLocation(), symbol.Name));
                    }
                }
            }
Esempio n. 14
0
        public void ExplodedGraph_NonLocalNorFieldSymbolBranching()
        {
            string        testInput = "if (Property) { cw(); }";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var           propertySymbol = semanticModel.GetSymbolInfo(
                method.DescendantNodes().OfType <IdentifierNameSyntax>().First(d => d.Identifier.ToString() == "Property")).Symbol;

            propertySymbol.Should().NotBeNull();

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "Property")
                {
                    args.ProgramState.GetSymbolValue(propertySymbol).Should().BeNull();
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfExitBlockReached.Should().Be(1);
        }
Esempio n. 15
0
        public void ExplodedGraph_SequentialInput_OutParameter()
        {
            var testInput          = "outParameter = true;";
            var method             = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel);
            var methodSymbol       = semanticModel.GetDeclaredSymbol(method);
            var parameters         = method.DescendantNodes().OfType <ParameterSyntax>();
            var outParameterSymbol = semanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "outParameter"));

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfProcessedInstructions = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "outParameter = true")
                {
                    args.ProgramState.GetSymbolValue(outParameterSymbol)
                    .Should().Be(SymbolicValue.True);
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            numberOfProcessedInstructions.Should().Be(2);
            numberOfExitBlockReached.Should().Be(1);
        }
        private static void ReportOnDeadParametersAtEntry(BaseMethodDeclarationSyntax declaration, IMethodSymbol methodSymbol,
                                                          IImmutableList <IParameterSymbol> noReportOnParameters, SyntaxNodeAnalysisContext context)
        {
            if (!declaration.IsKind(SyntaxKind.MethodDeclaration) ||
                declaration.Body == null)
            {
                return;
            }

            var excludedParameters = noReportOnParameters;

            if (methodSymbol.IsExtensionMethod)
            {
                excludedParameters = excludedParameters.Add(methodSymbol.Parameters.First());
            }

            excludedParameters = excludedParameters.AddRange(methodSymbol.Parameters.Where(p => p.RefKind != RefKind.None));

            var candidateParameters = methodSymbol.Parameters.Except(excludedParameters);

            if (!candidateParameters.Any())
            {
                return;
            }

            IControlFlowGraph cfg;

            if (!CSharpControlFlowGraph.TryGet(declaration.Body, context.SemanticModel, out cfg))
            {
                return;
            }

            var lva            = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, context.SemanticModel);
            var liveParameters = lva.GetLiveIn(cfg.EntryBlock).OfType <IParameterSymbol>();

            ReportOnUnusedParameters(declaration, candidateParameters.Except(liveParameters).Except(lva.CapturedVariables), MessageDead,
                                     context, isRemovable: false);
        }
Esempio n. 17
0
        public void ExplodedGraph_InternalStateCount_MaxReached()
        {
            var testInput    = @"
using System;

namespace TesteAnalyzer
{
    class Program
    {
        static bool GetBool() { return bool.Parse(""True""); }

        static void Main(string[] args)
        {
            bool corrupted = false;
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();
            corrupted |= !GetBool();

            if (!corrupted)
            {
                Console.Out.WriteLine();
            }
        }
    }
}
";
            var tree         = ControlFlowGraphTest.Compile(testInput, out var semanticModel);
            var method       = tree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>().First(m => m.Identifier.ValueText == "Main");
            var methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };
            var maxStepCountReached = false;

            explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; };
            var maxInternalStateCountReached = false;

            explodedGraph.MaxInternalStateCountReached += (sender, args) => { maxInternalStateCountReached = true; };

            explodedGraph.Walk();

            explorationEnded.Should().BeFalse();
            maxStepCountReached.Should().BeFalse();
            maxInternalStateCountReached.Should().BeTrue();
        }
Esempio n. 18
0
        public void ExplodedGraph_NonDecisionMakingAssignments()
        {
            var testInput      = "var a = true; a |= false; var b = 42; b++; ++b;";
            var method         = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel);
            var methodSymbol   = semanticModel.GetDeclaredSymbol(method);
            var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);

            SymbolicValue sv = null;
            var           numberOfProcessedInstructions = 0;
            var           branchesVisited = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = true")
                {
                    branchesVisited++;
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "a |= false")
                {
                    branchesVisited++;
                    args.ProgramState.GetSymbolValue(aSymbol).Should().NotBeNull();
                    args.ProgramState.GetSymbolValue(aSymbol).Should().NotBe(SymbolicValue.False);
                    args.ProgramState.GetSymbolValue(aSymbol).Should().NotBe(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "b = 42")
                {
                    branchesVisited++;
                    sv = args.ProgramState.GetSymbolValue(bSymbol);
                    sv.Should().NotBeNull();
                }
                if (args.Instruction.ToString() == "b++")
                {
                    branchesVisited++;
                    var svNew = args.ProgramState.GetSymbolValue(bSymbol);
                    svNew.Should().NotBeNull();
                    svNew.Should().NotBe(sv);
                }
                if (args.Instruction.ToString() == "++b")
                {
                    branchesVisited++;
                    var svNew = args.ProgramState.GetSymbolValue(bSymbol);
                    svNew.Should().NotBeNull();
                    svNew.Should().NotBe(sv);
                }
            };

            explodedGraph.Walk();

            numberOfProcessedInstructions.Should().Be(11);
            branchesVisited.Should().Be(5);
        }
Esempio n. 19
0
        public void ExplodedGraph_BothBranchesVisited()
        {
            var testInput    = "var a = false; bool b; if (inParameter) { b = inParameter; } else { b = !inParameter; } a = b;";
            var method       = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel);
            var methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>();
            var aSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a"));
            var bSymbol        = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b"));

            var parameters        = method.DescendantNodes().OfType <ParameterSyntax>();
            var inParameterSymbol = semanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "inParameter"));

            var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel);
            var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva);
            var explorationEnded = false;

            explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; };

            var numberOfExitBlockReached = 0;

            explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; };

            var numberOfLastInstructionVisits = 0;
            var numberOfProcessedInstructions = 0;

            var visitedBlocks   = new HashSet <Block>();
            var branchesVisited = 0;

            explodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                visitedBlocks.Add(args.ProgramPoint.Block);

                numberOfProcessedInstructions++;
                if (args.Instruction.ToString() == "a = false")
                {
                    branchesVisited++;

                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);     // Roslyn is clever !true has const value.
                }
                if (args.Instruction.ToString() == "b = inParameter")
                {
                    branchesVisited++;

                    bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeTrue();
                    inParameterSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeTrue();
                }
                if (args.Instruction.ToString() == "b = !inParameter")
                {
                    branchesVisited++;

                    // b has value, but not true or false
                    args.ProgramState.GetSymbolValue(bSymbol).Should().NotBeNull();
                    bSymbol.HasConstraint(BoolConstraint.False, args.ProgramState).Should().BeFalse();
                    bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeFalse();

                    inParameterSymbol.HasConstraint(BoolConstraint.False, args.ProgramState).Should().BeTrue();
                }
                if (args.Instruction.ToString() == "a = b")
                {
                    branchesVisited++;

                    args.ProgramState.GetSymbolValue(inParameterSymbol).Should().BeNull();     // not out/ref parameter and LVA says dead
                    numberOfLastInstructionVisits++;
                }
            };

            explodedGraph.Walk();

            explorationEnded.Should().BeTrue();
            branchesVisited.Should().Be(4 + 1);
            numberOfExitBlockReached.Should().Be(1,
                                                 "All variables are dead at the ExitBlock, so whenever we get there, the ExplodedGraph nodes should be the same, " +
                                                 "and thus should be processed only once.");
            numberOfLastInstructionVisits.Should().Be(2);

            visitedBlocks.Count.Should().Be(cfg.Blocks.Count() - 1 /* Exit block*/);
        }