Esempio n. 1
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)
            {
                base.ErrorReporter.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)
            {
                base.ErrorReporter.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);
        }
Esempio n. 2
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the control-flow graph node.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected void AnalyzeOwnershipInStatement(GivenUpOwnershipSymbol givenUpSymbol,
                                                   Statement statement, StateMachine machine, SemanticModel model,
                                                   TraceInfo trace)
        {
            var localDecl = statement.SyntaxNode.DescendantNodesAndSelf().
                            OfType <LocalDeclarationStatementSyntax>().FirstOrDefault();
            var expr = statement.SyntaxNode.DescendantNodesAndSelf().
                       OfType <ExpressionStatementSyntax>().FirstOrDefault();

            if (localDecl != null)
            {
                var varDecl = localDecl.Declaration;
                this.AnalyzeOwnershipInLocalDeclaration(givenUpSymbol, varDecl,
                                                        statement, machine, model, trace);
            }
            else if (expr != null)
            {
                if (expr.Expression is AssignmentExpressionSyntax)
                {
                    var assignment = expr.Expression as AssignmentExpressionSyntax;
                    this.AnalyzeOwnershipInAssignment(givenUpSymbol, assignment,
                                                      statement, machine, model, trace);
                }
                else if (expr.Expression is InvocationExpressionSyntax ||
                         expr.Expression is ObjectCreationExpressionSyntax)
                {
                    trace.InsertCall(statement.Summary.Method, expr.Expression);
                    this.AnalyzeOwnershipInCall(givenUpSymbol, expr.Expression,
                                                statement, machine, model, trace);
                }
            }
        }
Esempio n. 3
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 IdentifierNameSyntax ||
                expr is MemberAccessExpressionSyntax)
            {
                IdentifierNameSyntax rightIdentifier = base.AnalysisContext.GetRootIdentifier(expr);
                if (rightIdentifier != null)
                {
                    var rightSymbol = model.GetSymbolInfo(rightIdentifier).Symbol;
                    this.AnalyzeGivingUpFieldOwnership(givenUpSymbol, rightSymbol, statement, machine, trace);
                }
            }
            else if (expr is InvocationExpressionSyntax ||
                     expr is ObjectCreationExpressionSyntax)
            {
                trace.InsertCall(statement.Summary.Method, expr);

                HashSet <ISymbol> returnSymbols = base.AnalyzeOwnershipInCall(givenUpSymbol,
                                                                              expr, statement, machine, model, trace);
                foreach (var returnSymbol in returnSymbols)
                {
                    this.AnalyzeGivingUpFieldOwnership(givenUpSymbol, returnSymbol, statement, machine, trace);
                }
            }
        }
Esempio n. 4
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);
             }
         }
     }
 }
Esempio n. 5
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>
        /// 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);
                }
            }
        }
Esempio n. 7
0
 /// <summary>
 /// Merges the given trace to the current trace.
 /// </summary>
 internal void Merge(TraceInfo traceInfo)
 {
     this.ErrorTrace.AddRange(traceInfo.ErrorTrace);
     this.CallTrace.AddRange(traceInfo.CallTrace);
     this.Method  = traceInfo.Method;
     this.Machine = traceInfo.Machine;
     this.State   = traceInfo.State;
     this.Payload = traceInfo.Payload;
 }
Esempio n. 8
0
 /// <summary>
 /// Reports an error to the user.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 /// <param name="s">String</param>
 internal static void Report(TraceInfo trace, string s)
 {
     Report(s);
     for (int idx = trace.ErrorTrace.Count - 1; idx >= 0; idx--)
     {
         IO.Print("   at '{0}' ", trace.ErrorTrace[idx].Expression);
         IO.Print("in {0}:", trace.ErrorTrace[idx].File);
         IO.PrintLine("line {0}", trace.ErrorTrace[idx].Line);
     }
 }
Esempio n. 9
0
 /// <summary>
 /// Reports a warning to the user.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 /// <param name="s">String</param>
 /// <param name="args">Parameters</param>
 internal static void ReportWarning(TraceInfo trace, string s, params object[] args)
 {
     ReportWarning(s, args);
     if (ErrorReporter.ShowWarnings)
     {
         IO.Print("   at '{0}' ", trace.ErrorTrace[trace.ErrorTrace.Count - 1].Expression);
         IO.Print("in {0}:", trace.ErrorTrace[trace.ErrorTrace.Count - 1].File);
         IO.PrintLine("line {0}", trace.ErrorTrace[trace.ErrorTrace.Count - 1].Line);
     }
 }
