示例#1
0
 /// <summary>
 /// Checks the methods of each machine and report warnings if
 /// any method is directly accessed by anything else than the
 /// P# runtime.
 /// </summary>
 /// <param name="machines">StateMachines</param>
 private void CheckMethods(ISet <StateMachine> machines)
 {
     foreach (var machine in machines)
     {
         foreach (var method in machine.Declaration.ChildNodes().OfType <MethodDeclarationSyntax>())
         {
             if (method.Modifiers.Any(SyntaxKind.PublicKeyword))
             {
                 TraceInfo trace = new TraceInfo();
                 trace.AddErrorTrace(method.Identifier);
                 AnalysisErrorReporter.ReportWarning(trace, "Method '{0}' of machine '{1}' " +
                                                     "is declared as 'public'.", method.Identifier.ValueText,
                                                     machine.Name);
             }
             else if (method.Modifiers.Any(SyntaxKind.InternalKeyword))
             {
                 TraceInfo trace = new TraceInfo();
                 trace.AddErrorTrace(method.Identifier);
                 AnalysisErrorReporter.ReportWarning(trace, "Method '{0}' of machine '{1}' " +
                                                     "is declared as 'internal'.", method.Identifier.ValueText,
                                                     machine.Name);
             }
         }
     }
 }
示例#2
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the call.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="call">ExpressionSyntax</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        /// <returns>Set of return symbols</returns>
        protected HashSet <ISymbol> AnalyzeOwnershipInCall(GivenUpOwnershipSymbol givenUpSymbol,
                                                           ExpressionSyntax call, Statement statement, StateMachine machine,
                                                           SemanticModel model, TraceInfo trace)
        {
            var potentialReturnSymbols = new HashSet <ISymbol>();

            var invocation  = call as InvocationExpressionSyntax;
            var objCreation = call as ObjectCreationExpressionSyntax;

            if ((invocation == null && objCreation == null))
            {
                return(potentialReturnSymbols);
            }

            TraceInfo callTrace = new TraceInfo();

            callTrace.Merge(trace);
            callTrace.AddErrorTrace(call);

            var callSymbol = model.GetSymbolInfo(call).Symbol;

            if (callSymbol == null)
            {
                AnalysisErrorReporter.ReportExternalInvocation(callTrace);
                return(potentialReturnSymbols);
            }

            if (callSymbol.ContainingType.ToString().Equals("Microsoft.PSharp.Machine"))
            {
                this.AnalyzeOwnershipInGivesUpCall(givenUpSymbol, invocation,
                                                   statement, machine, model, callTrace);
                return(potentialReturnSymbols);
            }

            if (SymbolFinder.FindSourceDefinitionAsync(callSymbol,
                                                       this.AnalysisContext.Solution).Result == null)
            {
                AnalysisErrorReporter.ReportExternalInvocation(callTrace);
                return(potentialReturnSymbols);
            }

            var candidateSummaries = MethodSummary.GetCachedSummaries(callSymbol, statement);

            foreach (var candidateSummary in candidateSummaries)
            {
                this.AnalyzeOwnershipInCandidateCallee(givenUpSymbol, candidateSummary,
                                                       call, statement, machine, model, callTrace);

                if (invocation != null)
                {
                    var resolvedReturnSymbols = candidateSummary.GetResolvedReturnSymbols(invocation, model);
                    foreach (var resolvedReturnSymbol in resolvedReturnSymbols)
                    {
                        potentialReturnSymbols.Add(resolvedReturnSymbol);
                    }
                }
            }

            return(potentialReturnSymbols);
        }
