public void ExplodedGraph_BothBranchesVisited_NonCondition() { var testInput = "var str = this?.ToString();"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var 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 countConditionEvaluated = 0; explodedGraph.ConditionEvaluated += (sender, args) => { countConditionEvaluated++; }; var visitedBlocks = new HashSet <Block>(); explodedGraph.InstructionProcessed += (sender, args) => { visitedBlocks.Add(args.ProgramPoint.Block); }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); visitedBlocks.Count.Should().Be(cfg.Blocks.Count() - 1 /* Exit block */); countConditionEvaluated.Should().Be(0); }
public void ExplodedGraph_SequentialInput_Max() { var inputBuilder = new StringBuilder(); for (var i = 0; i < CSharpExplodedGraph.MaxStepCount / 2 + 1; i++) { inputBuilder.AppendLine($"var x{i} = true;"); } var testInput = inputBuilder.ToString(); var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var 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 maxStepCountReached = false; explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; explodedGraph.Walk(); explorationEnded.Should().BeFalse(); maxStepCountReached.Should().BeTrue(); numberOfExitBlockReached.Should().Be(0); }
public void ExplodedGraph_LoopExploration() { var testInput = "var i = 0; while (i < 1) { i = i + 1; }"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var 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 exceeded = 0; explodedGraph.ProgramPointVisitCountExceedLimit += (sender, args) => { exceeded++; args.ProgramPoint.Block.Instructions.Should().Contain(i => i.ToString() == "i < 1"); }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); exceeded.Should().Be(1); }
public void ExportFunction(MethodDeclarationSyntax method) { if (method.Body == null) { return; } if (IsTooComplexForMlirOrTheCfg(method)) { writer.WriteLine($"// Skipping function {method.Identifier.ValueText}{GetAnonymousArgumentsString(method)}, it contains poisonous unsupported syntaxes"); writer.WriteLine(); return; } blockCounter = 0; blockMap.Clear(); opCounter = 0; opMap.Clear(); var returnType = HasNoReturn(method) ? "()" : MlirType(method.ReturnType); writer.WriteLine($"func @{GetMangling(method)}{GetAnonymousArgumentsString(method)} -> {returnType} {GetLocation(method)} {{"); CreateEntryBlock(method); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); foreach (var block in cfg.Blocks) { ExportBlock(block, method, returnType); } writer.WriteLine("}"); }
protected UCFG GetUcfgForMethod(string code, string methodName) { (var method, var semanticModel) = TestHelper.Compile(code, Verifier.SystemWebMvcAssembly).GetMethod(methodName); var builder = new UniversalControlFlowGraphBuilder(); return(builder.Build(semanticModel, method, semanticModel.GetDeclaredSymbol(method), CSharpControlFlowGraph.Create(method.Body, semanticModel))); }
public void ExplodedGraph_SingleBranchVisited_If() { string testInput = "var a = false; bool b; if (a) { b = true; } else { b = false; } 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 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); }
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); }
private static UCFG BuildUcfg(CSharpSyntaxNode cfgStartNode, CSharpSyntaxNode ucfgStartNode, IMethodSymbol methodSymbol, SemanticModel semanticModel) { var builder = new UcfgFactory(semanticModel); var cfg = CSharpControlFlowGraph.Create(cfgStartNode, semanticModel); var ucfg = builder.Create(ucfgStartNode, methodSymbol, cfg); //var serializedCfg = CfgSerializer.Serialize(methodName, cfg); //var serializedUcfg = UcfgSerializer.Serialize(ucfg); return(ucfg); }
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++; }; }
private static UCFG CreateUcfgForConstructor(string code, string name) { var(syntaxTree, semanticModel) = TestHelper.Compile(code, Verifier.SystemWebMvcAssembly); var ctor = syntaxTree.GetRoot() .DescendantNodes() .OfType <ConstructorDeclarationSyntax>() .First(m => m.Identifier.ValueText == name); var builder = new UniversalControlFlowGraphBuilder(); var ucfg = builder.Build(semanticModel, ctor, semanticModel.GetDeclaredSymbol(ctor), CSharpControlFlowGraph.Create(ctor.Body, semanticModel)); return(ucfg); }
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); }
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); }
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); }
public void ExplodedGraph_SingleBranchVisited_And() { var testInput = "var a = false; if (a && !a) { a = true; }"; 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 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); }
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); }
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); }
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(); }
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); }
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*/); }
protected IControlFlowGraph GetCfgForMethod(string code, string methodName) { (var method, var semanticModel) = TestHelper.Compile(code).GetMethod(methodName); return(CSharpControlFlowGraph.Create(method.Body, semanticModel)); }