Ejemplo n.º 1
0
        private void WriteUCFG <TDeclarationSyntax>(SyntaxNodeAnalysisContext context, Func <TDeclarationSyntax, CSharpSyntaxNode> getBody)
            where TDeclarationSyntax : SyntaxNode
        {
            var declaration = (TDeclarationSyntax)context.Node;

            var symbol = context.SemanticModel.GetDeclaredSymbol(declaration);

            var methodSymbol = (symbol is IPropertySymbol propertySymbol)
                ? propertySymbol.GetMethod // We are in PropertyDeclarationSyntax
                : symbol as IMethodSymbol; // all other are methods

            if (methodSymbol == null ||
                methodSymbol.IsAbstract ||
                methodSymbol.IsExtern ||
                !CSharpControlFlowGraph.TryGet(getBody(declaration), context.SemanticModel, out var cfg))
            {
                return;
            }

            var ucfg = new UniversalControlFlowGraphBuilder()
                       .Build(context.SemanticModel, declaration, methodSymbol, cfg);

            if (!IsValid(ucfg))
            {
                return;
            }

            var path = Path.Combine(protobufDirectory,
                                    $"ucfg_{projectBuildId}_{Interlocked.Increment(ref protobufFileIndex)}.pb");

            using (var stream = File.Create(path))
            {
                ucfg.WriteTo(stream);
            }
        }
        private static void ReportOnDeadParametersAtEntry(MethodContext declaration, IImmutableList <IParameterSymbol> noReportOnParameters)
        {
            var bodyNode = (CSharpSyntaxNode)declaration.Body ?? declaration.ExpressionBody;

            if (bodyNode == null || declaration.Context.Node.IsKind(SyntaxKind.ConstructorDeclaration))
            {
                return;
            }

            var excludedParameters = noReportOnParameters;

            if (declaration.Symbol.IsExtensionMethod)
            {
                excludedParameters = excludedParameters.Add(declaration.Symbol.Parameters.First());
            }
            excludedParameters = excludedParameters.AddRange(declaration.Symbol.Parameters.Where(p => p.RefKind != RefKind.None));

            var candidateParameters = declaration.Symbol.Parameters.Except(excludedParameters);

            if (!candidateParameters.Any())
            {
                return;
            }
            if (CSharpControlFlowGraph.TryGet(bodyNode, declaration.Context.SemanticModel, out var cfg))
            {
                var lva            = CSharpLiveVariableAnalysis.Analyze(cfg, declaration.Symbol, declaration.Context.SemanticModel);
                var liveParameters = lva.GetLiveIn(cfg.EntryBlock).OfType <IParameterSymbol>();
                ReportOnUnusedParameters(declaration, candidateParameters.Except(liveParameters).Except(lva.CapturedVariables), MessageDead, isRemovable: false);
            }
        }
Ejemplo n.º 3
0
        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("}");
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
0
        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);
        }
        private void ProcessLocalFunction(SyntaxNode instruction, HashSet <ISymbol> assignedInBlock,
                                          HashSet <ISymbol> usedBeforeAssigned, HashSet <ISymbol> processedLocalFunctions)
        {
            var symbol = semanticModel.GetSymbolInfo(((InvocationExpressionSyntax)instruction).Expression).Symbol;

            // Local function invocation
            if (symbol != null &&
                (processedLocalFunctions == null || !processedLocalFunctions.Contains(symbol)) &&
                symbol.ContainingSymbol is IMethodSymbol &&
                symbol.DeclaringSyntaxReferences.Length == 1 &&
                symbol.DeclaringSyntaxReferences.Single().GetSyntax() is CSharpSyntaxNode node &&
                node.Kind() == SyntaxKindEx.LocalFunctionStatement &&
                (LocalFunctionStatementSyntaxWrapper)node is LocalFunctionStatementSyntaxWrapper function &&
                CSharpControlFlowGraph.TryGet(function.Body ?? function.ExpressionBody as CSharpSyntaxNode, semanticModel, out var cfg))
            {
                processedLocalFunctions = processedLocalFunctions ?? new HashSet <ISymbol>();
                processedLocalFunctions.Add(symbol);
                foreach (var block in cfg.Blocks.Reverse())
                {
                    ProcessBlockInternal(block, processedLocalFunctions, out var subAssigned, out var subUsed);
                    assignedInBlock.UnionWith(subAssigned);
                    usedBeforeAssigned.UnionWith(subUsed);
                }
            }
        }
