Beispiel #1
0
        /// <summary>
        /// Computes the 'gives_up' set for the given argument.
        /// </summary>
        /// <param name="arg">Argument</param>
        /// <param name="cfgNode">ControlFlowGraphNode</param>
        /// <param name="summary">MethodSummary</param>
        private static void ComputeGivesUpSetForArgument(ExpressionSyntax arg, ControlFlowGraphNode cfgNode,
                                                         MethodSummary summary)
        {
            var model = AnalysisContext.Compilation.GetSemanticModel(arg.SyntaxTree);

            if (arg is IdentifierNameSyntax || arg is MemberAccessExpressionSyntax)
            {
                for (int idx = 0; idx < summary.Method.ParameterList.Parameters.Count; idx++)
                {
                    if (Utilities.IsTypeAllowedToBeSend(summary.Method.ParameterList.Parameters[idx].Type, model))
                    {
                        continue;
                    }

                    var paramSymbol = model.GetDeclaredSymbol(summary.Method.ParameterList.Parameters[idx]);
                    if (DataFlowAnalysis.FlowsFromTarget(arg, paramSymbol, summary.Node.SyntaxNodes.First(),
                                                         summary.Node, cfgNode.SyntaxNodes.First(), cfgNode, model))
                    {
                        summary.GivesUpSet.Add(idx);
                    }
                }
            }
            else if (arg is ObjectCreationExpressionSyntax)
            {
                var payload = arg as ObjectCreationExpressionSyntax;
                foreach (var item in payload.ArgumentList.Arguments)
                {
                    MethodSummaryAnalysis.ComputeGivesUpSetForArgument(item.Expression,
                                                                       cfgNode, summary);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Computes the summary for the given method.
        /// </summary>
        /// <param name="method">Method</param>
        /// <param name="machine">Machine</param>
        /// <param name="state">State</param>
        private static void ComputeSummaryForMethod(MethodDeclarationSyntax method,
                                                    ClassDeclarationSyntax machine, ClassDeclarationSyntax state)
        {
            List <InvocationExpressionSyntax> givesUpSources = new List <InvocationExpressionSyntax>();

            foreach (var call in method.DescendantNodes().OfType <InvocationExpressionSyntax>())
            {
                var model = AnalysisContext.Compilation.GetSemanticModel(call.SyntaxTree);

                var callSymbol = model.GetSymbolInfo(call).Symbol;
                if (callSymbol == null)
                {
                    continue;
                }

                var definition = SymbolFinder.FindSourceDefinitionAsync(callSymbol, ProgramInfo.Solution).Result;
                if (definition == null)
                {
                    continue;
                }

                var callee       = Utilities.GetCallee(call);
                var calleeMethod = definition.DeclaringSyntaxReferences.First().GetSyntax()
                                   as BaseMethodDeclarationSyntax;

                if (Utilities.IsSourceOfGivingUpOwnership(call, model, callee) ||
                    AnalysisContext.Summaries.ContainsKey(calleeMethod))
                {
                    givesUpSources.Add(call);
                }
                else if (machine.ChildNodes().OfType <BaseMethodDeclarationSyntax>().Contains(calleeMethod) &&
                         !AnalysisContext.Summaries.ContainsKey(calleeMethod) &&
                         !calleeMethod.Modifiers.Any(SyntaxKind.AbstractKeyword))
                {
                    return;
                }
            }

            MethodSummary summary = MethodSummary.Factory.Summarize(method, machine, state);

            foreach (var givesUpNode in summary.GivesUpNodes)
            {
                MethodSummaryAnalysis.TryComputeGivesUpSetForSendControlFlowGraphNode(
                    givesUpNode, summary);
                MethodSummaryAnalysis.TryComputeGivesUpSetForCreateControlFlowGraphNode(
                    givesUpNode, summary);
                MethodSummaryAnalysis.TryComputeGivesUpSetForGenericControlFlowGraphNode(
                    givesUpNode, summary);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Analyses all the eligible methods of the given machine to compute each
        /// method summary. This process continues until it reaches a fix point.
        /// </summary>
        /// <param name="machine">Machine</param>
        private static void AnalyseMethodsInMachine(ClassDeclarationSyntax machine)
        {
            int fixPoint = 0;

            foreach (var nestedClass in machine.ChildNodes().OfType <ClassDeclarationSyntax>())
            {
                foreach (var method in nestedClass.ChildNodes().OfType <MethodDeclarationSyntax>())
                {
                    if (!Utilities.ShouldAnalyseMethod(method) ||
                        AnalysisContext.Summaries.ContainsKey(method))
                    {
                        continue;
                    }

                    MethodSummaryAnalysis.ComputeSummaryForMethod(method, machine, nestedClass);
                    if (!AnalysisContext.Summaries.ContainsKey(method))
                    {
                        fixPoint++;
                    }
                }
            }

            foreach (var method in machine.ChildNodes().OfType <MethodDeclarationSyntax>())
            {
                if (!Utilities.ShouldAnalyseMethod(method) ||
                    AnalysisContext.Summaries.ContainsKey(method))
                {
                    continue;
                }

                MethodSummaryAnalysis.ComputeSummaryForMethod(method, machine, null);
                if (!AnalysisContext.Summaries.ContainsKey(method))
                {
                    fixPoint++;
                }
            }

            if (fixPoint > 0)
            {
                MethodSummaryAnalysis.AnalyseMethodsInMachine(machine);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Runs the analysis.
        /// </summary>
        public static void Run()
        {
            // Starts profiling the data flow analysis.
            if (Configuration.ShowDFARuntimeResults &&
                !Configuration.ShowRuntimeResults &&
                !Configuration.ShowROARuntimeResults)
            {
                Profiler.StartMeasuringExecutionTime();
            }

            foreach (var machine in AnalysisContext.Machines)
            {
                MethodSummaryAnalysis.AnalyseMethodsInMachine(machine);
            }

            // Stops profiling the data flow analysis.
            if (Configuration.ShowDFARuntimeResults &&
                !Configuration.ShowRuntimeResults &&
                !Configuration.ShowROARuntimeResults)
            {
                Profiler.StopMeasuringExecutionTime();
            }
        }
Beispiel #5
0
        /// <summary>
        /// Tries to compute the 'gives_up' set of indexes for the given control flow graph node.
        /// If the node does not contain a generic 'gives_up' operation, then it returns false.
        /// </summary>
        /// <param name="cfgNode">ControlFlowGraphNode</param>
        /// <param name="summary">MethodSummary</param>
        /// <returns>Boolean value</returns>
        private static bool TryComputeGivesUpSetForGenericControlFlowGraphNode(ControlFlowGraphNode cfgNode,
                                                                               MethodSummary summary)
        {
            var callLocalDecl = cfgNode.SyntaxNodes.First() as LocalDeclarationStatementSyntax;
            var callExpr      = cfgNode.SyntaxNodes.First() as ExpressionStatementSyntax;

            InvocationExpressionSyntax call = null;

            if (callLocalDecl != null)
            {
                call = callLocalDecl.DescendantNodesAndSelf().OfType <InvocationExpressionSyntax>().First();
            }
            else if (callExpr != null)
            {
                call = callExpr.DescendantNodesAndSelf().OfType <InvocationExpressionSyntax>().First();
            }
            else if (call == null || !((call.Expression is MemberAccessExpressionSyntax) ||
                                       (call.Expression is IdentifierNameSyntax)))
            {
                return(false);
            }

            var model = AnalysisContext.Compilation.GetSemanticModel(call.SyntaxTree);

            if (call.Expression is MemberAccessExpressionSyntax)
            {
                var callStmt = call.Expression as MemberAccessExpressionSyntax;
                if (callStmt.Name.Identifier.ValueText.Equals("Send") ||
                    callStmt.Name.Identifier.ValueText.Equals("CreateMachine"))
                {
                    return(false);
                }
            }
            else if (call.Expression is IdentifierNameSyntax)
            {
                var callStmt = call.Expression as IdentifierNameSyntax;
                if (callStmt.Identifier.ValueText.Equals("Send") ||
                    callStmt.Identifier.ValueText.Equals("CreateMachine"))
                {
                    return(false);
                }
            }

            if (call.ArgumentList.Arguments.Count == 0)
            {
                return(false);
            }

            var callSymbol   = model.GetSymbolInfo(call).Symbol;
            var definition   = SymbolFinder.FindSourceDefinitionAsync(callSymbol, ProgramInfo.Solution).Result;
            var calleeMethod = definition.DeclaringSyntaxReferences.First().GetSyntax()
                               as BaseMethodDeclarationSyntax;
            var calleeSummary = MethodSummary.Factory.Summarize(calleeMethod);

            foreach (int idx in calleeSummary.GivesUpSet)
            {
                if (call.ArgumentList.Arguments[idx].Expression is ObjectCreationExpressionSyntax)
                {
                    var objCreation = call.ArgumentList.Arguments[idx].Expression
                                      as ObjectCreationExpressionSyntax;
                    foreach (var arg in objCreation.ArgumentList.Arguments)
                    {
                        MethodSummaryAnalysis.ComputeGivesUpSetForArgument(
                            arg.Expression, cfgNode, summary);
                    }
                }
                else if (call.ArgumentList.Arguments[idx].Expression is BinaryExpressionSyntax &&
                         call.ArgumentList.Arguments[idx].Expression.IsKind(SyntaxKind.AsExpression))
                {
                    var binExpr = call.ArgumentList.Arguments[idx].Expression
                                  as BinaryExpressionSyntax;
                    if ((binExpr.Left is IdentifierNameSyntax) || (binExpr.Left is MemberAccessExpressionSyntax))
                    {
                        MethodSummaryAnalysis.ComputeGivesUpSetForArgument(binExpr.Left,
                                                                           cfgNode, summary);
                    }
                    else if (binExpr.Left is InvocationExpressionSyntax)
                    {
                        var invocation = binExpr.Left as InvocationExpressionSyntax;
                        for (int i = 1; i < invocation.ArgumentList.Arguments.Count; i++)
                        {
                            MethodSummaryAnalysis.ComputeGivesUpSetForArgument(invocation.ArgumentList.
                                                                               Arguments[i].Expression, cfgNode, summary);
                        }
                    }
                }
                else if ((call.ArgumentList.Arguments[idx].Expression is IdentifierNameSyntax) ||
                         (call.ArgumentList.Arguments[idx].Expression is MemberAccessExpressionSyntax))
                {
                    MethodSummaryAnalysis.ComputeGivesUpSetForArgument(call.ArgumentList.
                                                                       Arguments[idx].Expression, cfgNode, summary);
                }
            }

            return(true);
        }
Beispiel #6
0
        /// <summary>
        /// Tries to compute the 'gives_up' set of indexes for the given control flow graph node.
        /// If the node does not contain a 'Create' operation, then it returns false.
        /// </summary>
        /// <param name="cfgNode">ControlFlowGraphNode</param>
        /// <param name="summary">MethodSummary</param>
        /// <returns>Boolean value</returns>
        private static bool TryComputeGivesUpSetForCreateControlFlowGraphNode(ControlFlowGraphNode cfgNode,
                                                                              MethodSummary summary)
        {
            var createExpr = cfgNode.SyntaxNodes.First() as ExpressionStatementSyntax;

            if (createExpr == null)
            {
                return(false);
            }

            var create = createExpr.Expression as InvocationExpressionSyntax;

            if (create == null || !((create.Expression is MemberAccessExpressionSyntax) ||
                                    (create.Expression is IdentifierNameSyntax)))
            {
                return(false);
            }

            if (((create.Expression is MemberAccessExpressionSyntax) &&
                 !(create.Expression as MemberAccessExpressionSyntax).
                 Name.Identifier.ValueText.Equals("CreateMachine")) ||
                ((create.Expression is IdentifierNameSyntax) &&
                 !(create.Expression as IdentifierNameSyntax).
                 Identifier.ValueText.Equals("CreateMachine")))
            {
                return(false);
            }

            if (create.ArgumentList.Arguments.Count == 0)
            {
                return(true);
            }

            if (create.ArgumentList.Arguments[0].Expression is ObjectCreationExpressionSyntax)
            {
                var objCreation = create.ArgumentList.Arguments[0].Expression
                                  as ObjectCreationExpressionSyntax;
                foreach (var arg in objCreation.ArgumentList.Arguments)
                {
                    MethodSummaryAnalysis.ComputeGivesUpSetForArgument(arg.Expression,
                                                                       cfgNode, summary);
                }
            }
            else if (create.ArgumentList.Arguments[0].Expression is BinaryExpressionSyntax &&
                     create.ArgumentList.Arguments[0].Expression.IsKind(SyntaxKind.AsExpression))
            {
                var binExpr = create.ArgumentList.Arguments[0].Expression
                              as BinaryExpressionSyntax;
                if ((binExpr.Left is IdentifierNameSyntax) || (binExpr.Left is MemberAccessExpressionSyntax))
                {
                    MethodSummaryAnalysis.ComputeGivesUpSetForArgument(binExpr.Left,
                                                                       cfgNode, summary);
                }
                else if (binExpr.Left is InvocationExpressionSyntax)
                {
                    var invocation = binExpr.Left as InvocationExpressionSyntax;
                    for (int i = 1; i < invocation.ArgumentList.Arguments.Count; i++)
                    {
                        MethodSummaryAnalysis.ComputeGivesUpSetForArgument(invocation.ArgumentList.
                                                                           Arguments[i].Expression, cfgNode, summary);
                    }
                }
            }
            else if ((create.ArgumentList.Arguments[0].Expression is IdentifierNameSyntax) ||
                     (create.ArgumentList.Arguments[0].Expression is MemberAccessExpressionSyntax))
            {
                MethodSummaryAnalysis.ComputeGivesUpSetForArgument(create.ArgumentList.
                                                                   Arguments[0].Expression, cfgNode, summary);
            }

            return(true);
        }