示例#3
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the candidate callee.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="calleeSummary">MethodSummary</param>
        /// <param name="call">ExpressionSyntax</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected override void AnalyzeOwnershipInCandidateCallee(GivenUpOwnershipSymbol givenUpSymbol,
                                                                  MethodSummary calleeSummary, ExpressionSyntax call, Statement statement,
                                                                  StateMachine machine, SemanticModel model, TraceInfo trace)
        {
            ArgumentListSyntax argumentList = base.AnalysisContext.GetArgumentList(call);

            if (argumentList == null)
            {
                return;
            }

            for (int idx = 0; idx < argumentList.Arguments.Count; idx++)
            {
                var argIdentifier = base.AnalysisContext.GetRootIdentifier(
                    argumentList.Arguments[idx].Expression);
                if (argIdentifier == null)
                {
                    continue;
                }

                ISymbol argSymbol = model.GetSymbolInfo(argIdentifier).Symbol;
                if (statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(argSymbol,
                                                                       givenUpSymbol.ContainingSymbol, statement, givenUpSymbol.Statement))
                {
                    if (calleeSummary.SideEffectsInfo.FieldFlowParamIndexes.Any(v => v.Value.Contains(idx) &&
                                                                                base.IsFieldAccessedInSuccessor(v.Key, statement.Summary, machine)))
                    {
                        AnalysisErrorReporter.ReportGivenUpFieldOwnershipError(trace, argSymbol);
                    }
                }
            }
        }
示例#4
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the assignment expression.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="assignment">AssignmentExpressionSyntax</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected override void AnalyzeOwnershipInAssignment(GivenUpOwnershipSymbol givenUpSymbol,
                                                             AssignmentExpressionSyntax assignment, Statement statement, StateMachine machine,
                                                             SemanticModel model, TraceInfo trace)
        {
            var     leftIdentifier = base.AnalysisContext.GetRootIdentifier(assignment.Left);
            ISymbol leftSymbol     = model.GetSymbolInfo(leftIdentifier).Symbol;

            if (assignment.Right is IdentifierNameSyntax)
            {
                var     rightIdentifier = base.AnalysisContext.GetRootIdentifier(assignment.Right);
                ISymbol rightSymbol     = model.GetSymbolInfo(rightIdentifier).Symbol;

                if (statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(rightSymbol,
                                                                       givenUpSymbol.ContainingSymbol, statement, givenUpSymbol.Statement))
                {
                    var type = model.GetTypeInfo(assignment.Right).Type;
                    if (leftSymbol != null && leftSymbol.Kind == SymbolKind.Field &&
                        base.IsFieldAccessedInSuccessor(leftSymbol as IFieldSymbol, statement.Summary, machine) &&
                        !base.AnalysisContext.IsTypePassedByValueOrImmutable(type))
                    {
                        TraceInfo newTrace = new TraceInfo();
                        newTrace.Merge(trace);
                        newTrace.AddErrorTrace(statement.SyntaxNode);

                        AnalysisErrorReporter.ReportGivenUpOwnershipFieldAssignment(newTrace, leftSymbol);
                    }

                    return;
                }
            }
            else if (assignment.Right is MemberAccessExpressionSyntax)
            {
                this.AnalyzeOwnershipInExpression(givenUpSymbol, assignment.Right, statement,
                                                  machine, model, trace);
            }
            else if (assignment.Right is InvocationExpressionSyntax ||
                     assignment.Right is ObjectCreationExpressionSyntax)
            {
                trace.InsertCall(statement.Summary.Method, assignment.Right);
                base.AnalyzeOwnershipInCall(givenUpSymbol, assignment.Right, statement,
                                            machine, model, trace);
            }


            if (assignment.Left is MemberAccessExpressionSyntax)
            {
                ISymbol outerLeftMemberSymbol = model.GetSymbolInfo(assignment.Left).Symbol;
                if (!outerLeftMemberSymbol.Equals(leftSymbol) &&
                    statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(givenUpSymbol.ContainingSymbol,
                                                                       leftSymbol, givenUpSymbol.Statement, statement))
                {
                    TraceInfo newTrace = new TraceInfo();
                    newTrace.Merge(trace);
                    newTrace.AddErrorTrace(statement.SyntaxNode);

                    AnalysisErrorReporter.ReportGivenUpOwnershipAccess(newTrace);
                }
            }
        }
 /// <summary>
 /// Reports use of external asynchrony.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportExternalAsynchronyUsage(Log log)
 {
     AnalysisErrorReporter.ReportGenericError(log,
                                              "Machine '{0}' is trying to use non-P# asynchronous operations. " +
                                              "This can lead to data races and is *strictly* not allowed.",
                                              log.Machine);
     Environment.Exit(1);
 }
 /// <summary>
 /// Checks the given machine for using non-P# related asynchrony.
 /// </summary>
 /// <param name="machine"></param>
 private static void CheckForExternalAsynchronyUseInMachine(ClassDeclarationSyntax machine)
 {
     if (machine.SyntaxTree.GetRoot().DescendantNodesAndSelf().Any(v
                                                                   => v.ToString().Contains("System.Threading")))
     {
         Log log = new Log(null, machine, null, null);
         AnalysisErrorReporter.ReportExternalAsynchronyUsage(log);
     }
 }
