/// <summary> /// Returns the candidate callees after resolving the specified invocation. /// </summary> /// <param name="invocation">InvocationExpressionSyntax</param> /// <param name="node">IDataFlowNode</param> /// <returns>Set of candidate callees</returns> private static HashSet <MethodDeclarationSyntax> ResolveCandidateMethodsAtCallSite( InvocationExpressionSyntax invocation, IDataFlowNode node) { var candidateCallees = new HashSet <MethodDeclarationSyntax>(); var candidateMethodDeclaration = MethodSummaryResolver.ResolveMethodDeclaration( invocation, node) as MethodDeclarationSyntax; if (candidateMethodDeclaration == null) { return(candidateCallees); } if (candidateMethodDeclaration.Modifiers.Any(SyntaxKind.AbstractKeyword) || candidateMethodDeclaration.Modifiers.Any(SyntaxKind.VirtualKeyword) || candidateMethodDeclaration.Modifiers.Any(SyntaxKind.OverrideKeyword)) { HashSet <MethodDeclarationSyntax> overriders = null; if (!MethodSummaryResolver.TryGetCandidateMethodOverriders(out overriders, invocation, node)) { return(candidateCallees); } candidateCallees.UnionWith(overriders); } if (candidateCallees.Count == 0) { candidateCallees.Add(candidateMethodDeclaration); } return(candidateCallees); }
/// <summary> /// Returns all cached method summaries for the specified call. /// </summary> /// <param name="call">ExpressionSyntax</param> /// <param name="node">IDataFlowNode</param> /// <returns>MethodSummarys</returns> private static ISet <MethodSummary> ResolveMethodSummaries(ExpressionSyntax call, IDataFlowNode node) { var summaries = new HashSet <MethodSummary>(); var invocation = call as InvocationExpressionSyntax; var objCreation = call as ObjectCreationExpressionSyntax; var callSymbol = node.Summary.SemanticModel.GetSymbolInfo(call).Symbol; if (callSymbol == null || (invocation == null && objCreation == null)) { return(summaries); } if (node.MethodSummaryCache.ContainsKey(callSymbol)) { summaries.UnionWith(node.MethodSummaryCache[callSymbol]); } else if (invocation != null) { var parameterTypes = MethodSummaryResolver.GetCandidateParameterTypes( invocation.ArgumentList, node); var candidateCalleeDeclarations = MethodSummaryResolver. ResolveCandidateMethodsAtCallSite(invocation, node); foreach (var candidateCalleeDeclaration in candidateCalleeDeclarations) { var calleeSummary = MethodSummary.Create(node.Summary.AnalysisContext, candidateCalleeDeclaration, parameterTypes); if (calleeSummary != null) { summaries.Add(calleeSummary); } } } else { var parameterTypes = MethodSummaryResolver.GetCandidateParameterTypes( objCreation.ArgumentList, node); var constructor = MethodSummaryResolver.ResolveMethodDeclaration( objCreation, node) as ConstructorDeclarationSyntax; if (constructor != null) { var calleeSummary = MethodSummary.Create(node.Summary.AnalysisContext, constructor, parameterTypes); if (calleeSummary != null) { summaries.Add(calleeSummary); } } } return(summaries); }
/// <summary> /// Returns all cached method summaries for the specified object creation. /// </summary> /// <param name="objCreation">ObjectCreationExpressionSyntax</param> /// <param name="node">IDataFlowNode</param> /// <returns>MethodSummarys</returns> internal static ISet <MethodSummary> ResolveMethodSummaries( ObjectCreationExpressionSyntax objCreation, IDataFlowNode node) { return(MethodSummaryResolver.ResolveMethodSummaries(objCreation as ExpressionSyntax, node)); }
/// <summary> /// Returns all cached method summaries for the specified invocation. /// </summary> /// <param name="invocation">InvocationExpressionSyntax</param> /// <param name="node">IDataFlowNode</param> /// <returns>MethodSummarys</returns> internal static ISet <MethodSummary> ResolveMethodSummaries( InvocationExpressionSyntax invocation, IDataFlowNode node) { return(MethodSummaryResolver.ResolveMethodSummaries(invocation as ExpressionSyntax, node)); }
/// <summary> /// Tries to get the list of candidate methods that can /// override the specified virtual call. /// </summary> /// <param name="overriders">List of overrider methods</param> /// <param name="virtualCall">Virtual call</param> /// <param name="node">IDataFlowNode</param> /// <returns>Boolean</returns> private static bool TryGetCandidateMethodOverriders(out HashSet <MethodDeclarationSyntax> overriders, InvocationExpressionSyntax virtualCall, IDataFlowNode node) { overriders = new HashSet <MethodDeclarationSyntax>(); ISymbol calleeSymbol = null; SimpleNameSyntax callee = null; bool isThis = false; if (virtualCall.Expression is MemberAccessExpressionSyntax) { var expr = virtualCall.Expression as MemberAccessExpressionSyntax; var identifier = expr.Expression.DescendantNodesAndSelf(). OfType <IdentifierNameSyntax>().Last(); calleeSymbol = node.Summary.SemanticModel.GetSymbolInfo(identifier).Symbol; if (expr.Expression is ThisExpressionSyntax) { callee = expr.Name; isThis = true; } } else { callee = virtualCall.Expression as IdentifierNameSyntax; isThis = true; } if (isThis) { var typeDeclaration = node.Summary.Method.FirstAncestorOrSelf <TypeDeclarationSyntax>(); if (typeDeclaration != null) { foreach (var method in typeDeclaration.Members.OfType <MethodDeclarationSyntax>()) { if (method.Identifier.ToString().Equals(callee.Identifier.ToString())) { overriders.Add(method); return(true); } } } return(false); } var calleeDefinitions = node.DataFlowInfo.ResolveOutputAliases(calleeSymbol); var calleeTypes = calleeDefinitions.SelectMany(def => def.CandidateTypes); if (!calleeTypes.Any()) { return(false); } foreach (var calleeType in calleeTypes) { MethodDeclarationSyntax method = null; if (MethodSummaryResolver.TryGetMethodDeclarationFromType( out method, calleeType, virtualCall, node)) { overriders.Add(method); } } return(true); }
/// <summary> /// Analyzes the data-flow in the method call. /// </summary> /// <param name="call">ExpressionSyntax</param> /// <param name="node">IDataFlowNode</param> /// <param name="returnSymbols">Return symbols</param> /// <param name="returnTypes">Return types</param> private void AnalyzeMethodCall(ExpressionSyntax call, IDataFlowNode node, out ISet <ISymbol> returnSymbols, out ISet <ITypeSymbol> returnTypes) { returnSymbols = new HashSet <ISymbol>(); returnTypes = new HashSet <ITypeSymbol>(); var callSymbol = this.SemanticModel.GetSymbolInfo(call).Symbol; if (callSymbol == null) { return; } var invocation = call as InvocationExpressionSyntax; var objCreation = call as ObjectCreationExpressionSyntax; ISet <MethodSummary> candidateCalleeSummaries; if (invocation != null) { candidateCalleeSummaries = MethodSummaryResolver.ResolveMethodSummaries(invocation, node); } else { candidateCalleeSummaries = MethodSummaryResolver.ResolveMethodSummaries(objCreation, node); } ArgumentListSyntax argumentList; if (invocation != null) { argumentList = invocation.ArgumentList; } else { argumentList = objCreation.ArgumentList; } this.ResolveGivesUpOwnershipInCall(callSymbol, argumentList, node); foreach (var candidateCalleeSummary in candidateCalleeSummaries) { this.MapCalleeSummaryToCallSymbol(candidateCalleeSummary, callSymbol, node); this.ResolveGivesUpOwnershipInCall(callSymbol, candidateCalleeSummary, argumentList, node); this.ResolveSideEffectsInCall(call, candidateCalleeSummary, node); if (invocation != null) { returnSymbols.UnionWith(candidateCalleeSummary.GetResolvedReturnSymbols( invocation, this.SemanticModel)); } returnTypes.UnionWith(candidateCalleeSummary.SideEffectsInfo.ReturnTypes); } if (objCreation != null) { returnTypes.Add(this.SemanticModel.GetTypeInfo(call).Type); } if (invocation != null) { this.ResolveSideEffectsInExpression(invocation.Expression, node); } }