Beispiel #1
0
        private static ControlFlowGraph Graph(string path)
        {
            var code        = File.ReadAllText(path, Encoding.UTF8);
            var tree        = CSharpSyntaxTree.ParseText(code);
            var compilation = CSharpCompilation.Create(
                "Suspension.Tests.Samples",
                new[] { tree },
                new[]
            {
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile("C:\\Program Files\\dotnet\\shared\\Microsoft.NETCore.App\\3.1.13\\System.Runtime.dll"),
                MetadataReference.CreateFromFile(typeof(Coroutine).Assembly.Location)
            },
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                );

            var semantic = compilation.GetSemanticModel(tree);
            var method   = tree.GetRoot().DescendantNodes()
                           .OfType <MethodDeclarationSyntax>()
                           .That(
                new HasAttribute(semantic, new FullName("global::Suspension.SuspendableAttribute"))
                )
                           .Single();

            return(ControlFlowGraph.Create(method, semantic));
        }
        public void LambdaFlow_04()
        {
            string source = @"
struct C
{
    void M(System.Action d1, System.Action<bool, bool> d2)
/*<bind>*/{
        d1 = () =>
        {
            d2 = (bool result1, bool input1) =>
            {
                result1 = input1;
            
            };
        };

        void local(bool result2, bool input2) => result2 = input2;
    }/*</bind>*/
}
";

            var compilation   = CreateCompilation(source);
            var tree          = compilation.SyntaxTrees.Single();
            var semanticModel = compilation.GetSemanticModel(tree);
            var graphM        = ControlFlowGraph.Create((IMethodBodyOperation)semanticModel.GetOperation(tree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>().Single()));

            Assert.NotNull(graphM);
            Assert.Null(graphM.Parent);

            IFlowAnonymousFunctionOperation lambdaD1 = getLambda(graphM);

            Assert.Throws <ArgumentNullException>(() => graphM.GetLocalFunctionControlFlowGraph(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetLocalFunctionControlFlowGraph(lambdaD1.Symbol));
            Assert.Throws <ArgumentNullException>(() => graphM.GetLocalFunctionControlFlowGraphInScope(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetLocalFunctionControlFlowGraphInScope(lambdaD1.Symbol));

            var graphD1 = graphM.GetAnonymousFunctionControlFlowGraph(lambdaD1);

            Assert.NotNull(graphD1);
            Assert.Same(graphM, graphD1.Parent);
            var graphD1_FromExtension = graphM.GetAnonymousFunctionControlFlowGraphInScope(lambdaD1);

            Assert.Same(graphD1, graphD1_FromExtension);

            IFlowAnonymousFunctionOperation lambdaD2 = getLambda(graphD1);
            var graphD2 = graphD1.GetAnonymousFunctionControlFlowGraph(lambdaD2);

            Assert.NotNull(graphD2);
            Assert.Same(graphD1, graphD2.Parent);

            Assert.Throws <ArgumentNullException>(() => graphM.GetAnonymousFunctionControlFlowGraph(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetAnonymousFunctionControlFlowGraph(lambdaD2));
            Assert.Throws <ArgumentNullException>(() => graphM.GetAnonymousFunctionControlFlowGraphInScope(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetAnonymousFunctionControlFlowGraphInScope(lambdaD2));

            IFlowAnonymousFunctionOperation getLambda(ControlFlowGraph graph)
            {
                return(graph.Blocks.SelectMany(b => b.Operations.SelectMany(o => o.DescendantsAndSelf())).OfType <IFlowAnonymousFunctionOperation>().Single());
            }
        }
Beispiel #3
0
        static void Main(string [] args)
        {
            //var method = GetProgramMethod ("Triangle1");
            AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(args[1]);
            TypeDefinition     type     = assembly.MainModule.GetType("TestCase");
            MethodDefinition   method   = GetMethod(type.Methods, "Main");

            var cfg = ControlFlowGraph.Create(method);

            FormatControlFlowGraph(Console.Out, cfg);

            Console.WriteLine("--------------------");

            var store = AnnotationStore.CreateStore(cfg, BlockOptimization.Detailed);

            PrintAnnotations(method, store);

            var language = CSharp.GetLanguage(CSharpVersion.V1);

            //var body = method.Body.Decompile (language);

            var writer = language.GetWriter(new PlainTextFormatter(Console.Out));

            writer.Write(method);

            Console.ReadKey();
        }
        public void ExplodedGraph_LoopExploration()
        {
            string        testInput = "var i = 0; while (i < 1) { i = i + 1; }";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(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.Where(i => i.ToString() == "i < 1").Should().NotBeEmpty();
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(1, exceeded);
        }
Beispiel #5
0
        public EvaluationResult Evaluate(Dictionary <VariableSymbol, object> variables)
        {
            if (this.GlobalScope.Diagnostics.Any())
            {
                return(new EvaluationResult(this.GlobalScope.Diagnostics, null));
            }

            var program = this.GetProgram();

#if false // CFG Graphviz output
            var appPath      = Environment.GetCommandLineArgs()[0];
            var appDirectory = Path.GetDirectoryName(appPath) !;
            var cfgPath      = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Slang", "cfg.dot");      //Path.Combine( appDirectory , "cfg.dot" );
            var cfgStatement = !program.Statement.Statements.Any() && program.Functions.Any()
                             ? program.Functions.Last().Value
                             : program.Statement;
            var cfg = ControlFlowGraph.Create(cfgStatement);

            using var streamWriter = new StreamWriter(cfgPath);

            cfg.WriteTo(streamWriter);
#endif

            if (program.Diagnostics.Any())
            {
                return(new EvaluationResult(program.Diagnostics.ToImmutableArray(), null));
            }

            var evaluator = new Evaluator(program, variables);
            var value     = evaluator.Evaluate();

            return(new EvaluationResult(ImmutableArray <Diagnostic> .Empty, value));
        }
        protected void RunTestCase(string name)
        {
            MethodDefinition method = LoadTestCaseMethod(name);
            ControlFlowGraph cfg    = ControlFlowGraph.Create(method);

            Assert.AreEqual(Normalize(LoadExpectedControlFlowString(name)), Normalize(ToString(cfg)));
        }
        public bool TryGetOrComputeResult(
            ImmutableArray <IOperation> operationBlocks,
            IMethodSymbol containingMethod,
            bool trackInstanceFields,
            out DataFlowAnalysisResult <DisposeBlockAnalysisResult, DisposeAbstractValue> disposeAnalysisResult,
            out DataFlowAnalysisResult <PointsToBlockAnalysisResult, PointsToAbstractValue> pointsToAnalysisResult,
            out ImmutableDictionary <IFieldSymbol, PointsToAbstractValue> trackedInstanceFieldPointsToMap)
        {
            foreach (var operationRoot in operationBlocks)
            {
                IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock();
                if (topmostBlock != null)
                {
                    var cfg = ControlFlowGraph.Create(topmostBlock);

                    // Invoking an instance method may likely invalidate all the instance field analysis state, i.e.
                    // reference type fields might be re-assigned to point to different objects in the called method.
                    // An optimistic points to analysis assumes that the points to values of instance fields don't change on invoking an instance method.
                    // A pessimistic points to analysis resets all the instance state and assumes the instance field might point to any object, hence has unknown state.
                    // For dispose analysis, we want to perform an optimistic points to analysis as we assume a disposable field is not likely to be re-assigned to a separate object in helper method invocations in Dispose.
                    pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, _wellKnownTypeProvider, pessimisticAnalysis: false);
                    disposeAnalysisResult  = DisposeAnalysis.GetOrComputeResult(cfg, containingMethod, _wellKnownTypeProvider, _disposeOwnershipTransferLikelyTypes, pointsToAnalysisResult,
                                                                                trackInstanceFields, out trackedInstanceFieldPointsToMap);
                    return(true);
                }
            }

            disposeAnalysisResult           = null;
            pointsToAnalysisResult          = null;
            trackedInstanceFieldPointsToMap = null;
            return(false);
        }
Beispiel #8
0
        private static bool ReportDiagnosticIfNecessary(OperationAnalysisContext operationContext,
                                                        IOperation argumentValue,
                                                        SyntaxNode syntax,
                                                        ISymbol invokedSymbol,
                                                        ISymbol containingMethod)
        {
            if (argumentValue.Type.SpecialType != SpecialType.System_String || !argumentValue.ConstantValue.HasValue)
            {
                // We have a candidate for diagnostic. perform more precise dataflow analysis.
                var topmostBlock = argumentValue.GetTopmostParentBlock();
                if (topmostBlock != null)
                {
                    var cfg = ControlFlowGraph.Create(topmostBlock);
                    var wellKnownTypeProvider        = WellKnownTypeProvider.GetOrCreate(operationContext.Compilation);
                    var copyAnalysisResult           = CopyAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider);
                    var nullAnalysisResult           = NullAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider);
                    var pointsToAnalysisResult       = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, nullAnalysisResult);
                    var stringContentResult          = StringContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, nullAnalysisResult, pointsToAnalysisResult);
                    StringContentAbstractValue value = stringContentResult[argumentValue];
                    if (value.NonLiteralState == StringContainsNonLiteralState.No)
                    {
                        // The value is a constant literal or default/unitialized, so avoid flagging this usage.
                        return(false);
                    }
                }

                // Review if the symbol passed to {invocation} in {method/field/constructor/etc} has user input.
                operationContext.ReportDiagnostic(syntax.CreateDiagnostic(Rule,
                                                                          invokedSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
                                                                          containingMethod.Name));
                return(true);
            }

            return(false);
        }
        public void ExplodedGraph_SequentialInput_Max()
        {
            var inputBuilder = new StringBuilder();

            for (int i = 0; i < ExplodedGraph.MaxStepCount / 2 + 1; i++)
            {
                inputBuilder.AppendLine($"var x{i} = true;");
            }
            string        testInput = inputBuilder.ToString();
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(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();

            Assert.IsFalse(explorationEnded);
            Assert.IsTrue(maxStepCountReached);
            Assert.AreEqual(0, numberOfExitBlockReached);
        }
        public void ExplodedGraph_BothBranchesVisited_NonCondition()
        {
            string        testInput = "var str = this?.ToString();";
            SemanticModel semanticModel;
            var           method       = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel);
            var           methodSymbol = semanticModel.GetDeclaredSymbol(method);

            var cfg = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(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();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(cfg.Blocks.Count() - 1 /* Exit block */, visitedBlocks.Count);
            Assert.AreEqual(0, countConditionEvaluated);
        }
Beispiel #11
0
        /// <summary>
        /// Evaluates the current compilation provided a symbol table with actual values.
        /// </summary>
        /// <param name="variables">The symbol table with actual values.</param>
        /// <returns>An evaluation result.</returns>
        public EvaluationResult Evaluate(Dictionary <VariableSymbol, object> variables)
        {
            var diagnostics = SyntaxTree.Diagnostics.Concat(GlobalScope.Diagnostics).ToImmutableArray();

            if (diagnostics.Any())
            {
                return(new EvaluationResult(diagnostics, null));
            }

            var program = Binder.BindProgram(GlobalScope);

            var appPath      = Environment.GetCommandLineArgs()[0];
            var appDirectory = Path.GetDirectoryName(appPath);
            var cfgPath      = Path.Combine(appDirectory, "cfg.dot");
            var cfgStatement = !program.Statement.Statements.Any() && program.Functions.Any()
                                  ? program.Functions.Last().Value
                                  : program.Statement;
            var cfg = ControlFlowGraph.Create(cfgStatement);

            using (var streamWriter = new StreamWriter(cfgPath))
            {
                cfg.WriteTo(streamWriter);
            }

            if (program.Diagnostics.Any())
            {
                return(new EvaluationResult(program.Diagnostics.ToImmutableArray(), null));
            }

            var evaluator = new Evaluator(program, variables);
            var value     = evaluator.Evaluate();

            return(new EvaluationResult(ImmutableArray <Diagnostic> .Empty, value));
        }
Beispiel #12
0
        internal static IEnumerable <object> TryAnalyze(
            SyntaxNode methodNode,
            SemanticModel semanticModel,
            CSharpCompilation compilation)
        {
            var cfg = ControlFlowGraph.Create(methodNode, semanticModel);
            var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);
            var owningSymbol          = semanticModel.GetDeclaredSymbol(methodNode);

            var valueContentAnalysis = ValueContentAnalysis.TryGetOrComputeResult(cfg,
                                                                                  owningSymbol,
                                                                                  wellKnownTypeProvider,
                                                                                  new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty),
                                                                                  null,
                                                                                  CancellationToken.None
                                                                                  );

            if (HasLiteralStateLoss(valueContentAnalysis))
            {
                return(null);
            }

            var returnValues = valueContentAnalysis.ReturnValueAndPredicateKindOpt?.Value.LiteralValues;

            return(returnValues);
        }
        public void Analyze(ClassDeclarationSyntax classDeclarationSyntax, ClassModel classModel)
        {
            List <MethodDeclarationSyntax> methodDeclarationSyntaxes = classDeclarationSyntax
                                                                       .DescendantNodes()
                                                                       .OfType <MethodDeclarationSyntax>()
                                                                       .ToList();

            foreach (MethodDeclarationSyntax methodDeclarationSyntax in methodDeclarationSyntaxes)
            {
                MethodModel methodModel = new MethodModel();

                methodModel.Name = methodDeclarationSyntax.Identifier.Text;

                IMethodSymbol methodSymbol = SemanticModel.GetDeclaredSymbol(methodDeclarationSyntax) as IMethodSymbol;

                if (methodSymbol != null && !methodSymbol.IsAbstract)
                {
                    ControlFlowGraph controlFlowGraph = ControlFlowGraph
                                                        .Create(methodDeclarationSyntax, SemanticModel, CancellationToken.None);

                    int numberOfBlocks = controlFlowGraph.Blocks.Length;
                    int numberOfEdges  = 0;

                    foreach (BasicBlock basicBlock in controlFlowGraph.Blocks)
                    {
                        if (basicBlock.ConditionalSuccessor != null)
                        {
                            numberOfEdges++;
                        }

                        if (basicBlock.FallThroughSuccessor != null)
                        {
                            numberOfEdges++;
                        }
                    }

                    methodModel.CyclomaticComplexity = numberOfEdges - numberOfBlocks + 2;
                }

                methodModel.Fqn             = methodSymbol.ToString();
                methodModel.Static          = methodSymbol.IsStatic;
                methodModel.Abstract        = methodSymbol.IsAbstract;
                methodModel.Sealed          = methodSymbol.IsSealed;
                methodModel.Async           = methodSymbol.IsAsync;
                methodModel.Override        = methodSymbol.IsOverride;
                methodModel.Virtual         = methodSymbol.IsVirtual;
                methodModel.Extern          = methodSymbol.IsExtern;
                methodModel.Accessibility   = methodSymbol.DeclaredAccessibility.ToString();
                methodModel.ReturnType      = methodSymbol.ReturnType.ToString();
                methodModel.FirstLineNumber =
                    methodDeclarationSyntax.GetLocation().GetLineSpan().StartLinePosition.Line + 1;
                methodModel.LastLineNumber =
                    methodDeclarationSyntax.GetLocation().GetLineSpan().EndLinePosition.Line + 1;

                _invocationAnalyzer.Analyze(methodDeclarationSyntax, methodModel);
                _parameterAnalyzer.Analyze(methodDeclarationSyntax, methodModel);

                classModel.Methods.Add(methodModel);
            }
        }