Esempio n. 10
0
 /// <summary>
 /// Reports an error to the user.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 /// <param name="s">String</param>
 internal void Report(TraceInfo trace, string s)
 {
     this.Report(s);
     for (int idx = trace.ErrorTrace.Count - 1; idx >= 0; idx--)
     {
         this.Logger.Write("   at '{0}' ", trace.ErrorTrace[idx].Expression);
         this.Logger.Write("in {0}:", trace.ErrorTrace[idx].File);
         this.Logger.WriteLine("line {0}", trace.ErrorTrace[idx].Line);
     }
 }
Esempio n. 11
0
 /// <summary>
 /// Reports a warning to the user.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 /// <param name="s">String</param>
 /// <param name="args">Parameters</param>
 internal void ReportWarning(TraceInfo trace, string s, params object[] args)
 {
     this.ReportWarning(s, args);
     if (this.Configuration.ShowWarnings)
     {
         this.Logger.Write("   at '{0}' ", trace.ErrorTrace[trace.ErrorTrace.Count - 1].Expression);
         this.Logger.Write("in {0}:", trace.ErrorTrace[trace.ErrorTrace.Count - 1].File);
         this.Logger.WriteLine("line {0}", trace.ErrorTrace[trace.ErrorTrace.Count - 1].Line);
     }
 }
Esempio n. 12
0
        /// <summary>
        /// Reports a warning to the user.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="message">Message</param>
        private static void ReportWarningTrace(TraceInfo trace, string message)
        {
            if (ReportedMessages.Contains(message))
            {
                return;
            }

            ReportWarning(message);
            PrintTrace(trace);
            ReportedMessages.Add(message);
        }
Esempio n. 13
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)
        {
            IdentifierNameSyntax leftIdentifier = base.AnalysisContext.GetRootIdentifier(assignment.Left);
            ISymbol leftSymbol = model.GetSymbolInfo(leftIdentifier).Symbol;

            this.AnalyzeGivingUpFieldOwnership(givenUpSymbol, leftSymbol, statement, machine, trace);
            this.AnalyzeOwnershipInExpression(givenUpSymbol, assignment.Right,
                                              statement, machine, model, trace);
        }
Esempio n. 14
0
        /// <summary>
        /// Reports an error to the user.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="message">Message</param>
        /// <param name="allowMultiple">Allow multiple messages</param>
        private void ReportErrorTrace(TraceInfo trace, string message, bool allowMultiple = false)
        {
            if (!allowMultiple && this.ReportedMessages.Contains(message))
            {
                return;
            }

            this.Report(message);
            this.PrintTrace(trace);
            this.ReportedMessages.Add(message);
        }
Esempio n. 15
0
        /// <summary>
        /// Reports a warning to the user.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="message">Message</param>
        private void ReportWarningTrace(TraceInfo trace, string message)
        {
            if (this.ReportedMessages.Contains(message))
            {
                return;
            }

            this.ReportWarning(message);
            this.PrintTrace(trace);
            this.ReportedMessages.Add(message);
        }
Esempio n. 16
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))
     {
         base.ErrorReporter.ReportGivenUpFieldOwnershipError(trace, givenUpSymbol.ContainingSymbol);
     }
 }
        /// <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)
        {
            IdentifierNameSyntax leftIdentifier = base.AnalysisContext.GetRootIdentifier(assignment.Left);
            ISymbol leftSymbol = model.GetSymbolInfo(leftIdentifier).Symbol;

            this.AnalyzeGivingUpFieldOwnership(givenUpSymbol, leftSymbol, statement, machine, trace);
            this.AnalyzeOwnershipInExpression(givenUpSymbol, assignment.Right,
                statement, machine, model, trace);
        }
Esempio n. 18
0
        /// <summary>
        /// Analyzes the method summaries of the machine to check if
        /// each summary respects given-up ownerships.
        /// </summary>
        private void AnalyzeMethodSummariesInMachine(StateMachine machine)
        {
            foreach (var summary in machine.MethodSummaries.Values)
            {
                foreach (var givenUpSymbol in summary.GetSymbolsWithGivenUpOwnership())
                {
                    TraceInfo trace = new TraceInfo(summary.Method, machine, null, givenUpSymbol.ContainingSymbol);
                    trace.AddErrorTrace(givenUpSymbol.Statement.SyntaxNode);

                    var model = this.AnalysisContext.Compilation.GetSemanticModel(
                        givenUpSymbol.Statement.SyntaxNode.SyntaxTree);
                    this.AnalyzeOwnershipInControlFlowGraph(givenUpSymbol, machine, model, trace);
                }
            }
        }