示例#7
0
 /// <summary>
 /// Analyzes the ownership of the given-up symbol
 /// in the gives-up operation.
 /// </summary>
 /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
 /// <param name="call">Gives-up call</param>
 /// <param name="statement">Statement</param>
 /// <param name="machine">StateMachine</param>
 /// <param name="model">SemanticModel</param>
 /// <param name="trace">TraceInfo</param>
 protected override void AnalyzeOwnershipInGivesUpCall(GivenUpOwnershipSymbol givenUpSymbol,
                                                       InvocationExpressionSyntax call, Statement statement, StateMachine machine,
                                                       SemanticModel model, TraceInfo trace)
 {
     if (givenUpSymbol.Statement.Equals(statement) &&
         givenUpSymbol.ContainingSymbol.Kind == SymbolKind.Field &&
         base.IsFieldAccessedInSuccessor(givenUpSymbol.ContainingSymbol as IFieldSymbol, statement.Summary, machine))
     {
         AnalysisErrorReporter.ReportGivenUpFieldOwnershipError(trace, givenUpSymbol.ContainingSymbol);
     }
 }
示例#8
0
 /// <summary>
 /// Checks the states of each machine and report warnings if
 /// any state is declared as generic.
 /// </summary>
 /// <param name="machines">StateMachines</param>
 private void CheckStates(ISet <StateMachine> machines)
 {
     foreach (var machine in machines)
     {
         foreach (var state in machine.MachineStates)
         {
             if (state.Declaration.Arity > 0)
             {
                 TraceInfo trace = new TraceInfo();
                 trace.AddErrorTrace(state.Declaration.Identifier);
                 AnalysisErrorReporter.Report(trace, $"State '{state.Name}' was" +
                                              $" declared as generic, which is not allowed by P#.");
             }
         }
     }
 }
 /// <summary>
 /// Reports assignment of payload to a machine field.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportPayloadFieldAssignment(Log log)
 {
     if (log.State == null)
     {
         AnalysisErrorReporter.ReportDataRaceSource(log,
                                                    "Method '{0}' of machine '{1}' assigns the latest received " +
                                                    "payload to a machine field.",
                                                    log.Method, log.Machine);
     }
     else
     {
         AnalysisErrorReporter.ReportDataRaceSource(log,
                                                    "Method '{0}' in state '{1}' of machine '{2}' assigns " +
                                                    "the latest received payload to a machine field.",
                                                    log.Method, log.State, log.Machine);
     }
 }
 /// <summary>
 /// Reports calling a virtual method with unknown overrider,
 /// thus cannot be further analysed.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportUnknownVirtualCall(Log log)
 {
     if (log.State == null)
     {
         AnalysisErrorReporter.ReportWarning(log,
                                             "Method '{0}' of machine '{1}' calls a virtual method that " +
                                             "cannot be further analysed.",
                                             log.Method, log.Machine);
     }
     else
     {
         AnalysisErrorReporter.ReportWarning(log,
                                             "Method '{0}' in state '{1}' of machine '{2}' calls a virtual " +
                                             "method that cannot be further analysed.",
                                             log.Method, log.State, log.Machine);
     }
 }
 /// <summary>
 /// Reports a potendial data race.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportPotentialDataRace(Log log)
 {
     if (log.State == null)
     {
         AnalysisErrorReporter.ReportOwnershipError(log,
                                                    "Method '{0}' of machine '{1}' accesses '{2}' after " +
                                                    "giving up its ownership.",
                                                    log.Method, log.Machine, log.Payload);
     }
     else
     {
         AnalysisErrorReporter.ReportOwnershipError(log,
                                                    "Method '{0}' in state '{1}' of machine '{2}' accesses " +
                                                    "'{3}' after giving up its ownership.",
                                                    log.Method, log.State, log.Machine, log.Payload);
     }
 }
 /// <summary>
 /// Reports calling a method with unavailable source code,
 /// thus cannot be further analysed.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportUnknownInvocation(Log log)
 {
     if (log.State == null)
     {
         AnalysisErrorReporter.ReportWarning(log,
                                             "Method '{0}' of machine '{1}' calls a method with unavailable " +
                                             "source code, which might be a source of errors.",
                                             log.Method, log.Machine);
     }
     else
     {
         AnalysisErrorReporter.ReportWarning(log,
                                             "Method '{0}' in state '{1}' of machine '{2}' calls a method " +
                                             "with unavailable source code, which might be a source of errors.",
                                             log.Method, log.State, log.Machine);
     }
 }
 /// <summary>
 /// Reports sending data with a given up ownership.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportGivenUpOwnershipSending(Log log)
 {
     if (log.State == null)
     {
         AnalysisErrorReporter.ReportOwnershipError(log,
                                                    "Method '{0}' of machine '{1}' sends an event that contains " +
                                                    "payload with already given up ownership.",
                                                    log.Method, log.Machine);
     }
     else
     {
         AnalysisErrorReporter.ReportOwnershipError(log,
                                                    "Method '{0}' in state '{1}' of machine '{2}' sends an event that " +
                                                    "contains payload with already given up ownership.",
                                                    log.Method, log.State, log.Machine);
     }
 }
 /// <summary>
 /// Reports assignment of given up ownership to a machine field.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportGivenUpOwnershipFieldAssignment(Log log)
 {
     if (log.State == null)
     {
         AnalysisErrorReporter.ReportOwnershipError(log,
                                                    "Method '{0}' of machine '{1}' assigns '{2}' to " +
                                                    "a machine field after giving up its ownership.",
                                                    log.Method, log.Machine, log.Payload);
     }
     else
     {
         AnalysisErrorReporter.ReportOwnershipError(log,
                                                    "Method '{0}' in state '{1}' of machine '{2}' assigns " +
                                                    "'{3}' to a machine field after giving up its ownership.",
                                                    log.Method, log.State, log.Machine, log.Payload);
     }
 }
 /// <summary>
 /// Reports a given up field ownership error.
 /// </summary>
 /// <param name="log">Log</param>
 internal static void ReportGivenUpFieldOwnershipError(Log log)
 {
     if (log.State == null)
     {
         AnalysisErrorReporter.ReportDataRaceSource(log,
                                                    "Method '{0}' of machine '{1}' sends payload '{2}', which " +
                                                    "contains data from a machine field.",
                                                    log.Method, log.Machine, log.Payload);
     }
     else
     {
         AnalysisErrorReporter.ReportDataRaceSource(log,
                                                    "Method '{0}' in state '{1}' of machine '{2}' sends payload " +
                                                    "'{3}', which contains data from a machine field.",
                                                    log.Method, log.State, log.Machine, log.Payload);
     }
 }
        /// <summary>
        /// Reports a runtime only method access error.
        /// </summary>
        /// <param name="log">Log</param>
        internal static void ReportRuntimeOnlyMethodAccess(Log log)
        {
            if (log.State == null)
            {
                AnalysisErrorReporter.ReportGenericError(log,
                                                         "Method '{0}' of machine '{1}' is trying to access a P# " +
                                                         "runtime only method.", log.Method, log.Machine);
            }
            else
            {
                AnalysisErrorReporter.ReportGenericError(log,
                                                         "Method '{0}' in state {1} of machine '{2}' is trying to " +
                                                         "access a P# runtime only method.",
                                                         log.Method, log.State, log.Machine);
            }

            Environment.Exit(1);
        }
