/// <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; } } }
/// <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); } } } }