Esempio n. 19
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>
        /// Analyzes the ownership of the given-up symbol in the expression.
        /// </summary>
        private void AnalyzeOwnershipInExpression(GivenUpOwnershipSymbol givenUpSymbol, ExpressionSyntax expr,
                                                  Statement statement, SemanticModel model, TraceInfo trace)
        {
            if (expr is MemberAccessExpressionSyntax)
            {
                var     identifier = 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);

                    this.ErrorReporter.ReportGivenUpOwnershipAccess(newTrace);
                }
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Analyzes the given-up ownership of fields in the expression.
        /// </summary>
        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 &&
                this.IsFieldAccessedInSuccessor(symbol as IFieldSymbol, statement.Summary, machine))
            {
                TraceInfo newTrace = new TraceInfo();
                newTrace.Merge(trace);
                newTrace.AddErrorTrace(statement.SyntaxNode);

                this.ErrorReporter.ReportGivenUpFieldOwnershipError(newTrace, symbol);
            }
        }
Esempio n. 22
0
 /// <summary>
 /// Prints the trace.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 private void PrintTrace(TraceInfo trace)
 {
     for (int idx = trace.ErrorTrace.Count - 1; idx >= 0; idx--)
     {
         if (idx == 0)
         {
             this.Logger.WriteLine("   --- Source of giving up ownership ---");
             this.Logger.Write("   at '{0}' ", trace.ErrorTrace[idx].Expression);
             this.Logger.Write("in {0}:", trace.ErrorTrace[idx].File);
             this.Logger.WriteLine("line {0}", trace.ErrorTrace[idx].Line);
         }
         else
         {
             this.Logger.Write("   at '{0}' ", trace.ErrorTrace[idx].Expression);
             this.Logger.Write("in {0}:", trace.ErrorTrace[idx].File);
             this.Logger.WriteLine("line {0}", trace.ErrorTrace[idx].Line);
         }
     }
 }
Esempio n. 23
0
        /// <summary>
        /// Reports assignment of given up ownership to a machine field.
        /// </summary>
        internal void ReportGivenUpOwnershipFieldAssignment(TraceInfo trace, ISymbol fieldSymbol)
        {
            string message;

            if (trace.State is null)
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' of machine '{1}' assigns '{2}' to field '{3}' after giving up its ownership.",
                                        trace.Method, trace.Machine, trace.Payload, fieldSymbol);
            }
            else
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' in state '{1}' of machine '{2}' assigns '{3}' to field '{4}' after giving up its ownership.",
                                        trace.Method, trace.State, trace.Machine, trace.Payload, fieldSymbol);
            }

            this.ReportErrorTrace(trace, message);
        }
Esempio n. 24
0
        /// <summary>
        /// Reports sending data with a given up ownership.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="argSymbol">ISymbol</param>
        internal void ReportGivenUpOwnershipSending(TraceInfo trace, ISymbol argSymbol)
        {
            string message;

            if (trace.State == null)
            {
                message = IO.Utilities.Format("Method '{0}' of machine '{1}' sends '{2}', " +
                                              "the ownership of which has already been given up.", trace.Method,
                                              trace.Machine, argSymbol);
            }
            else
            {
                message = IO.Utilities.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                                              "sends '{3}', the ownership of which has already been given up.",
                                              trace.Method, trace.State, trace.Machine, argSymbol);
            }

            this.ReportErrorTrace(trace, message);
        }
Esempio n. 25
0
        /// <summary>
        /// Reports sending data with a given up ownership.
        /// </summary>
        internal void ReportGivenUpOwnershipSending(TraceInfo trace, ISymbol argSymbol)
        {
            string message;

            if (trace.State is null)
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' of machine '{1}' sends '{2}', the ownership of which has already been given up.",
                                        trace.Method, trace.Machine, argSymbol);
            }
            else
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' in state '{1}' of machine '{2}' sends '{3}', the ownership of which has already been given up.",
                                        trace.Method, trace.State, trace.Machine, argSymbol);
            }

            this.ReportErrorTrace(trace, message);
        }