示例#17
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the expression.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="expr">ExpressionSyntax</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        private void AnalyzeOwnershipInExpression(GivenUpOwnershipSymbol givenUpSymbol,
                                                  ExpressionSyntax expr, Statement statement, StateMachine machine,
                                                  SemanticModel model, TraceInfo trace)
        {
            if (expr is MemberAccessExpressionSyntax)
            {
                var     identifier = base.AnalysisContext.GetRootIdentifier(expr);
                ISymbol symbol     = model.GetSymbolInfo(identifier).Symbol;
                if (statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(symbol,
                                                                       givenUpSymbol.ContainingSymbol, statement, givenUpSymbol.Statement))
                {
                    TraceInfo newTrace = new TraceInfo();
                    newTrace.Merge(trace);
                    newTrace.AddErrorTrace(statement.SyntaxNode);

                    AnalysisErrorReporter.ReportGivenUpOwnershipAccess(newTrace);
                }
            }
        }
示例#18
0
        /// <summary>
        /// Analyzes the given-up ownership of fields in the expression.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="symbol">Symbol</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="trace">TraceInfo</param>
        private void AnalyzeGivingUpFieldOwnership(GivenUpOwnershipSymbol givenUpSymbol,
                                                   ISymbol symbol, Statement statement, StateMachine machine, TraceInfo trace)
        {
            if (!statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(symbol,
                                                                    givenUpSymbol.ContainingSymbol, statement, givenUpSymbol.Statement))
            {
                return;
            }

            if (symbol.Kind == SymbolKind.Field &&
                base.IsFieldAccessedInSuccessor(symbol as IFieldSymbol, statement.Summary, machine))
            {
                TraceInfo newTrace = new TraceInfo();
                newTrace.Merge(trace);
                newTrace.AddErrorTrace(statement.SyntaxNode);

                AnalysisErrorReporter.ReportGivenUpFieldOwnershipError(newTrace, symbol);
            }
        }
        /// <summary>
        /// Reports an explicit state initialisation error.
        /// </summary>
        /// <param name="log">Log</param>
        internal static void ReportExplicitStateInitialisation(Log log)
        {
            if (log.State == null)
            {
                AnalysisErrorReporter.ReportGenericError(log,
                                                         "Method '{0}' of machine '{1}' is trying to explicitly " +
                                                         "initialize a machine state.",
                                                         log.Method, log.Machine);
            }
            else
            {
                AnalysisErrorReporter.ReportGenericError(log,
                                                         "Method '{0}' in state {1} of machine '{2}' is trying to " +
                                                         "explicitly initialize a machine state.",
                                                         log.Method, log.State, log.Machine);
            }

            Environment.Exit(1);
        }