Ejemplo n.º 8
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);

            try
            {
                var explodedGraph = new CSharpExplodedGraph(cfg, symbol, context.SemanticModel, lva);
                analyze(explodedGraph, context);
            }
            catch (Exception e)
            {
                // Roslyn/MSBuild is currently cutting exception message at the end of the line instead
                // of displaying the full message. As a workaround, we replace the line ending with ' ## '.
                // See https://github.com/dotnet/roslyn/issues/1455 and https://github.com/dotnet/roslyn/issues/24346
                var sb = new StringBuilder();
                sb.AppendLine($"Error processing method: {symbol?.Name ?? "{unknown}"}");
                sb.AppendLine($"Method file: {declarationBody.GetLocation()?.GetLineSpan().Path ?? "{unknown}"}");
                sb.AppendLine($"Method line: {declarationBody.GetLocation()?.GetLineSpan().StartLinePosition.ToString() ?? "{unknown}"}");
                sb.AppendLine($"Inner exception: {e.ToString()}");

                throw new SymbolicExecutionException(sb.ToString().Replace(Environment.NewLine, " ## "), e);
            }
        }
Ejemplo n.º 9
0
        private void WriteUCFG <TDeclarationSyntax>(SyntaxNodeAnalysisContext context, Func <TDeclarationSyntax, CSharpSyntaxNode> getBody)
            where TDeclarationSyntax : SyntaxNode
        {
            var declaration = (TDeclarationSyntax)context.Node;

            var symbol = context.SemanticModel.GetDeclaredSymbol(declaration);

            var methodSymbol = (symbol is IPropertySymbol propertySymbol)
                ? propertySymbol.GetMethod // We are in PropertyDeclarationSyntax
                : symbol as IMethodSymbol; // all other are methods

            if (methodSymbol == null ||
                methodSymbol.IsAbstract ||
                methodSymbol.IsExtern ||
                !CSharpControlFlowGraph.TryGet(getBody(declaration), context.SemanticModel, out var cfg))
            {
                return;
            }

            var ucfg = new UniversalControlFlowGraphBuilder()
                       .Build(context.SemanticModel, declaration, methodSymbol, cfg);

            if (IsValid(ucfg))
            {
                var fileName = $"{projectBuildId}_{Interlocked.Increment(ref protobufFileIndex)}";

                WriteProtobuf(ucfg, Path.Combine(protobufDirectory, $"ucfg_{fileName}.pb"));

                if (ShouldGenerateDot)
                {
                    WriteDot(Path.Combine(protobufDirectory, $"ucfg_{fileName}.dot"), writer => UcfgSerializer.Serialize(ucfg, writer));
                    WriteDot(Path.Combine(protobufDirectory, $"cfg_{fileName}.dot"), writer => CfgSerializer.Serialize(ucfg.MethodId, cfg, writer));
                }
            }
        }
Ejemplo n.º 10
0
        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)));
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        private static void CheckForNoExitMethod(SyntaxNodeAnalysisContext c, CSharpSyntaxNode body, SyntaxToken identifier)
        {
            var symbol = c.SemanticModel.GetDeclaredSymbol(c.Node);

            if (symbol != null && body != null && CSharpControlFlowGraph.TryGet(body, c.SemanticModel, out var cfg))
            {
                var walker = new CfgWalkerForMethod(new RecursionAnalysisContext(cfg, symbol, identifier.GetLocation(), c));
                walker.CheckPaths();
                CheckInfiniteJumpLoop(body, cfg, "method", c);
            }
        }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
0
        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);
        }
Ejemplo n.º 15
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++; };
 }
Ejemplo n.º 16
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);
            }
        }
Ejemplo n.º 17
0
        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);
        }
Ejemplo n.º 18
0
        private static void CheckForNoExitProperty(SyntaxNodeAnalysisContext c)
        {
            var property       = (PropertyDeclarationSyntax)c.Node;
            var propertySymbol = c.SemanticModel.GetDeclaredSymbol(property);

            if (propertySymbol == null)
            {
                return;
            }

            IControlFlowGraph cfg;

            if (property.ExpressionBody?.Expression != null)
            {
                if (CSharpControlFlowGraph.TryGet(property.ExpressionBody.Expression, c.SemanticModel, out cfg))
                {
                    var walker = new CfgWalkerForProperty(
                        new RecursionAnalysisContext(cfg, propertySymbol, property.Identifier.GetLocation(), c),
                        "property's recursion",
                        isSetAccessor: false);
                    walker.CheckPaths();
                }
                return;
            }

            var accessors = property.AccessorList?.Accessors.Where(a => a.HasBodyOrExpressionBody());

            if (accessors != null)
            {
                foreach (var accessor in accessors)
                {
                    var bodyNode = (CSharpSyntaxNode)accessor.Body ?? accessor.ExpressionBody();
                    if (CSharpControlFlowGraph.TryGet(bodyNode, c.SemanticModel, out cfg))
                    {
                        var walker = new CfgWalkerForProperty(
                            new RecursionAnalysisContext(cfg, propertySymbol, accessor.Keyword.GetLocation(), c),
                            "property accessor's recursion",
                            isSetAccessor: accessor.Keyword.IsKind(SyntaxKind.SetKeyword));
                        walker.CheckPaths();

                        CheckInfiniteJumpLoop(bodyNode, cfg, "property accessor", c);
                    }
                }
            }
        }
        private static bool IsSymbolFirstSetInCtor(ISymbol declaredSymbol, CtorDeclarationTuple ctor)
        {
            if (ctor.SyntaxNode.Initializer != null &&
                ctor.SyntaxNode.Initializer.ThisOrBaseKeyword.IsKind(SyntaxKind.ThisKeyword))
            {
                // Calls another ctor, which is also checked.
                return(true);
            }

            if (!CSharpControlFlowGraph.TryGet(ctor.SyntaxNode.Body, ctor.SemanticModel, out var cfg))
            {
                return(false);
            }

            var checker = new MemberInitializerRedundancyChecker(cfg, declaredSymbol, ctor.SemanticModel);

            return(checker.CheckAllPaths());
        }
