Пример #1
0
        protected Program RewriteFile(
            string relativePath,
            Address addrBase,
            Func <IServiceProvider, IProcessorArchitecture, IPlatform> mkPlatform)
        {
            var sc = new ServiceContainer();

            PopulateServiceContainer(sc);
            var     arch    = new X86ArchitectureReal(sc, "x86-real-16", new Dictionary <string, object>());
            ILoader ldr     = new Loader(sc);
            var     program = ldr.AssembleExecutable(
                ImageLocation.FromUri(FileUnitTester.MapTestPath(relativePath)),
                new X86TextAssembler(arch),
                null,
                addrBase);

            program.Platform = mkPlatform(sc, program.Architecture);

            var ep      = ImageSymbol.Procedure(arch, program.SegmentMap.BaseAddress);
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                project.LoadedMetadata,
                new DynamicLinker(project, program, eventListener),
                sc);

            scan.EnqueueImageSymbol(ep, true);
            scan.ScanImage();

            var dynamicLinker = new DynamicLinker(project, program, eventListener);
            var dfa           = new DataFlowAnalysis(program, dynamicLinker, sc);

            dfa.AnalyzeProgram();
            return(program);
        }
Пример #2
0
        private void Build(Program prog)
        {
            DataFlowAnalysis dfa = new DataFlowAnalysis(prog, new FakeDecompilerEventListener());

            dfa.UntangleProcedures();
            foreach (Procedure proc in prog.Procedures.Values)
            {
                Aliases alias = new Aliases(proc, prog.Architecture);
                alias.Transform();
                var          gr  = proc.CreateBlockDominatorGraph();
                SsaTransform sst = new SsaTransform(dfa.ProgramDataFlow, proc, gr);
                SsaState     ssa = sst.SsaState;

                ConditionCodeEliminator cce = new ConditionCodeEliminator(ssa.Identifiers, prog.Platform);
                cce.Transform();

                DeadCode.Eliminate(proc, ssa);

                var vp = new ValuePropagator(prog.Architecture, ssa.Identifiers, proc);
                vp.Transform();

                DeadCode.Eliminate(proc, ssa);

                Coalescer coa = new Coalescer(proc, ssa);
                coa.Transform();

                DeadCode.Eliminate(proc, ssa);

                LiveCopyInserter lci = new LiveCopyInserter(proc, ssa.Identifiers);
                lci.Transform();

                WebBuilder web = new WebBuilder(proc, ssa.Identifiers, new Dictionary <Identifier, LinearInductionVariable>());
                web.Transform();

                ssa.ConvertBack(false);
            }
        }
Пример #3
0
        protected void DumpProcedureFlows(Program program, DataFlowAnalysis dfa, RegisterLiveness live, TextWriter w)
        {
            foreach (Procedure proc in program.Procedures.Values)
            {
                w.WriteLine("// {0} /////////////////////", proc.Name);
                ProcedureFlow flow = dfa.ProgramDataFlow[proc];
                DataFlow.EmitRegisters(program.Architecture, "\tLiveOut:  ", flow.grfLiveOut, flow.LiveOut, w);
                w.WriteLine();
                DataFlow.EmitRegisters(program.Architecture, "\tMayUseIn: ", flow.grfMayUse, flow.MayUse, w);
                w.WriteLine();
                DataFlow.EmitRegisters(program.Architecture, "\tBypassIn: ", flow.grfMayUse, flow.ByPass, w);
                w.WriteLine();
                DataFlow.EmitRegisters(program.Architecture, "\tTrashed:  ", flow.grfTrashed, flow.TrashedRegisters, w);
                w.WriteLine();
                DataFlow.EmitRegisters(program.Architecture, "\tPreserved:", flow.grfPreserved, flow.PreservedRegisters, w);
                w.WriteLine();

                w.WriteLine("// {0}", proc.Name);
                proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, new TextFormatter(w));
                w.WriteLine();
                foreach (Block block in proc.SortBlocksByName())
                {
                    if (live != null)
                    {
                        var bFlow = dfa.ProgramDataFlow[block];
                        bFlow.WriteBefore(program.Architecture, w);
                        block.Write(w);
                        bFlow.WriteAfter(program.Architecture, w);
                        w.WriteLine();
                    }
                    else
                    {
                        block.Write(w);
                    }
                }
            }
        }
Пример #4
0
        public void AnalysisOnArrayAccess()
        {
            var           source = @"
public class Sample
{
   public void Foo()
   {
        int[] outerArray = new int[10] { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4};
        for (int index = 0; index < 10; index++)
        {
             int[] innerArray = new int[10] { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 };
             index = index + 2;
             outerArray[index - 1] = 5;
        }
   }
}";
            var           tree   = CSharpSyntaxTree.ParseText(source);
            SemanticModel model  = GetSemanticModel(tree);

            var forStatement        = tree.GetRoot().DescendantNodes().OfType <ForStatementSyntax>().Single();
            DataFlowAnalysis result = model.AnalyzeDataFlow(forStatement);

            Trace.WriteLine(source);
            DumpSymbolArray("Always Assigned", result.AlwaysAssigned);
            DumpSymbolArray("Written Outside", result.WrittenOutside);
            DumpSymbolArray("Written Inside", result.WrittenInside);
            DumpSymbolArray("Read Inside", result.ReadInside);
            DumpSymbolArray("Variables Declared", result.VariablesDeclared);

            void DumpSymbolArray(string prefix, ImmutableArray <ISymbol> symbols)
            {
                foreach (var symbol in symbols)
                {
                    Trace.WriteLine($"{prefix}: {symbol}");
                }
            }
        }