Beispiel #14
0
        private IEnumerable <Output> MakeSuspendable(MethodDeclarationSyntax method, SemanticModel semantic)
        {
            var symbol = semantic.GetDeclaredSymbol(method) ?? throw new Exception("GetDeclaredSymbol failed");
            var graph  = ControlFlowGraph.Create(method, semantic);
            var entry  = graph.Entry();

            var graph3     = new Graph3(graph);
            var references = graph3.ToDictionary(pair => pair.Suspension, pair => pair.References);

            Output Dumb(string name, FlowPoint point)
            {
                return(new Dumb(name, symbol, point, references[name], graph3));
            }

            yield return(new Base(symbol, graph3));

            yield return(Dumb("Entry", new FlowPoint(entry)));

            // todo put this code into bfs class
            var visited = new HashSet <BasicBlock>();
            var queue   = new Queue <BasicBlock>();

            queue.Enqueue(entry);

            while (queue.Count > 0)
            {
                var block = queue.Dequeue();
                if (visited.Contains(block))
                {
                    continue;
                }

                for (var i = 0; i < block.Operations.Length; i++)
                {
                    var operation = block.Operations[i];
                    if (operation.Accept(new SuspensionPoint.Is()))
                    {
                        var name = operation.Accept(new SuspensionPoint.Name());
                        yield return(Dumb(name, new FlowPoint(block, i + 1)));
                    }
                }

                visited.Add(block);
                if (block.ConditionalSuccessor is { } conditional)
                {
                    queue.Enqueue(conditional.Destination);
                }

                if (block.FallThroughSuccessor?.Destination is { } destination)
                {
                    queue.Enqueue(destination);
                }
            }

            if (references.ContainsKey("Exit"))
            {
                yield return(new Exit(symbol));
            }
        }