Esempio n. 26
0
        /// <summary>
        /// Reports calling a method with unavailable source code,
        /// thus cannot be further analyzed.
        /// </summary>
        internal void ReportExternalInvocation(TraceInfo trace)
        {
            string message;

            if (trace.State is null)
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' of machine '{1}' calls a method with unavailable source code, which might be a source of errors.",
                                        trace.Method, trace.Machine);
            }
            else
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' in state '{1}' of machine '{2}' calls a method with unavailable source code, which might be a source of errors.",
                                        trace.Method, trace.State, trace.Machine);
            }

            this.ReportWarningTrace(trace, message);
        }
Esempio n. 27
0
 /// <summary>
 /// Prints the trace.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 private static void PrintTrace(TraceInfo trace)
 {
     for (int idx = trace.ErrorTrace.Count - 1; idx >= 0; idx--)
     {
         if (idx == 0)
         {
             IO.PrintLine("   --- Source of giving up ownership ---");
             IO.Print("   at '{0}' ", trace.ErrorTrace[idx].Expression);
             IO.Print("in {0}:", trace.ErrorTrace[idx].File);
             IO.PrintLine("line {0}", trace.ErrorTrace[idx].Line);
         }
         else
         {
             IO.Print("   at '{0}' ", trace.ErrorTrace[idx].Expression);
             IO.Print("in {0}:", trace.ErrorTrace[idx].File);
             IO.PrintLine("line {0}", trace.ErrorTrace[idx].Line);
         }
     }
 }
Esempio n. 28
0
        /// <summary>
        /// Reports a given up field ownership error.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="fieldSymbol">ISymbol</param>
        internal void ReportGivenUpFieldOwnershipError(TraceInfo trace, ISymbol fieldSymbol)
        {
            string message;

            if (trace.State == null)
            {
                message = IO.Utilities.Format("Method '{0}' of machine '{1}' sends '{2}', " +
                                              "which contains data from field '{3}'.", trace.Method,
                                              trace.Machine, trace.Payload, fieldSymbol);
            }
            else
            {
                message = IO.Utilities.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                                              "sends '{3}', which contains data from field '{4}'.", trace.Method,
                                              trace.State, trace.Machine, trace.Payload, fieldSymbol);
            }

            this.ReportErrorTrace(trace, message);
        }
Esempio n. 29
0
        /// <summary>
        /// Reports assignment of given up ownership to a machine field.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="fieldSymbol">ISymbol</param>
        internal void ReportGivenUpOwnershipFieldAssignment(TraceInfo trace, ISymbol fieldSymbol)
        {
            string message;

            if (trace.State == null)
            {
                message = IO.Utilities.Format("Method '{0}' of machine '{1}' assigns '{2}' " +
                                              "to field '{3}' after giving up its ownership.", trace.Method,
                                              trace.Machine, trace.Payload, fieldSymbol);
            }
            else
            {
                message = IO.Utilities.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                                              "assigns '{3}' to field '{4}' after giving up its ownership.",
                                              trace.Method, trace.State, trace.Machine, trace.Payload, fieldSymbol);
            }

            this.ReportErrorTrace(trace, message);
        }
Esempio n. 30
0
        /// <summary>
        /// Reports calling a virtual method with unknown overrider,
        /// thus cannot be further analyzed.
        /// </summary>
        internal void ReportUnknownVirtualCall(TraceInfo trace)
        {
            string message;

            if (trace.State is null)
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' of machine '{1}' calls a virtual method that cannot be further analyzed.",
                                        trace.Method, trace.Machine);
            }
            else
            {
                message = string.Format(CultureInfo.InvariantCulture,
                                        "Method '{0}' in state '{1}' of machine '{2}' calls a virtual method that cannot be further analyzed.",
                                        trace.Method, trace.State, trace.Machine);
            }

            this.ReportWarningTrace(trace, message);
        }
Esempio n. 31
0
        /// <summary>
        /// Reports calling a virtual method with unknown overrider,
        /// thus cannot be further analyzed.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        internal void ReportUnknownVirtualCall(TraceInfo trace)
        {
            string message;

            if (trace.State == null)
            {
                message = IO.Utilities.Format("Method '{0}' of machine '{1}' calls " +
                                              "a virtual method that cannot be further analyzed.",
                                              trace.Method, trace.Machine);
            }
            else
            {
                message = IO.Utilities.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                                              "calls a virtual method that cannot be further analyzed.",
                                              trace.Method, trace.State, trace.Machine);
            }

            this.ReportWarningTrace(trace, message);
        }
