Пример #1
0
        /// <summary>
        /// Performs data flow analysis on the given control flow graph node.
        /// </summary>
        /// <param name="cfgNode">ControlFlowGraphNode</param>
        /// <param name="previousCfgNode">Previous controlFlowGraphNode</param>
        /// <param name="previousSyntaxNode">Previous syntaxNode</param>
        /// <param name="dataFlowMap">DataFlowMap</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="context">AnalysisContext</param>
        /// <returns>Boolean</returns>
        private static void AnalyseControlFlowGraphNode(ControlFlowGraphNode cfgNode, ControlFlowGraphNode previousCfgNode,
            SyntaxNode previousSyntaxNode, DataFlowMap dataFlowMap, SemanticModel model, AnalysisContext context)
        {
            if (!cfgNode.IsJumpNode && !cfgNode.IsLoopHeadNode)
            {
                foreach (var syntaxNode in cfgNode.SyntaxNodes)
                {
                    dataFlowMap.Transfer(previousSyntaxNode, previousCfgNode, syntaxNode, cfgNode);

                    var stmt = syntaxNode as StatementSyntax;
                    var localDecl = stmt.DescendantNodesAndSelf().OfType<LocalDeclarationStatementSyntax>().FirstOrDefault();
                    var expr = stmt.DescendantNodesAndSelf().OfType<ExpressionStatementSyntax>().FirstOrDefault();
                    var ret = stmt.DescendantNodesAndSelf().OfType<ReturnStatementSyntax>().FirstOrDefault();

                    if (localDecl != null)
                    {
                        var varDecl = (stmt as LocalDeclarationStatementSyntax).Declaration;
                        foreach (var variable in varDecl.Variables)
                        {
                            if (variable.Initializer == null)
                            {
                                continue;
                            }

                            DataFlowAnalysis.TryCaptureParameterAccess(variable.Initializer.Value,
                                syntaxNode, cfgNode, dataFlowMap, model, context);
                            DataFlowAnalysis.TryCaptureFieldAccess(variable.Initializer.Value,
                                syntaxNode, cfgNode, dataFlowMap, model, context);

                            ITypeSymbol declType = null;
                            if (variable.Initializer.Value is LiteralExpressionSyntax &&
                                variable.Initializer.Value.IsKind(SyntaxKind.NullLiteralExpression))
                            {
                                declType = model.GetTypeInfo(varDecl.Type).Type;
                            }
                            else
                            {
                                declType = model.GetTypeInfo(variable.Initializer.Value).Type;
                            }

                            if (context.IsTypeAllowedToBeSend(declType) ||
                                context.IsMachineType(declType, model))
                            {
                                continue;
                            }

                            var declSymbol = model.GetDeclaredSymbol(variable);

                            if (variable.Initializer.Value is IdentifierNameSyntax ||
                                variable.Initializer.Value is MemberAccessExpressionSyntax)
                            {
                                ISymbol varSymbol = null;
                                if (variable.Initializer.Value is IdentifierNameSyntax)
                                {
                                    varSymbol = model.GetSymbolInfo(variable.Initializer.Value
                                        as IdentifierNameSyntax).Symbol;
                                }
                                else if (variable.Initializer.Value is MemberAccessExpressionSyntax)
                                {
                                    varSymbol = model.GetSymbolInfo((variable.Initializer.Value
                                        as MemberAccessExpressionSyntax).Name).Symbol;
                                }

                                dataFlowMap.MapRefToSymbol(varSymbol, declSymbol, syntaxNode, cfgNode);

                                HashSet<ITypeSymbol> objectTypes = null;
                                if (DataFlowAnalysis.ResolveObjectType(out objectTypes, varSymbol, syntaxNode,
                                    cfgNode, dataFlowMap))
                                {
                                    dataFlowMap.MapObjectTypesToSymbol(objectTypes, declSymbol, syntaxNode, cfgNode);
                                }
                                else
                                {
                                    dataFlowMap.EraseObjectTypesFromSymbol(declSymbol, syntaxNode, cfgNode);
                                }
                            }
                            else if (variable.Initializer.Value is LiteralExpressionSyntax &&
                                variable.Initializer.Value.IsKind(SyntaxKind.NullLiteralExpression))
                            {
                                dataFlowMap.ResetSymbol(declSymbol, syntaxNode, cfgNode);
                            }
                            else if (variable.Initializer.Value is InvocationExpressionSyntax)
                            {
                                var invocation = variable.Initializer.Value as InvocationExpressionSyntax;
                                var summary = MethodSummary.TryGetSummary(invocation, model, context);
                                var reachableSymbols = DataFlowAnalysis.ResolveSideEffectsInCall(invocation,
                                    summary, syntaxNode, cfgNode, model, dataFlowMap);
                                var returnSymbols = DataFlowAnalysis.GetReturnSymbols(invocation, summary, model);

                                if (returnSymbols.Count == 0)
                                {
                                    dataFlowMap.ResetSymbol(declSymbol, syntaxNode, cfgNode);
                                }
                                else if (returnSymbols.Contains(declSymbol))
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, declSymbol, syntaxNode, cfgNode, false);
                                }
                                else
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, declSymbol, syntaxNode, cfgNode);
                                }

                                if (reachableSymbols.Count > 0)
                                {
                                    dataFlowMap.MapReachableFieldsToSymbol(reachableSymbols, declSymbol,
                                        syntaxNode, cfgNode);
                                }

                                if (summary != null && summary.ReturnTypeSet.Count > 0)
                                {
                                    dataFlowMap.MapObjectTypesToSymbol(summary.ReturnTypeSet,
                                        declSymbol, syntaxNode, cfgNode);
                                }
                                else
                                {
                                    dataFlowMap.EraseObjectTypesFromSymbol(declSymbol, syntaxNode, cfgNode);
                                }
                            }
                            else if (variable.Initializer.Value is ObjectCreationExpressionSyntax)
                            {
                                var objCreation = variable.Initializer.Value as ObjectCreationExpressionSyntax;
                                var summary = MethodSummary.TryGetSummary(objCreation, model, context);
                                var reachableSymbols = DataFlowAnalysis.ResolveSideEffectsInCall(objCreation,
                                    summary, syntaxNode, cfgNode, model, dataFlowMap);
                                var returnSymbols = DataFlowAnalysis.GetReturnSymbols(objCreation, summary, model);

                                if (returnSymbols.Count == 0)
                                {
                                    dataFlowMap.ResetSymbol(declSymbol, syntaxNode, cfgNode);
                                }
                                else if (returnSymbols.Contains(declSymbol))
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, declSymbol, syntaxNode, cfgNode, false);
                                }
                                else
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, declSymbol, syntaxNode, cfgNode);
                                }

                                if (reachableSymbols.Count > 0)
                                {
                                    dataFlowMap.MapReachableFieldsToSymbol(reachableSymbols, declSymbol,
                                        syntaxNode, cfgNode);
                                }

                                var typeSymbol = model.GetSymbolInfo(objCreation.Type).Symbol as ITypeSymbol;
                                if (typeSymbol != null)
                                {
                                    dataFlowMap.MapObjectTypesToSymbol(new HashSet<ITypeSymbol> { typeSymbol },
                                        declSymbol, syntaxNode, cfgNode);
                                }
                                else
                                {
                                    dataFlowMap.EraseObjectTypesFromSymbol(declSymbol, syntaxNode, cfgNode);
                                }
                            }
                        }
                    }
                    else if (expr != null)
                    {
                        if (expr.Expression is BinaryExpressionSyntax)
                        {
                            var binaryExpr = expr.Expression as BinaryExpressionSyntax;

                            DataFlowAnalysis.TryCaptureParameterAccess(binaryExpr.Left,
                                syntaxNode, cfgNode, dataFlowMap, model, context);
                            DataFlowAnalysis.TryCaptureParameterAccess(binaryExpr.Right,
                                syntaxNode, cfgNode, dataFlowMap, model, context);
                            DataFlowAnalysis.TryCaptureFieldAccess(binaryExpr.Left,
                                syntaxNode, cfgNode, dataFlowMap, model, context);
                            DataFlowAnalysis.TryCaptureFieldAccess(binaryExpr.Right,
                                syntaxNode, cfgNode, dataFlowMap, model, context);

                            IdentifierNameSyntax lhs = null;
                            ISymbol lhsFieldSymbol = null;
                            if (binaryExpr.Left is IdentifierNameSyntax)
                            {
                                lhs = binaryExpr.Left as IdentifierNameSyntax;
                                var lhsType = model.GetTypeInfo(lhs).Type;
                                if (context.IsTypeAllowedToBeSend(lhsType) ||
                                    context.IsMachineType(lhsType, model))
                                {
                                    previousSyntaxNode = syntaxNode;
                                    previousCfgNode = cfgNode;
                                    continue;
                                }
                            }
                            else if (binaryExpr.Left is MemberAccessExpressionSyntax)
                            {
                                var name = (binaryExpr.Left as MemberAccessExpressionSyntax).Name;
                                var lhsType = model.GetTypeInfo(name).Type;
                                if (context.IsTypeAllowedToBeSend(lhsType) ||
                                    context.IsMachineType(lhsType, model))
                                {
                                    previousSyntaxNode = syntaxNode;
                                    previousCfgNode = cfgNode;
                                    continue;
                                }

                                lhs = context.GetFirstNonMachineIdentifier(binaryExpr.Left, model);
                                lhsFieldSymbol = model.GetSymbolInfo(name as IdentifierNameSyntax).Symbol;
                            }
                            else if (binaryExpr.Left is ElementAccessExpressionSyntax)
                            {
                                var memberAccess = (binaryExpr.Left as ElementAccessExpressionSyntax);
                                if (memberAccess.Expression is IdentifierNameSyntax)
                                {
                                    lhs = memberAccess.Expression as IdentifierNameSyntax;
                                    var lhsType = model.GetTypeInfo(lhs).Type;
                                    if (context.IsTypeAllowedToBeSend(lhsType) ||
                                        context.IsMachineType(lhsType, model))
                                    {
                                        previousSyntaxNode = syntaxNode;
                                        previousCfgNode = cfgNode;
                                        continue;
                                    }
                                }
                                else if (memberAccess.Expression is MemberAccessExpressionSyntax)
                                {
                                    var name = (memberAccess.Expression as MemberAccessExpressionSyntax).Name;
                                    var lhsType = model.GetTypeInfo(name).Type;
                                    if (context.IsTypeAllowedToBeSend(lhsType) ||
                                        context.IsMachineType(lhsType, model))
                                    {
                                        previousSyntaxNode = syntaxNode;
                                        previousCfgNode = cfgNode;
                                        continue;
                                    }

                                    lhs = context.GetFirstNonMachineIdentifier(memberAccess.Expression, model);
                                    lhsFieldSymbol = model.GetSymbolInfo(name as IdentifierNameSyntax).Symbol;
                                }
                            }

                            var leftSymbol = model.GetSymbolInfo(lhs).Symbol;

                            if (binaryExpr.Right is IdentifierNameSyntax ||
                                binaryExpr.Right is MemberAccessExpressionSyntax)
                            {
                                IdentifierNameSyntax rhs = null;
                                if (binaryExpr.Right is IdentifierNameSyntax)
                                {
                                    rhs = binaryExpr.Right as IdentifierNameSyntax;
                                }
                                else if (binaryExpr.Right is MemberAccessExpressionSyntax)
                                {
                                    rhs = context.GetFirstNonMachineIdentifier(binaryExpr.Right, model);
                                }

                                var rightSymbol = model.GetSymbolInfo(rhs).Symbol;
                                dataFlowMap.MapRefToSymbol(rightSymbol, leftSymbol, syntaxNode, cfgNode);
                                if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                {
                                    dataFlowMap.MapRefToSymbol(rightSymbol, lhsFieldSymbol, syntaxNode, cfgNode);
                                }

                                HashSet<ITypeSymbol> objectTypes = null;
                                if (DataFlowAnalysis.ResolveObjectType(out objectTypes, rightSymbol, syntaxNode,
                                    cfgNode, dataFlowMap))
                                {
                                    dataFlowMap.MapObjectTypesToSymbol(objectTypes, leftSymbol, syntaxNode, cfgNode);
                                }
                                else
                                {
                                    dataFlowMap.EraseObjectTypesFromSymbol(leftSymbol, syntaxNode, cfgNode);
                                }
                            }
                            else if (binaryExpr.Right is LiteralExpressionSyntax &&
                                binaryExpr.Right.IsKind(SyntaxKind.NullLiteralExpression))
                            {
                                dataFlowMap.ResetSymbol(leftSymbol, syntaxNode, cfgNode);
                                if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                {
                                    dataFlowMap.ResetSymbol(lhsFieldSymbol, syntaxNode, cfgNode);
                                }
                            }
                            else if (binaryExpr.Right is InvocationExpressionSyntax)
                            {
                                var invocation = binaryExpr.Right as InvocationExpressionSyntax;
                                var summary = MethodSummary.TryGetSummary(invocation, model, context);
                                var reachableSymbols = DataFlowAnalysis.ResolveSideEffectsInCall(invocation,
                                    summary, syntaxNode, cfgNode, model, dataFlowMap);
                                var returnSymbols = DataFlowAnalysis.GetReturnSymbols(invocation,
                                    summary, model);
                                DataFlowAnalysis.CheckForNonMappedFieldSymbol(invocation, cfgNode,
                                    dataFlowMap, model, context);

                                if (returnSymbols.Count == 0)
                                {
                                    dataFlowMap.ResetSymbol(leftSymbol, syntaxNode, cfgNode);
                                    if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                    {
                                        dataFlowMap.ResetSymbol(lhsFieldSymbol, syntaxNode, cfgNode);
                                    }
                                }
                                else if (returnSymbols.Contains(leftSymbol))
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, leftSymbol, syntaxNode, cfgNode, false);
                                    if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                    {
                                        dataFlowMap.MapRefsToSymbol(returnSymbols, lhsFieldSymbol,
                                            syntaxNode, cfgNode, false);
                                    }
                                }
                                else
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, leftSymbol, syntaxNode, cfgNode);
                                    if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                    {
                                        dataFlowMap.MapRefsToSymbol(returnSymbols, lhsFieldSymbol,
                                            syntaxNode, cfgNode);
                                    }
                                }

                                if (lhsFieldSymbol != null && reachableSymbols.Count > 0)
                                {
                                    dataFlowMap.MapReachableFieldsToSymbol(reachableSymbols, lhsFieldSymbol,
                                        syntaxNode, cfgNode);
                                }

                                if (summary != null && summary.ReturnTypeSet.Count > 0)
                                {
                                    dataFlowMap.MapObjectTypesToSymbol(summary.ReturnTypeSet,
                                        leftSymbol, syntaxNode, cfgNode);
                                }
                                else
                                {
                                    dataFlowMap.EraseObjectTypesFromSymbol(leftSymbol, syntaxNode, cfgNode);
                                }
                            }
                            else if (binaryExpr.Right is ObjectCreationExpressionSyntax)
                            {
                                var objCreation = binaryExpr.Right as ObjectCreationExpressionSyntax;
                                var summary = MethodSummary.TryGetSummary(objCreation, model, context);
                                var reachableSymbols = DataFlowAnalysis.ResolveSideEffectsInCall(objCreation,
                                    summary, syntaxNode, cfgNode, model, dataFlowMap);
                                var returnSymbols = DataFlowAnalysis.GetReturnSymbols(objCreation, summary, model);

                                if (returnSymbols.Count == 0)
                                {
                                    dataFlowMap.ResetSymbol(leftSymbol, syntaxNode, cfgNode);
                                    if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                    {
                                        dataFlowMap.ResetSymbol(lhsFieldSymbol, syntaxNode, cfgNode);
                                    }
                                }
                                else if (returnSymbols.Contains(leftSymbol))
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, leftSymbol, syntaxNode, cfgNode, false);
                                    if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                    {
                                        dataFlowMap.MapRefsToSymbol(returnSymbols, lhsFieldSymbol,
                                            syntaxNode, cfgNode, false);
                                    }
                                }
                                else
                                {
                                    dataFlowMap.MapRefsToSymbol(returnSymbols, leftSymbol, syntaxNode, cfgNode);
                                    if (lhsFieldSymbol != null && !lhsFieldSymbol.Equals(leftSymbol))
                                    {
                                        dataFlowMap.MapRefsToSymbol(returnSymbols, lhsFieldSymbol,
                                            syntaxNode, cfgNode);
                                    }
                                }

                                if (lhsFieldSymbol != null && reachableSymbols.Count > 0)
                                {
                                    dataFlowMap.MapReachableFieldsToSymbol(reachableSymbols, lhsFieldSymbol,
                                        syntaxNode, cfgNode);
                                }

                                var typeSymbol = model.GetSymbolInfo(objCreation.Type).Symbol as ITypeSymbol;
                                if (typeSymbol != null)
                                {
                                    dataFlowMap.MapObjectTypesToSymbol(new HashSet<ITypeSymbol> { typeSymbol },
                                        leftSymbol, syntaxNode, cfgNode);
                                }
                                else
                                {
                                    dataFlowMap.EraseObjectTypesFromSymbol(leftSymbol, syntaxNode, cfgNode);
                                }
                            }
                        }
                        else if (expr.Expression is InvocationExpressionSyntax)
                        {
                            var invocation = expr.Expression as InvocationExpressionSyntax;
                            var summary = MethodSummary.TryGetSummary(invocation, model, context);
                            DataFlowAnalysis.ResolveSideEffectsInCall(invocation, summary,
                                syntaxNode, cfgNode, model, dataFlowMap);
                            DataFlowAnalysis.GetReturnSymbols(invocation, summary, model);
                            DataFlowAnalysis.CheckForNonMappedFieldSymbol(invocation, cfgNode,
                                dataFlowMap, model, context);
                        }
                    }
                    else if (ret != null)
                    {
                        HashSet<ISymbol> returnSymbols = null;
                        if (ret.Expression is IdentifierNameSyntax ||
                            ret.Expression is MemberAccessExpressionSyntax)
                        {
                            IdentifierNameSyntax rhs = null;
                            if (ret.Expression is IdentifierNameSyntax)
                            {
                                rhs = ret.Expression as IdentifierNameSyntax;
                            }
                            else if (ret.Expression is MemberAccessExpressionSyntax)
                            {
                                rhs = context.GetFirstNonMachineIdentifier(ret.Expression, model);
                            }

                            var rightSymbol = model.GetSymbolInfo(rhs).Symbol;
                            returnSymbols = new HashSet<ISymbol> { rightSymbol };

                            HashSet<ITypeSymbol> objectTypes = null;
                            if (DataFlowAnalysis.ResolveObjectType(out objectTypes, rightSymbol,
                                syntaxNode, cfgNode, dataFlowMap))
                            {
                                foreach (var objectType in objectTypes)
                                {
                                    cfgNode.Summary.ReturnTypeSet.Add(objectType);
                                }
                            }
                        }
                        else if (ret.Expression is InvocationExpressionSyntax)
                        {
                            var invocation = ret.Expression as InvocationExpressionSyntax;
                            var summary = MethodSummary.TryGetSummary(invocation, model, context);
                            DataFlowAnalysis.ResolveSideEffectsInCall(invocation, summary,
                                syntaxNode, cfgNode, model, dataFlowMap);
                            returnSymbols = DataFlowAnalysis.GetReturnSymbols(invocation, summary, model);

                            if (summary != null)
                            {
                                foreach (var objectType in summary.ReturnTypeSet)
                                {
                                    cfgNode.Summary.ReturnTypeSet.Add(objectType);
                                }
                            }
                        }
                        else if (ret.Expression is ObjectCreationExpressionSyntax)
                        {
                            var objCreation = ret.Expression as ObjectCreationExpressionSyntax;
                            var summary = MethodSummary.TryGetSummary(objCreation, model, context);
                            DataFlowAnalysis.ResolveSideEffectsInCall(objCreation, summary,
                                syntaxNode, cfgNode, model, dataFlowMap);
                            returnSymbols = DataFlowAnalysis.GetReturnSymbols(objCreation, summary, model);

                            var objectType = model.GetSymbolInfo(objCreation.Type).Symbol as ITypeSymbol;
                            if (objectType != null)
                            {
                                cfgNode.Summary.ReturnTypeSet.Add(objectType);
                            }
                        }

                        DataFlowAnalysis.TryCaptureReturnSymbols(returnSymbols, syntaxNode,
                            cfgNode, model, dataFlowMap);
                    }

                    previousSyntaxNode = syntaxNode;
                    previousCfgNode = cfgNode;
                }
            }
            else
            {
                dataFlowMap.Transfer(previousSyntaxNode, previousCfgNode, cfgNode.SyntaxNodes[0], cfgNode);
                previousSyntaxNode = cfgNode.SyntaxNodes[0];
                previousCfgNode = cfgNode;
            }

            foreach (var successor in cfgNode.ISuccessors)
            {
                if (DataFlowAnalysis.ReachedFixpoint(previousSyntaxNode, cfgNode, successor, dataFlowMap))
                {
                    continue;
                }

                DataFlowAnalysis.AnalyseControlFlowGraphNode(successor, cfgNode,
                    previousSyntaxNode, dataFlowMap, model, context);
            }
        }