Beispiel #15
0
        public void ControlFlow()
        {
            var graph = ControlFlowGraph.Create(
                new ControlFlowNode(Instructions)
                );

            InstructionTester.RunControlFlowTest(Instructions, graph);
        }
        public void NotEqualsExpression()
        {
            SyntaxNode node = ParseStatement("{ if (a != 0); }");

            ControlFlowGraph cfg = ControlFlowGraph.Create(node);

            Assert.AreEqual(SyntaxKind.NotEqualsExpression, cfg.BasicBlocks[0].Statements[0].CSharpKind());
        }
        public void ReturnStatement()
        {
            SyntaxNode node = ParseStatement("return foo;");

            ControlFlowGraph cfg = ControlFlowGraph.Create(node);

            Assert.AreEqual(1, cfg.BasicBlocks.Count);
            Assert.AreEqual(1, cfg.BasicBlocks[0].Statements.Count);
        }
        public void Block()
        {
            SyntaxNode node = ParseStatement("{ a = 0; a = 0; }");

            ControlFlowGraph cfg = ControlFlowGraph.Create(node);

            Assert.AreEqual(1, cfg.BasicBlocks.Count);
            Assert.AreEqual(2, cfg.BasicBlocks[0].Statements.Count);
        }
Beispiel #19
0
 public void TestGetFlowGraphNullArgument()
 {
     Assert.Throws <ArgumentNullException>(() => ControlFlowGraph.Create((IBlockOperation)null));
     Assert.Throws <ArgumentNullException>(() => ControlFlowGraph.Create((IFieldInitializerOperation)null));
     Assert.Throws <ArgumentNullException>(() => ControlFlowGraph.Create((IPropertyInitializerOperation)null));
     Assert.Throws <ArgumentNullException>(() => ControlFlowGraph.Create((IParameterInitializerOperation)null));
     Assert.Throws <ArgumentNullException>(() => ControlFlowGraph.Create((IConstructorBodyOperation)null));
     Assert.Throws <ArgumentNullException>(() => ControlFlowGraph.Create((IMethodBodyOperation)null));
 }
        public void PrintGraph()
        {
            SyntaxNode node = ParseStatement("{ if (a == null) { return a; } return \"\"; }");

            ControlFlowGraph cfg = ControlFlowGraph.Create(node);

            // FIXME Hardcoded path
            File.WriteAllText(@"C:\Users\vagrant\Desktop\cfg.dot", cfg.ToGraph());
        }
        public void SimpleAssignmentExpression()
        {
            SyntaxNode node = ParseStatement("a = 0;");

            ControlFlowGraph cfg = ControlFlowGraph.Create(node);

            Assert.AreEqual(1, cfg.BasicBlocks.Count);
            Assert.AreEqual(1, cfg.BasicBlocks[0].Statements.Count);
        }
        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.Compile(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 = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(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")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = true")
                {
                    Assert.Fail("We should never get into this branch");
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False);
                    Assert.IsNull(args.ProgramState.GetSymbolValue(aSymbol),
                                  "a is dead, so there should be no associated value to it.");
                }
                if (args.Instruction.ToString() == "a = b")
                {
                    numberOfLastInstructionVisits++;
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(10, numberOfProcessedInstructions);
            Assert.AreEqual(1, numberOfExitBlockReached);
            Assert.AreEqual(1, numberOfLastInstructionVisits);
        }
        public void ExplodedGraph_SequentialInput()
        {
            string        testInput = "var a = true; var b = false; b = !b; a = (b);";
            SemanticModel semanticModel;
            var           method         = ControlFlowGraphTest.Compile(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 = ControlFlowGraph.Create(method.Body, semanticModel);
            var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel);

            var explodedGraph    = new ExplodedGraph(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")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = !b")
                {
                    Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False);
                    Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "a = (b)")
                {
                    Assert.AreEqual(
                        args.ProgramState.GetSymbolValue(bSymbol),
                        args.ProgramState.GetSymbolValue(aSymbol));
                }
            };

            explodedGraph.Walk();

            Assert.IsTrue(explorationEnded);
            Assert.AreEqual(11, numberOfProcessedInstructions);
            Assert.AreEqual(1, numberOfExitBlockReached);
        }
        public void Test_02_ControlFlowGraph()
        {
            var compilation = CodeAnalysisTestingUtils.CreateFakeCompilation().LoadDocuments("TestData_ControlFlowGraph.cs");

            var(method, model) = compilation.FindDocument().FindMethod("ControlFlowGraphExample");

            var graph   = ControlFlowGraph.Create(method, model) ?? throw new Exception("Control flow graph is null");
            var message = RoslynDisplayUtils.GetDisplayString(graph);

            TestContext.WriteLine(message);
        }