Ejemplo n.º 20
0
        private static void CheckForRedundantJumps(CSharpSyntaxNode node, SyntaxNodeAnalysisContext context)
        {
            if (!CSharpControlFlowGraph.TryGet(node, context.SemanticModel, out var cfg))
            {
                return;
            }

            var yieldStatementCount = node.DescendantNodes().OfType <YieldStatementSyntax>().Count();

            var removableJumps = cfg.Blocks
                                 .OfType <JumpBlock>()
                                 .Where(jumpBlock => IsJumpRemovable(jumpBlock, yieldStatementCount));

            foreach (var jumpBlock in removableJumps)
            {
                context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, jumpBlock.JumpNode.GetLocation()));
            }
        }
Ejemplo n.º 21
0
        private void WriteUcfg <TDeclarationSyntax>(SyntaxNodeAnalysisContext context, Func <TDeclarationSyntax, CSharpSyntaxNode> getBody)
            where TDeclarationSyntax : SyntaxNode
        {
            var declaration = (TDeclarationSyntax)context.Node;

            var symbol = context.SemanticModel.GetDeclaredSymbol(declaration);

            var methodSymbol = (symbol is IPropertySymbol propertySymbol)
                ? propertySymbol.GetMethod // We are in PropertyDeclarationSyntax
                : symbol as IMethodSymbol; // all other are methods

            if (methodSymbol == null ||
                methodSymbol.IsAbstract ||
                methodSymbol.IsExtern ||
                !CSharpControlFlowGraph.TryGet(getBody(declaration), context.SemanticModel, out var cfg))
            {
                return;
            }

            try
            {
                var ucfg = new UcfgFactory(context.SemanticModel)
                           .Create(declaration, methodSymbol, cfg);

                if (!IsValid(ucfg))
                {
                    return;
                }

                var fileName = $"{this.projectBuildId}_{Interlocked.Increment(ref this.protobufFileIndex)}";

                WriteProtobuf(ucfg, Path.Combine(this.protobufDirectory, $"ucfg_{fileName}.pb"));

                if (ShouldGenerateDot)
                {
                    WriteDot(Path.Combine(this.protobufDirectory, $"ucfg_{fileName}.dot"), writer => UcfgSerializer.Serialize(ucfg, writer));
                    WriteDot(Path.Combine(this.protobufDirectory, $"cfg_{fileName}.dot"), writer => CfgSerializer.Serialize(ucfg.MethodId, cfg, writer));
                }
            }
            catch (UcfgException) when(!DebugHelper.IsInternalDebuggingContext())
            {
                // Ignore the exception in production
            }
        }
Ejemplo n.º 22
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);
        }
Ejemplo n.º 23
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);
        }
Ejemplo n.º 24
0
        private static void CheckForNoExitMethod(SyntaxNodeAnalysisContext c)
        {
            var method       = (MethodDeclarationSyntax)c.Node;
            var methodSymbol = c.SemanticModel.GetDeclaredSymbol(method);

            if (methodSymbol == null)
            {
                return;
            }

            if (CSharpControlFlowGraph.TryGet(method.Body, c.SemanticModel, out var cfg) ||
                CSharpControlFlowGraph.TryGet(method.ExpressionBody?.Expression, c.SemanticModel, out cfg))
            {
                var walker = new CfgWalkerForMethod(
                    new RecursionAnalysisContext(cfg, methodSymbol, method.Identifier.GetLocation(), c));
                walker.CheckPaths();

                CheckInfiniteJumpLoop(method.Body, cfg, "method", c);
            }
        }
Ejemplo n.º 25
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);
            }
Ejemplo n.º 26
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);
        }
Ejemplo n.º 27
0
        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);
        }
Ejemplo n.º 28
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);
            }
        }
Ejemplo n.º 29
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);
        }
Ejemplo n.º 30
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);
        }