示例#20
0
 /// <summary>
 /// Checks the fields of each machine and report warnings if
 /// any field is not private or protected.
 /// </summary>
 /// <param name="machines">StateMachines</param>
 private void CheckFields(ISet <StateMachine> machines)
 {
     foreach (var machine in machines)
     {
         foreach (var field in machine.Declaration.ChildNodes().OfType <FieldDeclarationSyntax>())
         {
             if (field.Modifiers.Any(SyntaxKind.PublicKeyword))
             {
                 TraceInfo trace = new TraceInfo();
                 trace.AddErrorTrace(field);
                 AnalysisErrorReporter.ReportWarning(trace, "Field '{0}' of machine '{1}' is " +
                                                     "declared as 'public'.", field.Declaration.ToString(), machine.Name);
             }
             else if (field.Modifiers.Any(SyntaxKind.InternalKeyword))
             {
                 TraceInfo trace = new TraceInfo();
                 trace.AddErrorTrace(field);
                 AnalysisErrorReporter.ReportWarning(trace, "Field '{0}' of machine '{1}' is " +
                                                     "declared as 'internal'.", field.Declaration.ToString(), machine.Name);
             }
         }
     }
 }
示例#21
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the gives-up operation.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="call">Gives-up call</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected override void AnalyzeOwnershipInGivesUpCall(GivenUpOwnershipSymbol givenUpSymbol,
                                                              InvocationExpressionSyntax call, Statement statement, StateMachine machine,
                                                              SemanticModel model, TraceInfo trace)
        {
            if (statement.Equals(givenUpSymbol.Statement) &&
                !statement.ControlFlowNode.IsSuccessorOf(
                    givenUpSymbol.Statement.ControlFlowNode))
            {
                return;
            }

            var opSymbol = model.GetSymbolInfo(call).Symbol;

            if ((!opSymbol.Name.Equals("Send") &&
                 !opSymbol.Name.Equals("CreateMachine")) ||
                (opSymbol.Name.Equals("CreateMachine") &&
                 call.ArgumentList.Arguments.Count != 2))
            {
                return;
            }

            ExpressionSyntax argExpr = call.ArgumentList.Arguments[1].Expression;
            var arguments            = new List <ExpressionSyntax>();

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

            var extractedArgs = base.ExtractArguments(arguments);

            foreach (var arg in extractedArgs)
            {
                IdentifierNameSyntax argIdentifier = base.AnalysisContext.GetRootIdentifier(arg);
                ITypeSymbol          argType       = model.GetTypeInfo(argIdentifier).Type;
                if (base.AnalysisContext.IsTypePassedByValueOrImmutable(argType))
                {
                    continue;
                }

                ISymbol argSymbol = model.GetSymbolInfo(argIdentifier).Symbol;
                if (statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(argSymbol,
                                                                       givenUpSymbol.ContainingSymbol, statement, givenUpSymbol.Statement))
                {
                    AnalysisErrorReporter.ReportGivenUpOwnershipSending(trace, argSymbol);
                    return;
                }
            }
        }