Beispiel #25
0
        public void Run(MethodBody body)
        {
            this.context = new DecompilationContext(body, ControlFlowGraph.Create(body.Method));
            var block = new BlockStatement();

            foreach (var step in steps)
            {
                block = step.Process(context, block);
            }

            body_block = block;
        }
Beispiel #26
0
        static ControlFlowGraph GetTreeCFG(Compilation compilation)
        {
            var tree = compilation.SyntaxTrees.Single();

            var root = tree.GetRoot();

            var semanticModel   = compilation.GetSemanticModel(tree);
            var firstMethod     = root.DescendantNodes().OfType <BaseMethodDeclarationSyntax>().First();
            var firstMethodOper = semanticModel.GetOperation(firstMethod) as IMethodBodyOperation;

            return(ControlFlowGraph.Create(firstMethodOper));
        }
 public string getIL_usingControlFLowGraph(MethodDefinition method)
 {
     try
     {
         ControlFlowGraph cfg = ControlFlowGraph.Create(method);
         return(this.FormatControlFlowGraph(cfg));
     }
     catch (Exception exception)
     {
         DI.log.error("in CecilDecompiler.getIL :{0} \n\n{1}\n\n", new object[] { exception.Message, exception.StackTrace });
     }
     return("");
 }
        public static ControlFlowGraph GetControlFlowGraph(SyntaxNode syntaxNode, SemanticModel model)
        {
            IOperation operationRoot = model.GetOperation(syntaxNode);

            // Workaround for unit tests designed to work on IBlockOperation with ConstructorBodyOperation/MethodBodyOperation parent.
            operationRoot = operationRoot.Kind == OperationKind.Block &&
                            (operationRoot.Parent?.Kind == OperationKind.ConstructorBodyOperation ||
                             operationRoot.Parent?.Kind == OperationKind.MethodBodyOperation) ?
                            operationRoot.Parent :
                            operationRoot;

            TestOperationVisitor.VerifySubTree(operationRoot);

            ControlFlowGraph graph;

            switch (operationRoot)
            {
            case IBlockOperation blockOperation:
                graph = ControlFlowGraph.Create(blockOperation);
                break;

            case IMethodBodyOperation methodBodyOperation:
                graph = ControlFlowGraph.Create(methodBodyOperation);
                break;

            case IConstructorBodyOperation constructorBodyOperation:
                graph = ControlFlowGraph.Create(constructorBodyOperation);
                break;

            case IFieldInitializerOperation fieldInitializerOperation:
                graph = ControlFlowGraph.Create(fieldInitializerOperation);
                break;

            case IPropertyInitializerOperation propertyInitializerOperation:
                graph = ControlFlowGraph.Create(propertyInitializerOperation);
                break;

            case IParameterInitializerOperation parameterInitializerOperation:
                graph = ControlFlowGraph.Create(parameterInitializerOperation);
                break;

            default:
                return(null);
            }

            Assert.NotNull(graph);
            Assert.Same(operationRoot, graph.OriginalOperation);
            return(graph);
        }