Esempio n. 32
0
        /// <summary>
        /// Reports an access of an object with given-up ownership.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        internal void ReportGivenUpOwnershipAccess(TraceInfo trace)
        {
            string message;

            if (trace.State == null)
            {
                message = IO.Utilities.Format("Method '{0}' of machine '{1}' " +
                                              "accesses '{2}' after giving up its ownership.",
                                              trace.Method, trace.Machine, trace.Payload);
            }
            else
            {
                message = IO.Utilities.Format("Method '{0}' in state '{1}' of machine " +
                                              "'{2}' accesses '{3}' after giving up its ownership.",
                                              trace.Method, trace.State, trace.Machine, trace.Payload);
            }

            this.ReportErrorTrace(trace, message, true);
        }
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the control-flow graph.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected override void AnalyzeOwnershipInControlFlowGraph(GivenUpOwnershipSymbol givenUpSymbol,
            StateMachine machine, SemanticModel model, TraceInfo trace)
        {
            var queue = new Queue<IControlFlowNode>();
            queue.Enqueue(givenUpSymbol.Statement.ControlFlowNode);

            var visitedNodes = new HashSet<IControlFlowNode>();
            visitedNodes.Add(givenUpSymbol.Statement.ControlFlowNode);

            bool repeatGivesUpNode = false;
            while (queue.Count > 0)
            {
                IControlFlowNode node = queue.Dequeue();

                var statements = new List<Statement>();
                if (!repeatGivesUpNode &&
                    node.Equals(givenUpSymbol.Statement.ControlFlowNode))
                {
                    statements.AddRange(node.Statements.SkipWhile(
                        val => !val.Equals(givenUpSymbol.Statement)));
                }
                else if (repeatGivesUpNode &&
                    node.Equals(givenUpSymbol.Statement.ControlFlowNode))
                {
                    statements.AddRange(node.Statements.TakeWhile(
                        val => !val.Equals(givenUpSymbol.Statement)));
                    statements.Add(givenUpSymbol.Statement);
                }
                else
                {
                    statements.AddRange(node.Statements);
                }

                foreach (var statement in statements)
                {
                    base.AnalyzeOwnershipInStatement(givenUpSymbol, statement,
                        machine, model, trace);
                }

                foreach (var successor in node.ISuccessors)
                {
                    if (!repeatGivesUpNode &&
                        successor.Equals(givenUpSymbol.Statement.ControlFlowNode))
                    {
                        repeatGivesUpNode = true;
                        visitedNodes.Remove(givenUpSymbol.Statement.ControlFlowNode);
                    }

                    if (!visitedNodes.Contains(successor))
                    {
                        queue.Enqueue(successor);
                        visitedNodes.Add(successor);
                    }
                }
            }
        }
Esempio n. 34
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 abstract void AnalyzeOwnershipInAssignment(GivenUpOwnershipSymbol givenUpSymbol,
     AssignmentExpressionSyntax assignment, Statement statement, StateMachine machine,
     SemanticModel model, TraceInfo trace);
Esempio n. 35
0
        /// <summary>
        /// Analyzes the method summaries of the machine to check if
        /// each summary respects given-up ownerships.
        /// </summary>
        /// <param name="machine">StateMachine</param>
        private void AnalyzeMethodSummariesInMachine(StateMachine machine)
        {
            foreach (var summary in machine.MethodSummaries.Values)
            {
                foreach (var givenUpSymbol in summary.GetSymbolsWithGivenUpOwnership())
                {
                    TraceInfo trace = new TraceInfo(summary.Method, machine, null, givenUpSymbol.ContainingSymbol);
                    trace.AddErrorTrace(givenUpSymbol.Statement.SyntaxNode);

                    var model = this.AnalysisContext.Compilation.GetSemanticModel(
                        givenUpSymbol.Statement.SyntaxNode.SyntaxTree);
                    this.AnalyzeOwnershipInControlFlowGraph(givenUpSymbol, machine, model, trace);
                }
            }
        }