Пример #5
0
        public void AnalyzeRegionDataFlow()
        {
            TestCode        testCode = new TestCode(@"
class C {
    public void F(int x)
    {
        int a;
/*start*/
        int b;
        int x, y = 1;
        { var z = ""a""; }
/*end*/
        int c;
    }
}");
            StatementSyntax firstStatement, lastStatement;

            testCode.GetStatementsBetweenMarkers(out firstStatement, out lastStatement);
            DataFlowAnalysis regionDataFlowAnalysis = testCode.SemanticModel.AnalyzeDataFlow(firstStatement, lastStatement);

            Assert.AreEqual("b,x,y,z", string.Join(",", regionDataFlowAnalysis
                                                   .VariablesDeclared
                                                   .Select(symbol => symbol.Name)));
        }
Пример #6
0
        private void PerformTest(FileUnitTester fut)
        {
            DataFlowAnalysis dfa = new DataFlowAnalysis(program, null, new FakeDecompilerEventListener());

            dfa.UntangleProcedures();
            foreach (Procedure proc in program.Procedures.Values)
            {
                Aliases alias = new Aliases(proc, program.Architecture);
                alias.Transform();
                SsaTransform sst = new SsaTransform(dfa.ProgramDataFlow, proc, null, proc.CreateBlockDominatorGraph());
                SsaState     ssa = sst.SsaState;

                proc.Write(false, fut.TextWriter);
                fut.TextWriter.WriteLine();

                OutParameterTransformer opt = new OutParameterTransformer(proc, ssa.Identifiers);
                opt.Transform();

                DeadCode.Eliminate(proc, ssa);

                proc.Write(false, fut.TextWriter);
                fut.TextWriter.WriteLine("====================");
            }
        }
Пример #7
0
        public void Dfa2_FactorialReg()
        {
            pb = new ProgramBuilder();
            pb.Add("fact", m =>
            {
                var sp = m.Register(m.Architecture.StackRegister);
                var r1 = m.Register(1);
                var r2 = m.Register(2);
                var r3 = m.Register(3);
                var cc = m.Flags(0xF, "cc");
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(r2, r1);
                m.Assign(r1, 1);
                m.Assign(cc, m.Cond(m.ISub(r2, r1)));
                m.BranchIf(m.Test(ConditionCode.LE, cc), "done");

                m.Assign(sp, m.ISub(sp, 4));
                m.Store(sp, r2);
                m.Assign(r1, m.ISub(r2, r1));
                m.Call("fact", 0);
                m.Assign(r2, m.LoadDw(sp));
                m.Assign(sp, m.IAdd(sp, 4));
                m.Assign(r1, m.IMul(r1, r2));

                m.Label("done");
                m.Return();
            });

            var dfa = new DataFlowAnalysis(pb.BuildProgram(), new FakeDecompilerEventListener());

            dfa.UntangleProcedures2();
            var sExp =
                @"@@@";

            AssertProgram(sExp, pb);
        }
Пример #8
0
        public static bool IsLocalVariable(this SemanticModel semanticModel, MethodDeclarationSyntax containingMethod, string?variableName)
        {
            semanticModel.ThrowOnNull(nameof(semanticModel));
            containingMethod.ThrowOnNull(nameof(containingMethod));

            if (variableName.IsNullOrWhiteSpace())
            {
                return(false);
            }

            if (containingMethod.Body == null)
            {
                return(false);
            }

            DataFlowAnalysis dataFlowAnalysis = semanticModel.AnalyzeDataFlow(containingMethod.Body);

            if (dataFlowAnalysis == null || !dataFlowAnalysis.Succeeded)
            {
                return(false);
            }

            return(dataFlowAnalysis.VariablesDeclared.Any(var => var.Name == variableName));
        }
Пример #9
0
        private Program RewriteProgram()
        {
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                new Dictionary <Address, ProcedureSignature>(),
                new ImportResolver(project),
                new FakeDecompilerEventListener());

            foreach (EntryPoint ep in program.EntryPoints)
            {
                scan.EnqueueEntryPoint(ep);
            }
            scan.ScanImage();

            DecompilerEventListener eventListener = new FakeDecompilerEventListener();
            DataFlowAnalysis        da            = new DataFlowAnalysis(program, eventListener);

            da.AnalyzeProgram();

            return(program);
        }
Пример #10
0
        protected override void RunTest(Program program, TextWriter writer)
        {
            DataFlowAnalysis dfa = new DataFlowAnalysis(program, null, new FakeDecompilerEventListener());

            dfa.UntangleProcedures();
            foreach (Procedure proc in program.Procedures.Values)
            {
                Aliases alias = new Aliases(proc, program.Architecture);
                alias.Transform();
                SsaTransform sst = new SsaTransform(
                    dfa.ProgramDataFlow,
                    proc,
                    null,
                    proc.CreateBlockDominatorGraph(),
                    program.Platform.CreateImplicitArgumentRegisters());
                SsaState ssa = sst.SsaState;
                ConditionCodeEliminator cce = new ConditionCodeEliminator(ssa, program.Platform);
                cce.Transform();

                DeadCode.Eliminate(proc, ssa);
                ssa.Write(writer);
                proc.Write(false, writer);
            }
        }
Пример #11
0
        protected void RunHexTest(string hexFile, string outputFile)
        {
            var svc = new ServiceContainer();
            var cfg = new FakeDecompilerConfiguration();

            svc.AddService <IConfigurationService>(cfg);
            ILoader ldr       = new Loader(svc);
            var     imgLoader = new DchexLoader(FileUnitTester.MapTestPath(hexFile), svc, null);
            var     img       = imgLoader.Load(null);
            var     program   = new Program(img.Image, img.Image.CreateImageMap(), img.Architecture, img.Platform);
            var     project   = new Project {
                Programs = { program }
            };
            var ep   = new EntryPoint(program.Image.BaseAddress, program.Architecture.CreateProcessorState());
            var scan = new Scanner(program, new Dictionary <Address, ProcedureSignature>(), new ImportResolver(project), new FakeDecompilerEventListener());

            scan.EnqueueEntryPoint(ep);
            scan.ScanImage();

            var dfa = new DataFlowAnalysis(program, new FakeDecompilerEventListener());

            dfa.AnalyzeProgram();
            RunTest(program, outputFile);
        }
Пример #12
0
        protected void DumpProcedureFlows(Program program, DataFlowAnalysis dfa, TextWriter w)
        {
            foreach (Procedure proc in program.Procedures.Values)
            {
                w.WriteLine("// {0} /////////////////////", proc.Name);
                ProcedureFlow flow = dfa.ProgramDataFlow[proc];
                DataFlow.EmitRegisters(program.Architecture, "\tLiveOut:  ", flow.grfLiveOut, flow.BitsLiveOut, w);
                w.WriteLine();
                DataFlow.EmitRegisterValues("\tBitsUsed: ", flow.BitsUsed, w);
                w.WriteLine();
                DataFlow.EmitRegisters(program.Architecture, "\tTrashed:  ", flow.grfTrashed, flow.Trashed, w);
                w.WriteLine();
                DataFlow.EmitRegisters(program.Architecture, "\tPreserved:", flow.grfPreserved, flow.Preserved, w);
                w.WriteLine();

                w.WriteLine("// {0}", proc.Name);
                proc.Signature.Emit(proc.Name, FunctionType.EmitFlags.None, new TextFormatter(w));
                w.WriteLine();
                foreach (Block block in proc.SortBlocksByName())
                {
                    block.Write(w);
                }
            }
        }
        private void RunTest(string sExp, Program program)
        {
            var sc = new ServiceContainer();

            sc.AddService(eventListener.Object);

            var dfa = new DataFlowAnalysis(
                program,
                import.Object,
                sc);
            var ssts = dfa.RewriteProceduresToSsa();

            var uvr = new UnusedOutValuesRemover(
                program,
                ssts.Select(sst => sst.SsaState),
                dfa.ProgramDataFlow,
                import.Object,
                eventListener.Object);

            uvr.Transform();

            var sb = new StringWriter();

            foreach (var proc in program.Procedures.Values)
            {
                proc.Write(false, sb);
                sb.WriteLine("===");
            }
            var sActual = sb.ToString();

            if (sExp != sActual)
            {
                Console.WriteLine(sActual);
                Assert.AreEqual(sExp, sActual);
            }
        }