Beispiel #29
0
        public void EmitControlFlowGraph(FunctionSymbol function)
        {
            var cfgStatement =
                program.Functions.SingleOrDefault(kvp => kvp.Key.Name == function.Name).Value;

            var cfg = ControlFlowGraph.Create(cfgStatement);

            var appPath      = Environment.GetCommandLineArgs()[0];
            var appDirectory = Path.GetDirectoryName(appPath);
            var cfgPath      = Path.Combine(appDirectory, "cfg.dot");

            using var streamWriter = new StreamWriter(cfgPath);

            cfg.WriteTo(streamWriter);
        }
        private static ParameterValidationResultWithHazardousUsages GetOrComputeResult(
            IOperation topmostBlock,
            ISymbol owningSymbol,
            WellKnownTypeProvider wellKnownTypeProvider,
            Func <IBlockOperation, IMethodSymbol, ParameterValidationResultWithHazardousUsages> getOrComputeLocationAnalysisResultOpt,
            bool pessimisticAnalysis)
        {
            var cfg = ControlFlowGraph.Create(topmostBlock);
            var pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.GetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider);
            var copyAnalysisResult     = CopyAnalysis.CopyAnalysis.GetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, pointsToAnalysisResultOpt: pointsToAnalysisResult);

            // Do another analysis pass to improve the results from PointsTo and Copy analysis.
            pointsToAnalysisResult = PointsToAnalysis.PointsToAnalysis.GetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, pointsToAnalysisResult, copyAnalysisResult);
            return(GetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, pointsToAnalysisResult, getOrComputeLocationAnalysisResultOpt, pessimisticAnalysis));
        }