Esempio n. 36
0
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the control-flow graph node.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected void AnalyzeOwnershipInStatement(GivenUpOwnershipSymbol givenUpSymbol,
            Statement statement, StateMachine machine, SemanticModel model,
            TraceInfo trace)
        {
            var localDecl = statement.SyntaxNode.DescendantNodesAndSelf().
                OfType<LocalDeclarationStatementSyntax>().FirstOrDefault();
            var expr = statement.SyntaxNode.DescendantNodesAndSelf().
                OfType<ExpressionStatementSyntax>().FirstOrDefault();

            if (localDecl != null)
            {
                var varDecl = localDecl.Declaration;
                this.AnalyzeOwnershipInLocalDeclaration(givenUpSymbol, varDecl,
                    statement, machine, model, trace);
            }
            else if (expr != null)
            {
                if (expr.Expression is AssignmentExpressionSyntax)
                {
                    var assignment = expr.Expression as AssignmentExpressionSyntax;
                    this.AnalyzeOwnershipInAssignment(givenUpSymbol, assignment,
                        statement, machine, model, trace);
                }
                else if (expr.Expression is InvocationExpressionSyntax ||
                    expr.Expression is ObjectCreationExpressionSyntax)
                {
                    trace.InsertCall(statement.Summary.Method, expr.Expression);
                    this.AnalyzeOwnershipInCall(givenUpSymbol, expr.Expression,
                        statement, machine, model, trace);
                }
            }
        }
Esempio n. 37
0
 /// <summary>
 /// Analyzes the ownership of the given-up symbol
 /// in the variable declaration.
 /// </summary>
 /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
 /// <param name="varDecl">VariableDeclarationSyntax</param>
 /// <param name="statement">Statement</param>
 /// <param name="machine">StateMachine</param>
 /// <param name="model">SemanticModel</param>
 /// <param name="trace">TraceInfo</param>
 protected abstract void AnalyzeOwnershipInLocalDeclaration(GivenUpOwnershipSymbol givenUpSymbol,
     VariableDeclarationSyntax varDecl, Statement statement, StateMachine machine,
     SemanticModel model, TraceInfo trace);
Esempio n. 38
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 abstract void AnalyzeOwnershipInGivesUpCall(GivenUpOwnershipSymbol givenUpSymbol,
     InvocationExpressionSyntax call, Statement statement, StateMachine machine,
     SemanticModel model, TraceInfo trace);
Esempio n. 39
0
        /// <summary>
        /// Reports sending data with a given up ownership.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="argSymbol">ISymbol</param>
        internal static void ReportGivenUpOwnershipSending(TraceInfo trace, ISymbol argSymbol)
        {
            string message;
            if (trace.State == null)
            {
                message = IO.Format("Method '{0}' of machine '{1}' sends '{2}', " +
                    "the ownership of which has already been given up.", trace.Method,
                    trace.Machine, argSymbol);
            }
            else
            {
                message = IO.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                    "sends '{3}', the ownership of which has already been given up.",
                    trace.Method, trace.State, trace.Machine, argSymbol);
            }

            ReportErrorTrace(trace, message);
        }
Esempio n. 40
0
        /// <summary>
        /// Reports an error to the user.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="message">Message</param>
        /// <param name="allowMultiple">Allow multiple messages</param>
        private static void ReportErrorTrace(TraceInfo trace, string message,
            bool allowMultiple = false)
        {
            if (!allowMultiple &&
                ReportedMessages.Contains(message))
            {
                return;
            }

            Report(message);
            PrintTrace(trace);
            ReportedMessages.Add(message);
        }
Esempio n. 41
0
        /// <summary>
        /// Reports a warning to the user.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="message">Message</param>
        private static void ReportWarningTrace(TraceInfo trace, string message)
        {
            if (ReportedMessages.Contains(message))
            {
                return;
            }

            ReportWarning(message);
            PrintTrace(trace);
            ReportedMessages.Add(message);
        }
Esempio n. 42
0
 /// <summary>
 /// Prints the trace.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 private static void PrintTrace(TraceInfo trace)
 {
     for (int idx = trace.ErrorTrace.Count - 1; idx >= 0; idx--)
     {
         if (idx == 0)
         {
             IO.PrintLine("   --- Source of giving up ownership ---");
             IO.Print("   at '{0}' ", trace.ErrorTrace[idx].Expression);
             IO.Print("in {0}:", trace.ErrorTrace[idx].File);
             IO.PrintLine("line {0}", trace.ErrorTrace[idx].Line);
         }
         else
         {
             IO.Print("   at '{0}' ", trace.ErrorTrace[idx].Expression);
             IO.Print("in {0}:", trace.ErrorTrace[idx].File);
             IO.PrintLine("line {0}", trace.ErrorTrace[idx].Line);
         }
     }
 }