Пример #14
0
        protected Program RewriteFile(string relativePath, Address addrBase)
        {
            sc = new ServiceContainer();
            var config        = new FakeDecompilerConfiguration();
            var eventListener = new FakeDecompilerEventListener();

            sc.AddService <IConfigurationService>(config);
            sc.AddService <IDecompiledFileService>(new FakeDecompiledFileService());
            sc.AddService <DecompilerEventListener>(eventListener);
            sc.AddService <IFileSystemService>(new FileSystemServiceImpl());
            var     arch    = new X86ArchitectureReal("x86-real-16");
            ILoader ldr     = new Loader(sc);
            var     program = ldr.AssembleExecutable(
                FileUnitTester.MapTestPath(relativePath),
                new X86TextAssembler(sc, arch),
                addrBase);

            program.Platform = new DefaultPlatform(sc, program.Architecture);
            var ep      = ImageSymbol.Procedure(arch, program.SegmentMap.BaseAddress);
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                new ImportResolver(project, program, eventListener),
                sc);

            scan.EnqueueImageSymbol(ep, true);
            scan.ScanImage();

            var importResolver = new ImportResolver(project, program, eventListener);
            var dfa            = new DataFlowAnalysis(program, importResolver, eventListener);

            dfa.AnalyzeProgram();
            return(program);
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AssignDefaultValueToOutParameter))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            SyntaxNode node = root
                              .FindNode(context.Span, getInnermostNodeForTie: true)?
                              .FirstAncestorOrSelf(f => f.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement) || f is StatementSyntax);

            Debug.Assert(node != null, $"{nameof(node)} is null");

            if (node == null)
            {
                return;
            }

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.OutParameterMustBeAssignedToBeforeControlLeavesCurrentMethod:
                {
                    SyntaxNode bodyOrExpressionBody = null;

                    StatementSyntax statement = null;

                    if (!node.IsKind(SyntaxKind.LocalFunctionStatement))
                    {
                        statement = node as StatementSyntax;
                    }

                    if (statement != null)
                    {
                        node = node.FirstAncestor(f => f.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement));
                    }

                    bodyOrExpressionBody = GetBodyOrExpressionBody(node);

                    SemanticModel semanticModel = await context.Document.GetSemanticModelAsync().ConfigureAwait(false);

                    var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(node);

                    DataFlowAnalysis dataFlowAnalysis = AnalyzeDataFlow(bodyOrExpressionBody, semanticModel);

                    // Flow analysis APIs do not work with local functions: https://github.com/dotnet/roslyn/issues/14214
                    if (!dataFlowAnalysis.Succeeded)
                    {
                        break;
                    }

                    ImmutableArray <ISymbol> alwaysAssigned = dataFlowAnalysis.AlwaysAssigned;

                    foreach (IParameterSymbol parameter in methodSymbol.Parameters)
                    {
                        if (parameter.RefKind == RefKind.Out &&
                            !alwaysAssigned.Contains(parameter))
                        {
                            CodeAction codeAction = CodeAction.Create(
                                $"Assign default value to parameter '{parameter.Name}'",
                                cancellationToken => RefactorAsync(context.Document, node, statement, bodyOrExpressionBody, parameter, semanticModel, cancellationToken),
                                GetEquivalenceKey(diagnostic));

                            context.RegisterCodeFix(codeAction, diagnostic);
                        }
                    }

                    break;
                }
                }
            }
        }