Пример #2
0
        /// <summary>
        /// Resolves the side effects from the given invocation summary.
        /// </summary>
        /// <param name="call">Call</param>
        /// <param name="summary">MethodSummary</param>
        /// <param name="syntaxNode">SyntaxNode</param>
        /// <param name="cfgNode">ControlFlowGraphNode</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="dataFlowMap">DataFlowMap</param>
        /// <returns>Set of reachable field symbols</returns>
        private static HashSet<ISymbol> ResolveSideEffectsInCall(InvocationExpressionSyntax call, MethodSummary summary,
            SyntaxNode syntaxNode, ControlFlowGraphNode cfgNode, SemanticModel model, DataFlowMap dataFlowMap)
        {
            if (summary == null)
            {
                return new HashSet<ISymbol>();
            }

            HashSet<ISymbol> reachableFields = new HashSet<ISymbol>();
            var sideEffects = summary.GetResolvedSideEffects(call.ArgumentList, model);
            foreach (var sideEffect in sideEffects)
            {
                dataFlowMap.MapRefsToSymbol(sideEffect.Value, sideEffect.Key, syntaxNode, cfgNode);
                reachableFields.Add(sideEffect.Key);
            }

            foreach (var fieldAccess in summary.FieldAccessSet)
            {
                foreach (var access in fieldAccess.Value)
                {
                    if (cfgNode.Summary.FieldAccessSet.ContainsKey(fieldAccess.Key as IFieldSymbol))
                    {
                        cfgNode.Summary.FieldAccessSet[fieldAccess.Key as IFieldSymbol].Add(access);
                    }
                    else
                    {
                        cfgNode.Summary.FieldAccessSet.Add(fieldAccess.Key as IFieldSymbol, new HashSet<SyntaxNode>());
                        cfgNode.Summary.FieldAccessSet[fieldAccess.Key as IFieldSymbol].Add(access);
                    }
                }
            }

            return reachableFields;
        }