Esempio n. 43
0
 /// <summary>
 /// Reports a warning to the user.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 /// <param name="s">String</param>
 /// <param name="args">Parameters</param>
 internal static void ReportWarning(TraceInfo trace, string s, params object[] args)
 {
     ReportWarning(s, args);
     if (ErrorReporter.ShowWarnings)
     {
         IO.Print("   at '{0}' ", trace.ErrorTrace[trace.ErrorTrace.Count - 1].Expression);
         IO.Print("in {0}:", trace.ErrorTrace[trace.ErrorTrace.Count - 1].File);
         IO.PrintLine("line {0}", trace.ErrorTrace[trace.ErrorTrace.Count - 1].Line);
     }
 }
Esempio n. 44
0
        /// <summary>
        /// Reports calling a virtual method with unknown overrider,
        /// thus cannot be further analyzed.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        internal static void ReportUnknownVirtualCall(TraceInfo trace)
        {
            string message;
            if (trace.State == null)
            {
                message = IO.Format("Method '{0}' of machine '{1}' calls " +
                    "a virtual method that cannot be further analyzed.",
                    trace.Method, trace.Machine);
            }
            else
            {
                message = IO.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                    "calls a virtual method that cannot be further analyzed.",
                    trace.Method, trace.State, trace.Machine);
            }

            ReportWarningTrace(trace, message);
        }
        /// <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);
                    }
                }
            }
        }
Esempio n. 46
0
        /// <summary>
        /// Reports an access of a field that is alias of
        /// an object with given-up ownership.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="fieldSymbol">ISymbol</param>
        internal static void ReportGivenUpOwnershipFieldAccess(TraceInfo trace,
            IFieldSymbol fieldSymbol)
        {
            string message;
            if (trace.State == null)
            {
                message = IO.Format("Method '{0}' of machine '{1}' accesses " +
                    "'{2}', via field '{3}', after giving up its ownership.",
                    trace.Method, trace.Machine, trace.Payload, fieldSymbol);
            }
            else
            {
                message = IO.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                    "accesses '{3}', via field '{4}', after giving up its ownership.",
                    trace.Method, trace.State, trace.Machine, trace.Payload,
                    fieldSymbol);
            }

            ReportErrorTrace(trace, message, true);
        }
Esempio n. 47
0
        /// <summary>
        /// Reports calling a method with unavailable source code,
        /// thus cannot be further analyzed.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        internal static void ReportExternalInvocation(TraceInfo trace)
        {
            string message;
            if (trace.State == null)
            {
                message = IO.Format("Method '{0}' of machine '{1}' calls " +
                    "a method with unavailable source code, which might " +
                    "be a source of errors.", trace.Method, trace.Machine);
            }
            else
            {
                message = IO.Format("Method '{0}' in state '{1}' of machine " +
                    "'{2}' calls a method with unavailable source code, which " +
                    "might be a source of errors.", trace.Method, trace.State,
                    trace.Machine);
            }

            ReportWarningTrace(trace, message);
        }
        /// <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);
                    }
                }
            }
        }
 /// <summary>
 /// Analyzes the ownership of the given-up symbol
 /// in the variable declaration.
 /// </summary>
 /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
 /// <param name="varDecl">VariableDeclarationSyntax</param>
 /// <param name="statement">Statement</param>
 /// <param name="machine">StateMachine</param>
 /// <param name="model">SemanticModel</param>
 /// <param name="trace">TraceInfo</param>
 protected override void AnalyzeOwnershipInLocalDeclaration(GivenUpOwnershipSymbol givenUpSymbol,
     VariableDeclarationSyntax varDecl, Statement statement, StateMachine machine,
     SemanticModel model, TraceInfo trace)
 {
     foreach (var variable in varDecl.Variables.Where(v => v.Initializer != null))
     {
         var expr = variable.Initializer.Value;
         if (expr is IdentifierNameSyntax ||
             expr is MemberAccessExpressionSyntax)
         {
             this.AnalyzeOwnershipInExpression(givenUpSymbol, expr, statement,
                 machine, model, trace);
         }
         else if (expr is InvocationExpressionSyntax ||
             expr is ObjectCreationExpressionSyntax)
         {
             trace.InsertCall(statement.Summary.Method, expr);
             base.AnalyzeOwnershipInCall(givenUpSymbol, expr, statement,
                 machine, model, trace);
         }
     }
 }