Пример #16
0
        internal static string CalcCondExpFuncOptions(DataFlowAnalysis dataFlow, ITypeSymbol typeSym, List <string> inputs, List <string> outputs, bool needFuncInfo)
        {
            string returnType         = ClassInfo.GetFullName(typeSym);
            string returnTypeKind     = "TypeKind." + typeSym.TypeKind;
            bool   returnTypeIsExtern = !SymbolTable.Instance.IsCs2DslSymbol(typeSym);

            var sb = new StringBuilder();

            sb.AppendFormat("needfuncinfo({0}), rettype(return, {1}, {2}, 0, {3})", needFuncInfo ? "true" : "false", returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false");
            foreach (var v in dataFlow.DataFlowsOut)
            {
                sb.Append(", ");
                int refOrOut = 2;
                if (inputs.Contains(v.Name))
                {
                    refOrOut = 1;
                }
                var psym = v as IParameterSymbol;
                var lsym = v as ILocalSymbol;
                if (null != psym)
                {
                    var  type     = ClassInfo.GetFullName(psym.Type);
                    var  typeKind = psym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
                else if (null != lsym)
                {
                    var  type     = ClassInfo.GetFullName(lsym.Type);
                    var  typeKind = lsym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
            }
            foreach (var v in dataFlow.DataFlowsIn)
            {
                if (v.Name == "this")
                {
                    continue;
                }
                sb.Append(", ");
                int refOrOut = 0;
                if (outputs.Contains(v.Name))
                {
                    refOrOut = 1;
                }
                var psym = v as IParameterSymbol;
                var lsym = v as ILocalSymbol;
                if (null != psym)
                {
                    var  type     = ClassInfo.GetFullName(psym.Type);
                    var  typeKind = psym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
                else if (null != lsym)
                {
                    var  type     = ClassInfo.GetFullName(lsym.Type);
                    var  typeKind = lsym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
            }
            foreach (var v in dataFlow.DataFlowsOut)
            {
                sb.Append(", ");
                int refOrOut = 2;
                if (inputs.Contains(v.Name))
                {
                    refOrOut = 1;
                }
                var psym = v as IParameterSymbol;
                var lsym = v as ILocalSymbol;
                if (null != psym)
                {
                    var  type     = ClassInfo.GetFullName(psym.Type);
                    var  typeKind = psym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
                else if (null != lsym)
                {
                    var  type     = ClassInfo.GetFullName(lsym.Type);
                    var  typeKind = lsym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
            }
            return(sb.ToString());
        }
Пример #17
0
        internal string CalcTryUsingFuncOptions(DataFlowAnalysis dataFlow, ControlFlowAnalysis ctrlFlow, List <string> inputs, List <string> outputs)
        {
            string returnType         = "System.Int32";
            string returnTypeKind     = "TypeKind.Struct";
            bool   returnTypeIsExtern = false;

            var sb = new StringBuilder();

            sb.AppendFormat("needfuncinfo({0}), rettype(return, {1}, {2}, 0, true)", NeedFuncInfo ? "true" : "false", returnType, returnTypeKind);
            if (ctrlFlow.ReturnStatements.Length > 0 && !string.IsNullOrEmpty(ReturnVarName))
            {
                returnType = ClassInfo.GetFullName(SemanticInfo.ReturnType);
                if (string.IsNullOrEmpty(returnType))
                {
                    returnType = "null";
                }
                returnTypeKind     = "TypeKind." + SemanticInfo.ReturnType.TypeKind.ToString();
                returnTypeIsExtern = !SymbolTable.Instance.IsCs2DslSymbol(SemanticInfo.ReturnType);
                sb.Append(", ");
                sb.AppendFormat("rettype({0}, {1}, {2}, 1, {3})", ReturnVarName, returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false");
            }
            foreach (var v in dataFlow.DataFlowsOut)
            {
                sb.Append(", ");
                int refOrOut = 2;
                if (inputs.Contains(v.Name))
                {
                    refOrOut = 1;
                }
                var psym = v as IParameterSymbol;
                var lsym = v as ILocalSymbol;
                if (null != psym)
                {
                    var  type     = ClassInfo.GetFullName(psym.Type);
                    var  typeKind = psym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
                else if (null != lsym)
                {
                    var  type     = ClassInfo.GetFullName(lsym.Type);
                    var  typeKind = lsym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
            }
            if (ctrlFlow.ReturnStatements.Length > 0 && !string.IsNullOrEmpty(ReturnVarName))
            {
                sb.Append(", ");
                sb.AppendFormat("paramtype({0}, {1}, {2}, 1, {3})", ReturnVarName, returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false");
            }
            foreach (var v in dataFlow.DataFlowsIn)
            {
                if (v.Name == "this")
                {
                    continue;
                }
                sb.Append(", ");
                int refOrOut = 0;
                if (outputs.Contains(v.Name))
                {
                    refOrOut = 1;
                }
                var psym = v as IParameterSymbol;
                var lsym = v as ILocalSymbol;
                if (null != psym)
                {
                    var  type     = ClassInfo.GetFullName(psym.Type);
                    var  typeKind = psym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
                else if (null != lsym)
                {
                    var  type     = ClassInfo.GetFullName(lsym.Type);
                    var  typeKind = lsym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
            }
            foreach (var v in dataFlow.DataFlowsOut)
            {
                sb.Append(", ");
                int refOrOut = 2;
                if (inputs.Contains(v.Name))
                {
                    refOrOut = 1;
                }
                var psym = v as IParameterSymbol;
                var lsym = v as ILocalSymbol;
                if (null != psym)
                {
                    var  type     = ClassInfo.GetFullName(psym.Type);
                    var  typeKind = psym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
                else if (null != lsym)
                {
                    var  type     = ClassInfo.GetFullName(lsym.Type);
                    var  typeKind = lsym.Type.TypeKind.ToString();
                    bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type);
                    if (string.IsNullOrEmpty(type))
                    {
                        type = "null";
                    }
                    sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false");
                }
            }
            return(sb.ToString());
        }
Пример #18
0
        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.RegisterSyntaxNodeAction(c => ExamineNode(c), _targetNodeTypes);

            void ExamineNode(SyntaxNodeAnalysisContext nodeContext)
            {
                if (TryGetSymbols(nodeContext.Node, nodeContext.SemanticModel, out IMethodSymbol methodSymbol, out IParameterSymbol parameterSymbol))
                {
                    if (HasNoCaptureAttribute(methodSymbol) || HasNoCaptureAttribute(parameterSymbol))
                    {
                        IEnumerable <ISymbol> capturedSymbols = GetCapturedSymbols();
                        if (capturedSymbols.Any())
                        {
                            Diagnostic diagnostic
                                = Diagnostic.Create
                                  (
                                      _descriptor,
                                      nodeContext.Node.GetLocation(),
                                      methodSymbol.Name,
                                      parameterSymbol.Name,
                                      String.Join(", ", capturedSymbols.Select(s => s.Name))
                                  );

                            nodeContext.ReportDiagnostic(diagnostic);
                        }
                    }

                    bool HasNoCaptureAttribute(ISymbol symbol)
                    => symbol.GetAttributes().Any(a => a.AttributeClass.Name == _noCaptureAttributeName);

                    IEnumerable <ISymbol> GetCapturedSymbols()
                    {
                        DataFlowAnalysis         dataFlow        = nodeContext.SemanticModel.AnalyzeDataFlow(nodeContext.Node);
                        ImmutableArray <ISymbol> capturedSymbols = dataFlow.Captured.IntersectWith(dataFlow.ReadInside);

                        if (capturedSymbols.IsEmpty)
                        {
                            return(Enumerable.Empty <ISymbol>());
                        }

                        IEnumerable <ISymbol> childDeclared = nodeContext
                                                              .Node
                                                              .DescendantNodesAndSelf(descendIntoChildren: _ => true, descendIntoTrivia: false)
                                                              .Where(child => _targetNodeTypes.Contains(child.Kind()))
                                                              .Select(child => nodeContext.SemanticModel.AnalyzeDataFlow(child))
                                                              .Where(dataFlow => dataFlow.Succeeded)
                                                              .Select(dataFlow => dataFlow.VariablesDeclared)
                                                              .Where(declared => declared.Length > 0)
                                                              .SelectMany(x => x)
                        ;

                        return(capturedSymbols
                               .Except(childDeclared)
                               );
                    }
                }
            }

            bool TryGetSymbols(SyntaxNode node, SemanticModel semanticModel, out IMethodSymbol method, out IParameterSymbol parameter)
            {
                if
                (
                    node.Parent is ArgumentSyntax argument &&
                    argument.Parent is ArgumentListSyntax argumentList &&
                    argumentList.Parent is InvocationExpressionSyntax invocation &&
                    semanticModel.GetSingleSymbol(invocation.Expression) is IMethodSymbol methodSymbol
                )
                {
                    method = methodSymbol;
                    parameter
                        = argument.NameColon is NameColonSyntax nameColon
                                                ? GetParameterByName()
                                                : GetParameterByOrder();

                    return(true);

                    IParameterSymbol GetParameterByName() => methodSymbol.Parameters.First(p => p.Name == nameColon.Name.Identifier.Text);

                    IParameterSymbol GetParameterByOrder()
                    {
                        int argumentIndex = argumentList.Arguments.IndexOf(argument);

                        /// params[] method invocations might have more arguments than parameters.
                        /// If they do, all extra arguments are actually passed to the last parameter.
                        int parameterIndex = argumentIndex < methodSymbol.Parameters.Length ? argumentIndex : methodSymbol.Parameters.Length - 1;

                        return(methodSymbol.Parameters[parameterIndex]);
                    }
                }
Пример #19
0
        private void VisitMethods(SyntaxNodeAnalysisContext ctx)
        {
            if (!(ctx.Node is CSharpSyntax.ClassDeclarationSyntax node))
            {
                return;
            }

            var classSymbol = CSharp.CSharpExtensions.GetDeclaredSymbol(ctx.SemanticModel, node);

            if (classSymbol == null ||
                !classSymbol.IsDerivedFrom(ControllerNames))
            {
                return;
            }

            var methodsWithParameters = node.DescendantNodesAndSelf()
                                        .OfType <CSharpSyntax.MethodDeclarationSyntax>()
                                        .Where(method => method.ParameterList.Parameters.Any())
                                        .Where(method => method.Modifiers
                                               .Any(x => x.IsKind(CSharp.SyntaxKind.PublicKeyword)))
                                        .Where(method => ctx.SemanticModel
                                               .GetSymbolInfo(method.ReturnType)
                                               .Symbol
                                               ?.IsType("System.String") == true);

            foreach (CSharpSyntax.MethodDeclarationSyntax method in methodsWithParameters)
            {
                SyntaxList <CSharpSyntax.StatementSyntax> methodStatements = method.Body.Statements;
                var methodInvocations = method.DescendantNodes()
                                        .OfType <CSharpSyntax.InvocationExpressionSyntax>()
                                        .ToArray();

                if (!methodStatements.Any())
                {
                    continue;
                }

                DataFlowAnalysis flow = ctx.SemanticModel.AnalyzeDataFlow(methodStatements.First(),
                                                                          methodStatements.Last());

                // Returns from the Data Flow Analysis of input data
                // Dangerous data is: Data passed as a parameter that is also returned as is by the method
                var inputVariables = flow.DataFlowsIn.Union(flow.VariablesDeclared.Except(flow.AlwaysAssigned))
                                     .Union(flow.WrittenInside)
                                     .Intersect(flow.WrittenOutside)
                                     .ToArray();

                if (!inputVariables.Any())
                {
                    continue;
                }

                foreach (ISymbol inputVariable in inputVariables)
                {
                    bool inputVariableIsEncoded = false;
                    foreach (CSharpSyntax.InvocationExpressionSyntax methodInvocation in methodInvocations)
                    {
                        var arguments = methodInvocation.ArgumentList.Arguments;
                        if (!arguments.Any())
                        {
                            continue;
                        }

                        if (arguments.First().ToString().Contains(inputVariable.Name))
                        {
                            inputVariableIsEncoded = true;
                        }
                    }

                    if (!inputVariableIsEncoded)
                    {
                        ctx.ReportDiagnostic(Diagnostic.Create(Rule, inputVariable.Locations[0]));
                        break;
                    }
                }
            }
        }
 private static bool IsParameterUsed([NotNull] IParameterSymbol parameter, [NotNull] DataFlowAnalysis dataFlowAnalysis)
 {
     return(dataFlowAnalysis.ReadInside.Contains(parameter) || dataFlowAnalysis.WrittenInside.Contains(parameter) ||
            dataFlowAnalysis.Captured.Contains(parameter));
 }
 /// <remarks>Unfortunately the roslyn UnassignedVariablesWalker and all useful collections created from it are internal only
 /// Other attempts using DataFlowsIn on each reference showed that "DataFlowsIn" even from an uninitialized variable (at least in the case of ints)
 /// https://github.com/dotnet/roslyn/blob/007022c37c6d21ee100728954bd75113e0dfe4bd/src/Compilers/VisualBasic/Portable/Analysis/FlowAnalysis/UnassignedVariablesWalker.vb#L15
 /// It'd be possible to see the result of the diagnostic analysis, but that would miss out value types, which don't cause a warning in VB
 /// PERF: Assume we'll only be passed one type of data flow analysis (VisualBasicDataFlowAnalysis)
 /// </remarks>
 public static IEnumerable <ISymbol> GetVbUnassignedVariables(this DataFlowAnalysis methodFlow) =>
 GetCachedReflectedPropertyDelegate(methodFlow, "UnassignedVariables", ref _vbUnassignedVariables).Cast <ISymbol>();
Пример #22
0
            private void GenerateVariableInfoMap(
                bool bestEffort,
                SemanticModel model,
                DataFlowAnalysis dataFlowAnalysisData,
                Dictionary <ISymbol, List <SyntaxToken> > symbolMap,
                out IDictionary <ISymbol, VariableInfo> variableInfoMap,
                out List <ISymbol> failedVariables)
            {
                Contract.ThrowIfNull(model);
                Contract.ThrowIfNull(dataFlowAnalysisData);

                variableInfoMap = new Dictionary <ISymbol, VariableInfo>();
                failedVariables = new List <ISymbol>();

                // create map of each data
                var capturedMap           = new HashSet <ISymbol>(dataFlowAnalysisData.Captured);
                var dataFlowInMap         = new HashSet <ISymbol>(dataFlowAnalysisData.DataFlowsIn);
                var dataFlowOutMap        = new HashSet <ISymbol>(dataFlowAnalysisData.DataFlowsOut);
                var alwaysAssignedMap     = new HashSet <ISymbol>(dataFlowAnalysisData.AlwaysAssigned);
                var variableDeclaredMap   = new HashSet <ISymbol>(dataFlowAnalysisData.VariablesDeclared);
                var readInsideMap         = new HashSet <ISymbol>(dataFlowAnalysisData.ReadInside);
                var writtenInsideMap      = new HashSet <ISymbol>(dataFlowAnalysisData.WrittenInside);
                var readOutsideMap        = new HashSet <ISymbol>(dataFlowAnalysisData.ReadOutside);
                var writtenOutsideMap     = new HashSet <ISymbol>(dataFlowAnalysisData.WrittenOutside);
                var unsafeAddressTakenMap = new HashSet <ISymbol>(dataFlowAnalysisData.UnsafeAddressTaken);

                // gather all meaningful symbols for the span.
                var candidates = new HashSet <ISymbol>(readInsideMap);

                candidates.UnionWith(writtenInsideMap);
                candidates.UnionWith(variableDeclaredMap);

                foreach (var symbol in candidates)
                {
                    if (symbol.IsThisParameter() ||
                        IsInteractiveSynthesizedParameter(symbol))
                    {
                        continue;
                    }

                    var captured           = capturedMap.Contains(symbol);
                    var dataFlowIn         = dataFlowInMap.Contains(symbol);
                    var dataFlowOut        = dataFlowOutMap.Contains(symbol);
                    var alwaysAssigned     = alwaysAssignedMap.Contains(symbol);
                    var variableDeclared   = variableDeclaredMap.Contains(symbol);
                    var readInside         = readInsideMap.Contains(symbol);
                    var writtenInside      = writtenInsideMap.Contains(symbol);
                    var readOutside        = readOutsideMap.Contains(symbol);
                    var writtenOutside     = writtenOutsideMap.Contains(symbol);
                    var unsafeAddressTaken = unsafeAddressTakenMap.Contains(symbol);

                    // if it is static local, make sure it is not defined inside
                    if (symbol.IsStatic)
                    {
                        dataFlowIn = dataFlowIn && !variableDeclared;
                    }

                    // make sure readoutside is true when dataflowout is true (bug #3790)
                    // when a variable is only used inside of loop, a situation where dataflowout == true and readOutside == false
                    // can happen. but for extract method's point of view, this is not an information that would affect output.
                    // so, here we adjust flags to follow predefined assumption.
                    readOutside = readOutside || dataFlowOut;

                    // make sure data flow out is true when declared inside/written inside/read outside/not written outside are true (bug #6277)
                    dataFlowOut = dataFlowOut || (variableDeclared && writtenInside && readOutside && !writtenOutside);

                    // variable that is declared inside but never referenced outside. just ignore it and move to next one.
                    if (variableDeclared && !dataFlowOut && !readOutside && !writtenOutside)
                    {
                        continue;
                    }

                    // parameter defined inside of the selection (such as lambda parameter) will be ignored (bug # 10964)
                    if (symbol is IParameterSymbol && variableDeclared)
                    {
                        continue;
                    }

                    var type = GetSymbolType(model, symbol);
                    if (type == null)
                    {
                        continue;
                    }

                    // If the variable doesn't have a name, it is invalid.
                    if (symbol.Name.IsEmpty())
                    {
                        continue;
                    }

                    if (!TryGetVariableStyle(
                            bestEffort, symbolMap, symbol, model, type,
                            captured, dataFlowIn, dataFlowOut, alwaysAssigned, variableDeclared,
                            readInside, writtenInside, readOutside, writtenOutside, unsafeAddressTaken,
                            out var variableStyle))
                    {
                        Contract.ThrowIfTrue(bestEffort, "Should never fail if bestEffort is true");
                        failedVariables.Add(symbol);
                        continue;
                    }

                    AddVariableToMap(variableInfoMap, symbol, CreateFromSymbol(model.Compilation, symbol, type, variableStyle, variableDeclared));
                }
            }
Пример #23
0
        private static void AnalyzeSetProcessDelegateMethod(SyntaxNodeAnalysisContext syntaxContext, PXContext pxContext)
        {
            var setDelegateInvocation = syntaxContext.Node as InvocationExpressionSyntax;

            if (!CheckIfDiagnosticIsValid(setDelegateInvocation, syntaxContext, pxContext))
            {
                return;
            }

            DataFlowAnalysis dfa = null;

            switch (setDelegateInvocation.ArgumentList.Arguments[0].Expression)
            {
            case IdentifierNameSyntax ins:
                ISymbol identifierSymbol = syntaxContext.SemanticModel.GetSymbolInfo(ins, syntaxContext.CancellationToken).Symbol;

                if (identifierSymbol != null && !identifierSymbol.IsStatic)
                {
                    syntaxContext.ReportDiagnosticWithSuppressionCheck(
                        Diagnostic.Create(
                            Descriptors.PX1008_LongOperationDelegateClosures, setDelegateInvocation.GetLocation()),
                        pxContext.CodeAnalysisSettings);
                }

                return;

            case MemberAccessExpressionSyntax memberAccess
                when memberAccess.Expression is ElementAccessExpressionSyntax arrayIndexAccess:
                AnalyzeMemberAccessExpressions(arrayIndexAccess.Expression, syntaxContext, pxContext);
                return;

            case MemberAccessExpressionSyntax memberAccess:
                AnalyzeMemberAccessExpressions(memberAccess.Expression, syntaxContext, pxContext);
                return;

            case ConditionalAccessExpressionSyntax conditionalAccess
                when conditionalAccess.Expression is ElementAccessExpressionSyntax arrayIndexAccess:
                AnalyzeMemberAccessExpressions(arrayIndexAccess.Expression, syntaxContext, pxContext);
                return;

            case ConditionalAccessExpressionSyntax conditionalAccess:
                AnalyzeMemberAccessExpressions(conditionalAccess.Expression, syntaxContext, pxContext);
                return;

            case AnonymousMethodExpressionSyntax anonMethodNode:
                dfa = syntaxContext.SemanticModel.AnalyzeDataFlow(anonMethodNode);
                break;

            case LambdaExpressionSyntax lambdaNode:
                dfa = syntaxContext.SemanticModel.AnalyzeDataFlow(lambdaNode);
                break;
            }

            if (dfa != null && dfa.DataFlowsIn.OfType <IParameterSymbol>().Any(p => p.IsThis))
            {
                syntaxContext.ReportDiagnosticWithSuppressionCheck(
                    Diagnostic.Create(
                        Descriptors.PX1008_LongOperationDelegateClosures, setDelegateInvocation.GetLocation()),
                    pxContext.CodeAnalysisSettings);
            }
        }
Пример #24
0
        private void AnalyzeNode(SyntaxNodeAnalysisContext context)
        {
            var localDeclaration = (LocalDeclarationStatementSyntax)context.Node;

            // make sure the declaration isn't already const:
            if (localDeclaration.Modifiers.Any(SyntaxKind.ConstKeyword))
            {
                return;
            }

            TypeSyntax  variableTypeName = localDeclaration.Declaration.Type;
            ITypeSymbol variableType     = context.SemanticModel.GetTypeInfo(variableTypeName, context.CancellationToken).ConvertedType;

            // Ensure that all variables in the local declaration have initializers that
            // are assigned with constant values.
            foreach (VariableDeclaratorSyntax variable in localDeclaration.Declaration.Variables)
            {
                EqualsValueClauseSyntax initializer = variable.Initializer;
                if (initializer == null)
                {
                    return;
                }

                Optional <object> constantValue = context.SemanticModel.GetConstantValue(initializer.Value, context.CancellationToken);
                if (!constantValue.HasValue)
                {
                    return;
                }

                // Ensure that the initializer value can be converted to the type of the
                // local declaration without a user-defined conversion.
                Conversion conversion = context.SemanticModel.ClassifyConversion(initializer.Value, variableType);
                if (!conversion.Exists || conversion.IsUserDefined)
                {
                    return;
                }

                // Special cases:
                //  * If the constant value is a string, the type of the local declaration
                //    must be System.String.
                //  * If the constant value is null, the type of the local declaration must
                //    be a reference type.
                if (constantValue.Value is string)
                {
                    if (variableType.SpecialType != SpecialType.System_String)
                    {
                        return;
                    }
                }
                else if (variableType.IsReferenceType && constantValue.Value != null)
                {
                    return;
                }
            }

            // Perform data flow analysis on the local declaration.
            DataFlowAnalysis dataFlowAnalysis = context.SemanticModel.AnalyzeDataFlow(localDeclaration);

            foreach (VariableDeclaratorSyntax variable in localDeclaration.Declaration.Variables)
            {
                // Retrieve the local symbol for each variable in the local declaration
                // and ensure that it is not written outside of the data flow analysis region.
                ISymbol variableSymbol = context.SemanticModel.GetDeclaredSymbol(variable, context.CancellationToken);
                if (dataFlowAnalysis.WrittenOutside.Contains(variableSymbol))
                {
                    return;
                }
            }

            context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.GetLocation()));
        }
        private static void Analyze(
            SyntaxNodeAnalysisContext context,
            SyntaxNode declaration,
            ParameterListSyntax parameterList,
            CSharpSyntaxNode bodyOrExpressionBody)
        {
            if (parameterList == null)
            {
                return;
            }

            if (bodyOrExpressionBody == null)
            {
                return;
            }

            if (!parameterList.Parameters.Any())
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(declaration, cancellationToken);

            SyntaxWalker walker = null;

            foreach (IParameterSymbol parameter in methodSymbol.Parameters)
            {
                cancellationToken.ThrowIfCancellationRequested();

                ITypeSymbol type = parameter.Type;

                if (type.Kind == SymbolKind.ErrorType)
                {
                    continue;
                }

                if (CSharpFacts.IsSimpleType(type.SpecialType))
                {
                    continue;
                }

                if (!type.IsReadOnlyStruct())
                {
                    if (parameter.RefKind == RefKind.In &&
                        type.TypeKind == TypeKind.Struct)
                    {
                        var parameterSyntax = (ParameterSyntax)parameter.GetSyntax(cancellationToken);

                        Debug.Assert(parameterSyntax.Modifiers.Contains(SyntaxKind.InKeyword), "");

                        DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.DoNotPassNonReadOnlyStructByReadOnlyReference, parameterSyntax.Identifier);
                    }

                    continue;
                }

                if (parameter.RefKind != RefKind.None)
                {
                    continue;
                }

                if (walker == null)
                {
                    if (methodSymbol.ImplementsInterfaceMember(allInterfaces: true))
                    {
                        break;
                    }

                    walker = SyntaxWalker.GetInstance();
                }
                else if (walker.Parameters.ContainsKey(parameter.Name))
                {
                    walker.Parameters.Clear();
                    break;
                }

                walker.Parameters.Add(parameter.Name, parameter);
            }

            if (walker == null)
            {
                return;
            }

            if (walker.Parameters.Count > 0)
            {
                walker.SemanticModel     = semanticModel;
                walker.CancellationToken = cancellationToken;

                if (bodyOrExpressionBody.IsKind(SyntaxKind.Block))
                {
                    walker.VisitBlock((BlockSyntax)bodyOrExpressionBody);
                }
                else
                {
                    walker.VisitArrowExpressionClause((ArrowExpressionClauseSyntax)bodyOrExpressionBody);
                }

                if (walker.Parameters.Count > 0)
                {
                    DataFlowAnalysis analysis = (bodyOrExpressionBody.IsKind(SyntaxKind.Block))
                        ? semanticModel.AnalyzeDataFlow((BlockSyntax)bodyOrExpressionBody)
                        : semanticModel.AnalyzeDataFlow(((ArrowExpressionClauseSyntax)bodyOrExpressionBody).Expression);

                    bool?isReferencedAsMethodGroup = null;

                    foreach (KeyValuePair <string, IParameterSymbol> kvp in walker.Parameters)
                    {
                        var isAssigned = false;

                        foreach (ISymbol assignedSymbol in analysis.AlwaysAssigned)
                        {
                            if (SymbolEqualityComparer.Default.Equals(assignedSymbol, kvp.Value))
                            {
                                isAssigned = true;
                                break;
                            }
                        }

                        if (isAssigned)
                        {
                            continue;
                        }

                        if (isReferencedAsMethodGroup ??= IsReferencedAsMethodGroup())
                        {
                            break;
                        }

                        if (kvp.Value.GetSyntaxOrDefault(cancellationToken) is ParameterSyntax parameter)
                        {
                            DiagnosticHelpers.ReportDiagnostic(
                                context,
                                DiagnosticDescriptors.MakeParameterRefReadOnly,
                                parameter.Identifier);
                        }
                    }
                }
            }

            SyntaxWalker.Free(walker);

            bool IsReferencedAsMethodGroup()
            {
                switch (declaration.Kind())
                {
                case SyntaxKind.MethodDeclaration:
                    return(MethodReferencedAsMethodGroupWalker.IsReferencedAsMethodGroup(declaration.Parent, methodSymbol, semanticModel, cancellationToken));

                case SyntaxKind.LocalFunctionStatement:
                    return(MethodReferencedAsMethodGroupWalker.IsReferencedAsMethodGroup(declaration.FirstAncestor <MemberDeclarationSyntax>(), methodSymbol, semanticModel, cancellationToken));

                default:
                    return(false);
                }
            }
        }
Пример #26
0
 public void Setup()
 {
     this.CSignature = null;
     this.dfa        = null;
     base.platform   = null;
 }
Пример #27
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Diagnostic diagnostic = context.Diagnostics[0];

            if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AssignDefaultValueToOutParameter))
            {
                return;
            }

            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindFirstAncestorOrSelf(
                    root,
                    context.Span,
                    out SyntaxNode node,
                    predicate: f => f.IsKind(SyntaxKind.MethodDeclaration) || f is StatementSyntax))
            {
                return;
            }

            StatementSyntax statement = null;

            if (!node.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement))
            {
                statement = (StatementSyntax)node;

                node = node.FirstAncestor(f => f.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement));

                Debug.Assert(node != null, "Containing method or local function not found.");

                if (node == null)
                {
                    return;
                }
            }

            SyntaxNode bodyOrExpressionBody = GetBodyOrExpressionBody(node);

            if (bodyOrExpressionBody == null)
            {
                return;
            }

            if (bodyOrExpressionBody is BlockSyntax body &&
                body.ContainsYield())
            {
                return;
            }

            SemanticModel semanticModel = await context.Document.GetSemanticModelAsync().ConfigureAwait(false);

            DataFlowAnalysis dataFlowAnalysis = AnalyzeDataFlow(bodyOrExpressionBody, semanticModel);

            // Flow analysis APIs do not work with local functions: https://github.com/dotnet/roslyn/issues/14214
            if (!dataFlowAnalysis.Succeeded)
            {
                return;
            }

            var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(node);

            ImmutableArray <IParameterSymbol> parameters = methodSymbol.Parameters;

            ImmutableArray <ISymbol> alwaysAssigned = dataFlowAnalysis.AlwaysAssigned;

            IParameterSymbol singleParameter = null;
            var isAny = false;

            foreach (IParameterSymbol parameter in parameters)
            {
                if (parameter.RefKind == RefKind.Out &&
                    !alwaysAssigned.Contains(parameter))
                {
                    if (singleParameter == null)
                    {
                        singleParameter = parameter;
                        isAny           = true;
                    }
                    else
                    {
                        singleParameter = null;
                        break;
                    }
                }
            }

            Debug.Assert(isAny, "No unassigned 'out' parameter found.");

            if (!isAny)
            {
                return;
            }

            CodeAction codeAction = CodeAction.Create(
                (singleParameter != null)
                    ? $"Assign default value to parameter '{singleParameter.Name}'"
                    : "Assign default value to parameters",
                cancellationToken => RefactorAsync(context.Document, node, statement, bodyOrExpressionBody, parameters, alwaysAssigned, semanticModel, cancellationToken),
                base.GetEquivalenceKey(diagnostic));

            context.RegisterCodeFix(codeAction, diagnostic);
        }
Пример #28
0
        public void Dfa2_StackArgs_Nested()
        {
            pb = new ProgramBuilder();
            pb.Add("main", m =>
            {
                var r1 = m.Register("r1");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(sp, m.ISub(sp, 4));
                m.MStore(sp, m.Mem32(m.Ptr32(0x123400)));
                m.Call("level1", 4);
                m.Assign(sp, m.IAdd(sp, 4));
                m.MStore(m.Ptr32(0x123404), r1);
                m.Return();
            });
            pb.Add("level1", m =>
            {
                var r1 = m.Register("r1");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.IAdd(sp, 4)));
                m.Assign(sp, m.ISub(sp, 4));
                m.MStore(sp, r1);
                m.Call("level2", 4);
                m.Assign(sp, m.IAdd(sp, 4));
                m.Return();
            });
            pb.Add("level2", m =>
            {
                var r1 = m.Register("r1");
                var r2 = m.Register("r2");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.IAdd(sp, 4)));
                m.Assign(r1, m.IAdd(r1, 1));
                m.Return();
            });
            var program = pb.BuildProgram();

            var dfa = new DataFlowAnalysis(program, dynamicLinker.Object, sc);

            dfa.AnalyzeProgram();

            var sExp =
                #region Expected
                @"// main
// Return size: 0
void main()
main_entry:
	// succ:  l1
l1:
	Mem8[0x00123404<p32>:word32] = level1(Mem0[0x00123400<p32>:word32])
	return
	// succ:  main_exit
main_exit:
===
// level1
// Return size: 0
word32 level1(word32 dwArg04)
level1_entry:
	// succ:  l1
l1:
	return level2(dwArg04)
	// succ:  level1_exit
level1_exit:
===
// level2
// Return size: 0
word32 level2(word32 dwArg04)
level2_entry:
	// succ:  l1
l1:
	return dwArg04 + 1<32>
	// succ:  level2_exit
level2_exit:
";

            #endregion
            AssertProgram(sExp, pb.Program);
        }
Пример #29
0
 private void GetLocalAndType(DataFlowAnalysis df, List<ISymbol> list)
 {
     foreach (var v in df.VariablesDeclared)
     {
         list.Add((Symbol)v);
         var local = v as LocalSymbol;
         if (local != null && (local.Type.Kind == SymbolKind.ArrayType || local.Type.Kind == SymbolKind.PointerType))
         {
             list.Add(local.Type);
         }
     }
 }
Пример #30
0
        private void ProcessEmitVertex(InvocationExpressionSyntax node)
        {
            var model = GetModel(node);
            DataFlowAnalysis analysis = null;

            if (_lastVertexEmit is ExpressionSyntax expression)
            {
                analysis = model.AnalyzeDataFlow(expression);
            }
            else if (_lastVertexEmit is StatementSyntax lastStatement)
            {
                var emitStatement = node.Ancestors().OfType <StatementSyntax>().FirstOrDefault();
                if (lastStatement.Parent != emitStatement.Parent)
                {
                    lastStatement = emitStatement.Parent.ChildNodes().Cast <StatementSyntax>().First();
                }
                analysis        = model.AnalyzeDataFlow(lastStatement, emitStatement);
                _lastVertexEmit = emitStatement;
            }

            var emit = model.GetSymbolInfo(node.ArgumentList.Arguments.Last().Expression);

            if (!(emit.Symbol is IFieldSymbol emitParam))
            {
                throw new ShaderGenerationException("EmitVertex argument must be a field");
            }
            var emitAttribute = emit.Symbol.GetAttributes().FirstOrDefault(a => a.AttributeClass.Name.Contains("EmitVertex"));

            if (emitAttribute == null)
            {
                throw new ShaderGenerationException("EmitVertex arguments must be marked with EmitVertexAttribute");
            }

            int streamId = 0;

            if (node.ArgumentList.Arguments.Count > 1)
            {
                streamId = (int)model.GetConstantValue(node.ArgumentList.Arguments.First()).Value;
            }

            var assignments = analysis.AlwaysAssigned.Concat(_writeFields);

            if (!_emittedData.TryGetValue(streamId, out var emissions))
            {
                emissions = new HashSet <ISymbol>(assignments.OfType <IFieldSymbol>(), SymbolEqualityComparer.Default);
                _emittedData.Add(streamId, emissions);
                if (assignments.Contains(emitParam))
                {
                    emissions.Add(emitParam);
                }
            }

            if (analysis != null)
            {
                foreach (var emission in emissions)
                {
                    if (!assignments.Contains(emission) && !assignments.Contains(emission.ContainingType))
                    {
                        var type = (emission as IFieldSymbol)?.Type ?? (emission as IParameterSymbol)?.Type;
                        if (type == null || !type.GetMembers().OfType <IFieldSymbol>().All(assignments.Contains))
                        {
                            throw new ShaderGenerationException($"{emission.Name} must be fully assigned before every call to EmitVertex");
                        }
                    }
                }
                foreach (var assignment in assignments.OfType <IFieldSymbol>().Append <ISymbol>(emitParam).Where(a => !emissions.Contains(a)))
                {
                    var type = (assignment as IFieldSymbol)?.Type ?? (assignment as IParameterSymbol)?.Type;
                    if (type == null || !type.GetMembers().OfType <IFieldSymbol>().All(emissions.Contains))
                    {
                        throw new ShaderGenerationException($"{assignment.Name} must be fully assigned before every call to EmitVertex");
                    }
                }
            }
            _writeFields.Clear();
        }
        protected void VisitMethods(SyntaxNodeAnalysisContext ctx)
        {
            if (!(ctx.Node is VBSyntax.ClassBlockSyntax node))
            {
                return;
            }

            var classSymbol = VB.VisualBasicExtensions.GetDeclaredSymbol(ctx.SemanticModel, node);

            if (classSymbol == null ||
                !classSymbol.IsDerivedFrom("Microsoft.AspNetCore.Mvc.Controller", "System.Web.Mvc.Controller"))
            {
                return;
            }

            var methodsWithParameters = node.DescendantNodesAndSelf()
                                        .OfType <VBSyntax.MethodBlockSyntax>()
                                        .Where(method =>
                                               method.SubOrFunctionStatement.ParameterList.Parameters.Any())
                                        .Where(method => method
                                               .SubOrFunctionStatement
                                               .Modifiers.Any(x => x.IsKind(VB.SyntaxKind.PublicKeyword)))
                                        .Where(method =>
            {
                var retType = method.SubOrFunctionStatement.AsClause?.Type;
                if (retType == null)
                {
                    return(false);
                }

                return(ctx.SemanticModel
                       .GetSymbolInfo(retType)
                       .Symbol
                       ?.IsType("System.String") == true);
            });

            foreach (VBSyntax.MethodBlockSyntax method in methodsWithParameters)
            {
                SyntaxList <VBSyntax.StatementSyntax> methodStatements = method.Statements;
                var methodInvocations = method.DescendantNodes()
                                        .OfType <VBSyntax.InvocationExpressionSyntax>()
                                        .ToArray();

                if (!methodStatements.Any())
                {
                    continue;
                }

                DataFlowAnalysis flow = ctx.SemanticModel.AnalyzeDataFlow(methodStatements.First(),
                                                                          methodStatements.Last());

                // Returns from the Data Flow Analysis of sensible data
                // Sensible data is: Data passed as a parameter that is also returned as is by the method
                var sensibleVariables = flow.DataFlowsIn.Union(flow.VariablesDeclared.Except(flow.AlwaysAssigned))
                                        .Union(flow.WrittenInside)
                                        .Intersect(flow.WrittenOutside)
                                        .ToArray();

                if (!sensibleVariables.Any())
                {
                    continue;
                }

                foreach (ISymbol sensibleVariable in sensibleVariables)
                {
                    bool sensibleVariableIsEncoded = false;
                    foreach (VBSyntax.InvocationExpressionSyntax methodInvocation in methodInvocations)
                    {
                        var arguments = methodInvocation.ArgumentList.Arguments;
                        if (!arguments.Any())
                        {
                            continue;
                        }

                        if (arguments.First().ToString().Contains(sensibleVariable.Name))
                        {
                            sensibleVariableIsEncoded = true;
                        }
                    }

                    if (!sensibleVariableIsEncoded)
                    {
                        ctx.ReportDiagnostic(Diagnostic.Create(Rule, method.GetLocation()));
                    }
                }
            }
        }