示例#22
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the candidate callee.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="calleeSummary">MethodSummary</param>
        /// <param name="call">ExpressionSyntax</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected override void AnalyzeOwnershipInCandidateCallee(GivenUpOwnershipSymbol givenUpSymbol,
                                                                  MethodSummary calleeSummary, ExpressionSyntax call, Statement statement,
                                                                  StateMachine machine, SemanticModel model, TraceInfo trace)
        {
            if (statement.Equals(givenUpSymbol.Statement) &&
                !statement.ControlFlowNode.IsSuccessorOf(
                    givenUpSymbol.Statement.ControlFlowNode))
            {
                return;
            }

            var invocation = call as InvocationExpressionSyntax;

            if (invocation != null)
            {
                this.AnalyzeOwnershipInExpression(givenUpSymbol, invocation.Expression, statement,
                                                  machine, model, trace);
            }

            ArgumentListSyntax argumentList = base.AnalysisContext.GetArgumentList(call);

            if (argumentList != null)
            {
                for (int idx = 0; idx < argumentList.Arguments.Count; idx++)
                {
                    var argType = model.GetTypeInfo(argumentList.Arguments[idx].Expression).Type;
                    if (base.AnalysisContext.IsTypePassedByValueOrImmutable(argType))
                    {
                        continue;
                    }

                    var argIdentifier = base.AnalysisContext.GetRootIdentifier(
                        argumentList.Arguments[idx].Expression);
                    ISymbol argSymbol = model.GetSymbolInfo(argIdentifier).Symbol;

                    if (statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(argSymbol,
                                                                           givenUpSymbol.ContainingSymbol, statement, givenUpSymbol.Statement))
                    {
                        if (calleeSummary.SideEffectsInfo.ParameterAccesses.ContainsKey(idx))
                        {
                            foreach (var access in calleeSummary.SideEffectsInfo.ParameterAccesses[idx])
                            {
                                TraceInfo newTrace = new TraceInfo();
                                newTrace.Merge(trace);
                                newTrace.AddErrorTrace(access.SyntaxNode);

                                AnalysisErrorReporter.ReportGivenUpOwnershipAccess(newTrace);
                            }
                        }

                        var fieldSymbols = calleeSummary.SideEffectsInfo.FieldFlowParamIndexes.Where(
                            v => v.Value.Contains(idx)).Select(v => v.Key);
                        foreach (var fieldSymbol in fieldSymbols)
                        {
                            if (base.IsFieldAccessedInSuccessor(fieldSymbol, statement.Summary, machine))
                            {
                                AnalysisErrorReporter.ReportGivenUpOwnershipFieldAssignment(trace, fieldSymbol);
                            }
                        }

                        if (calleeSummary.SideEffectsInfo.GivesUpOwnershipParamIndexes.Contains(idx))
                        {
                            AnalysisErrorReporter.ReportGivenUpOwnershipSending(trace, argSymbol);
                        }
                    }
                }
            }

            foreach (var fieldAccess in calleeSummary.SideEffectsInfo.FieldAccesses)
            {
                foreach (var access in fieldAccess.Value)
                {
                    if (statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(givenUpSymbol.ContainingSymbol,
                                                                           fieldAccess.Key, givenUpSymbol.Statement, statement))
                    {
                        TraceInfo newTrace = new TraceInfo();
                        newTrace.Merge(trace);
                        newTrace.AddErrorTrace(access.SyntaxNode);

                        AnalysisErrorReporter.ReportGivenUpOwnershipFieldAccess(newTrace, fieldAccess.Key);
                    }
                }
            }
        }
        /// <summary>
        /// Check the given statement for any missbehaviour.
        /// </summary>
        /// <param name="stmt">Statement</param>
        /// <param name="method">Method</param>
        /// <param name="machine">machine</param>
        /// <param name="state">state</param>
        private static void CheckStatement(StatementSyntax stmt, MethodDeclarationSyntax method,
                                           ClassDeclarationSyntax machine, ClassDeclarationSyntax state = null)
        {
            if (stmt is ExpressionStatementSyntax)
            {
                var exprStmt = stmt as ExpressionStatementSyntax;
                if (exprStmt.Expression is InvocationExpressionSyntax)
                {
                    var invExprStmt = exprStmt.Expression as InvocationExpressionSyntax;
                    if (invExprStmt.Expression is MemberAccessExpressionSyntax)
                    {
                        var callStmt = invExprStmt.Expression as MemberAccessExpressionSyntax;
                        if (callStmt.Name.Identifier.ValueText.Equals("OnEntry") ||
                            callStmt.Name.Identifier.ValueText.Equals("OnExit") ||
                            callStmt.Name.Identifier.ValueText.Equals("DefineIgnoredEvents") ||
                            callStmt.Name.Identifier.ValueText.Equals("DefineDeferredEvents") ||
                            callStmt.Name.Identifier.ValueText.Equals("DefineGotoStateTransitions") ||
                            callStmt.Name.Identifier.ValueText.Equals("DefinePushStateTransitions") ||
                            callStmt.Name.Identifier.ValueText.Equals("DefineActionBindings"))
                        {
                            Log log = new Log(method, machine, state, null);
                            log.AddTrace(callStmt.ToString(), callStmt.SyntaxTree.FilePath, callStmt.SyntaxTree.
                                         GetLineSpan(callStmt.Span).StartLinePosition.Line + 1);
                            AnalysisErrorReporter.ReportRuntimeOnlyMethodAccess(log);
                        }
                    }
                }
                else if (exprStmt.Expression is BinaryExpressionSyntax)
                {
                    var binExprStmt = exprStmt.Expression as BinaryExpressionSyntax;
                    if (binExprStmt.Right is ObjectCreationExpressionSyntax)
                    {
                        var newObjStmt = binExprStmt.Right as ObjectCreationExpressionSyntax;
                        if (SanityCheckingAnalysis.IsStateOfTheMachine(newObjStmt.Type.ToString(), machine))
                        {
                            Log log = new Log(method, machine, state, null);
                            log.AddTrace(newObjStmt.ToString(), newObjStmt.SyntaxTree.FilePath, newObjStmt.SyntaxTree.
                                         GetLineSpan(newObjStmt.Span).StartLinePosition.Line + 1);
                            AnalysisErrorReporter.ReportExplicitStateInitialisation(log);
                        }
                    }
                }
            }
            else if (stmt is LocalDeclarationStatementSyntax)
            {
                var localDeclStmt = stmt as LocalDeclarationStatementSyntax;
                foreach (var variable in localDeclStmt.Declaration.Variables)
                {
                    if (variable.Initializer != null &&
                        variable.Initializer.Value is ObjectCreationExpressionSyntax)
                    {
                        var newObjStmt = variable.Initializer.Value as ObjectCreationExpressionSyntax;
                        if (SanityCheckingAnalysis.IsStateOfTheMachine(newObjStmt.Type.ToString(), machine))
                        {
                            Log log = new Log(method, machine, state, null);
                            log.AddTrace(newObjStmt.ToString(), newObjStmt.SyntaxTree.FilePath, newObjStmt.SyntaxTree.
                                         GetLineSpan(newObjStmt.Span).StartLinePosition.Line + 1);
                            AnalysisErrorReporter.ReportExplicitStateInitialisation(log);
                        }
                    }
                }
            }
            else if (stmt is IfStatementSyntax)
            {
                var ifStmt = stmt as IfStatementSyntax;
                if (ifStmt.Statement is BlockSyntax)
                {
                    var ifBlockStmt = ifStmt.Statement as BlockSyntax;
                    foreach (var ibs in ifBlockStmt.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(ibs, method, machine, state);
                    }

                    if (ifStmt.Else != null)
                    {
                        if (ifStmt.Else.Statement is IfStatementSyntax)
                        {
                            SanityCheckingAnalysis.CheckStatement(ifStmt.Else.Statement,
                                                                  method, machine, state);
                        }
                        else if (ifStmt.Else.Statement is BlockSyntax)
                        {
                            var elseBlockStmt = ifStmt.Else.Statement as BlockSyntax;
                            foreach (var ebs in elseBlockStmt.Statements)
                            {
                                SanityCheckingAnalysis.CheckStatement(ebs, method, machine, state);
                            }
                        }
                    }
                }
                else
                {
                    SanityCheckingAnalysis.CheckStatement(ifStmt.Statement, method, machine, state);
                }
            }
            else if (stmt is ForStatementSyntax)
            {
                var forStmt = stmt as ForStatementSyntax;
                if (forStmt.Statement is BlockSyntax)
                {
                    var forBlockStmt = forStmt.Statement as BlockSyntax;
                    foreach (var fbs in forBlockStmt.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(fbs, method, machine, state);
                    }
                }
                else
                {
                    SanityCheckingAnalysis.CheckStatement(forStmt.Statement, method, machine, state);
                }
            }
            else if (stmt is ForEachStatementSyntax)
            {
                var forEachStmt = stmt as ForEachStatementSyntax;
                if (forEachStmt.Statement is BlockSyntax)
                {
                    var forEachBlockStmt = forEachStmt.Statement as BlockSyntax;
                    foreach (var fbs in forEachBlockStmt.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(fbs, method, machine, state);
                    }
                }
                else
                {
                    SanityCheckingAnalysis.CheckStatement(forEachStmt.Statement, method, machine, state);
                }
            }
            else if (stmt is WhileStatementSyntax)
            {
                var whileStmt = stmt as WhileStatementSyntax;
                if (whileStmt.Statement is BlockSyntax)
                {
                    var whileBlockStmt = whileStmt.Statement as BlockSyntax;
                    foreach (var wbs in whileBlockStmt.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(wbs, method, machine, state);
                    }
                }
                else
                {
                    SanityCheckingAnalysis.CheckStatement(whileStmt.Statement, method, machine, state);
                }
            }
            else if (stmt is DoStatementSyntax)
            {
                var doStmt = stmt as DoStatementSyntax;
                if (doStmt.Statement is BlockSyntax)
                {
                    var doBlockStmt = doStmt.Statement as BlockSyntax;
                    foreach (var dbs in doBlockStmt.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(dbs, method, machine, state);
                    }
                }
                else
                {
                    SanityCheckingAnalysis.CheckStatement(doStmt.Statement, method, machine, state);
                }
            }
            else if (stmt is SwitchStatementSyntax)
            {
                var switchStmt = stmt as SwitchStatementSyntax;
                foreach (var section in switchStmt.Sections)
                {
                    foreach (var sbs in section.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(sbs, method, machine, state);
                    }
                }
            }
            else if (stmt is TryStatementSyntax)
            {
                var tryStmt = stmt as TryStatementSyntax;
                foreach (var tbs in tryStmt.Block.Statements)
                {
                    SanityCheckingAnalysis.CheckStatement(tbs, method, machine, state);
                }

                foreach (var ctch in tryStmt.Catches)
                {
                    foreach (var cbs in ctch.Block.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(cbs, method, machine, state);
                    }
                }

                if (tryStmt.Finally != null)
                {
                    foreach (var tbs in tryStmt.Finally.Block.Statements)
                    {
                        SanityCheckingAnalysis.CheckStatement(tbs, method, machine, state);
                    }
                }
            }
            else if (stmt is UsingStatementSyntax)
            {
                var usingStmt      = stmt as UsingStatementSyntax;
                var usingBlockStmt = usingStmt.Statement as BlockSyntax;
                foreach (var ubs in usingBlockStmt.Statements)
                {
                    SanityCheckingAnalysis.CheckStatement(ubs, method, machine, state);
                }
            }
        }