Esempio n. 50
0
        /// <summary>
        /// Reports a given up field ownership error.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="fieldSymbol">ISymbol</param>
        internal static void ReportGivenUpFieldOwnershipError(TraceInfo trace,
            ISymbol fieldSymbol)
        {
            string message;
            if (trace.State == null)
            {
                message = IO.Format("Method '{0}' of machine '{1}' sends '{2}', " +
                    "which contains data from field '{3}'.", trace.Method,
                    trace.Machine, trace.Payload, fieldSymbol);
            }
            else
            {
                message = IO.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                    "sends '{3}', which contains data from field '{4}'.", trace.Method,
                    trace.State, trace.Machine, trace.Payload, fieldSymbol);
            }

            ReportErrorTrace(trace, message);
        }
        /// <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;
                }
            }
        }
Esempio n. 52
0
 /// <summary>
 /// Reports an error to the user.
 /// </summary>
 /// <param name="trace">TraceInfo</param>
 /// <param name="s">String</param>
 internal static void Report(TraceInfo trace, string s)
 {
     Report(s);
     for (int idx = trace.ErrorTrace.Count - 1; idx >= 0; idx--)
     {
         IO.Print("   at '{0}' ", trace.ErrorTrace[idx].Expression);
         IO.Print("in {0}:", trace.ErrorTrace[idx].File);
         IO.PrintLine("line {0}", trace.ErrorTrace[idx].Line);
     }
 }
Esempio n. 53
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);
             }
         }
     }
 }
Esempio n. 54
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);
             }
         }
     }
 }
Esempio n. 55
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;
        }
        /// <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);
                }
            }
        }
Esempio n. 57
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 abstract void AnalyzeOwnershipInCandidateCallee(GivenUpOwnershipSymbol givenUpSymbol,
     MethodSummary calleeSummary, ExpressionSyntax call, Statement statement,
     StateMachine machine, SemanticModel model, TraceInfo trace);
Esempio n. 58
0
 /// <summary>
 /// Analyzes the ownership of the given-up symbol
 /// in the control-flow graph.
 /// </summary>
 /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
 /// <param name="machine">StateMachine</param>
 /// <param name="model">SemanticModel</param>
 /// <param name="trace">TraceInfo</param>
 protected abstract void AnalyzeOwnershipInControlFlowGraph(GivenUpOwnershipSymbol givenUpSymbol,
     StateMachine machine, SemanticModel model, TraceInfo trace);
Esempio n. 59
0
        /// <summary>
        /// Reports assignment of given up ownership to a machine field.
        /// </summary>
        /// <param name="trace">TraceInfo</param>
        /// <param name="fieldSymbol">ISymbol</param>
        internal static void ReportGivenUpOwnershipFieldAssignment(TraceInfo trace,
            ISymbol fieldSymbol)
        {
            string message;
            if (trace.State == null)
            {
                message = IO.Format("Method '{0}' of machine '{1}' assigns '{2}' " +
                    "to field '{3}' after giving up its ownership.", trace.Method,
                    trace.Machine, trace.Payload, fieldSymbol);
            }
            else
            {
                message = IO.Format("Method '{0}' in state '{1}' of machine '{2}' " +
                    "assigns '{3}' to field '{4}' after giving up its ownership.",
                    trace.Method, trace.State, trace.Machine, trace.Payload, fieldSymbol);
            }

            ReportErrorTrace(trace, message);
        }
Esempio n. 60
0
 /// <summary>
 /// Merges the given trace to the current trace.
 /// </summary>
 /// <param name="traceInfo">TraceInfo</param>
 internal void Merge(TraceInfo traceInfo)
 {
     this.ErrorTrace.AddRange(traceInfo.ErrorTrace);
     this.CallTrace.AddRange(traceInfo.CallTrace);
     this.Method = traceInfo.Method;
     this.Machine = traceInfo.Machine;
     this.State = traceInfo.State;
     this.Payload = traceInfo.Payload;
 }