private VariableState VisitAssignment(VisualBasicSyntaxNode node,
                                              ExpressionSyntax leftExpression,
                                              ExpressionSyntax rightExpression,
                                              ExecutionState state)
        {
            var            leftSymbol = state.GetSymbol(leftExpression);
            MethodBehavior behavior   = null;

            if (leftSymbol != null)
            {
                behavior = leftSymbol.GetMethodBehavior(state.AnalysisContext.Options.AdditionalFiles);
            }

            var variableState = VisitExpression(rightExpression, state);

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitAssignment(node, state, behavior, leftSymbol, variableState);
            }

            if (leftSymbol != null)
            {
                var rightTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(rightExpression).Type;
                if (rightTypeSymbol == null)
                {
                    return(new VariableState(rightExpression, VariableTaint.Unknown));
                }

                var leftTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(leftExpression).Type;
                if (!state.AnalysisContext.SemanticModel.Compilation.ClassifyConversion(rightTypeSymbol, leftTypeSymbol).Exists)
                {
                    return(new VariableState(rightExpression, VariableTaint.Unknown));
                }
            }

            if (behavior != null &&                              //Injection
                behavior.IsInjectableField &&
                variableState.Taint != VariableTaint.Constant && //Skip safe values
                variableState.Taint != VariableTaint.Safe)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.LocaleInjection, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            if (behavior != null &&                            //Known Password API
                behavior.IsPasswordField &&
                variableState.Taint == VariableTaint.Constant) //Only constant
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.LocalePassword, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            //TODO: taint the variable being assigned.

            return(variableState);
        }
        private VariableState CheckIfTaintSource(ExpressionSyntax expression, ExecutionState state)
        {
            var symbol   = state.GetSymbol(expression);
            var behavior = symbol?.GetMethodBehavior(ProjectConfiguration.Behavior);

            if (behavior != null && behavior.PostConditions.TryGetValue(-1, out var taint))
            {
                return(new VariableState(expression, (VariableTaint)taint.Taint));
            }

            return(null);
        }
        private VariableState VisitAssignment(VisualBasicSyntaxNode node,
                                              ExpressionSyntax leftExpression,
                                              ExpressionSyntax rightExpression,
                                              ExecutionState state)
        {
            var            leftSymbol = state.GetSymbol(leftExpression);
            MethodBehavior behavior   = null;

            if (leftSymbol != null)
            {
                behavior = leftSymbol.GetMethodBehavior(ProjectConfiguration.Behavior);
            }

            var variableState = VisitExpression(rightExpression, state);

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitAssignment(node, state, behavior, leftSymbol, variableState);
            }

            //if (leftSymbol != null)
            //{
            //    var rightTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(rightExpression).Type;
            //    if (rightTypeSymbol == null)
            //        return new VariableState(rightExpression, VariableTaint.Unknown);

            //    var leftTypeSymbol = state.AnalysisContext.SemanticModel.GetTypeInfo(leftExpression).Type;
            //    if (!state.AnalysisContext.SemanticModel.Compilation.ClassifyConversion(rightTypeSymbol, leftTypeSymbol).Exists)
            //        return new VariableState(rightExpression, VariableTaint.Unknown);
            //}

            if (variableState.Taint != VariableTaint.Constant &&
                behavior != null &&
                // compare if all required sanitization bits are set
                ((ulong)(variableState.Taint & VariableTaint.Safe) & behavior.InjectableField.RequiredTaintBits) != behavior.InjectableField.RequiredTaintBits &&
                (variableState.Taint & (ProjectConfiguration.AuditMode ? VariableTaint.Tainted | VariableTaint.Unknown : VariableTaint.Tainted)) != 0)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.InjectableField.Locale, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            //TODO: taint the variable being assigned.

            return(variableState);
        }
Пример #4
0
        private VariableState VisitAssignment(VisualBasicSyntaxNode node,
                                              ExpressionSyntax leftExpression,
                                              ExpressionSyntax rightExpression,
                                              ExecutionState state)
        {
            var            symbol   = state.GetSymbol(leftExpression);
            MethodBehavior behavior = BehaviorRepo.GetMethodBehavior(symbol);

            var variableState = VisitExpression(rightExpression, state);

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitAssignment(node, state, behavior, symbol, variableState);
            }

            IdentifierNameSyntax parentIdentifierSyntax = GetParentIdentifier(leftExpression);

            if (parentIdentifierSyntax != null)
            {
                state.MergeValue(ResolveIdentifier(parentIdentifierSyntax.Identifier), variableState);
            }

            if (behavior != null &&                              //Injection
                behavior.IsInjectableField &&
                variableState.Taint != VariableTaint.Constant && //Skip safe values
                variableState.Taint != VariableTaint.Safe)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.LocaleInjection, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            if (behavior != null &&                            //Known Password API
                behavior.IsPasswordField &&
                variableState.Taint == VariableTaint.Constant) //Only constant
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.LocalePassword, "title_assignment");
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            //TODO: taint the variable being assigned.

            return(variableState);
        }
Пример #5
0
        /// <summary>
        /// Identifier name include variable name.
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private VariableState VisitIdentifierName(IdentifierNameSyntax expression, ExecutionState state)
        {
            var value = ResolveIdentifier(expression.Identifier);

            if (state.VariableStates.TryGetValue(value, out var varState))
            {
                return(varState);
            }

            var symbol = state.GetSymbol(expression);

            switch (symbol)
            {
            case null:
                return(new VariableState(expression, VariableTaint.Unknown));

            case IFieldSymbol field:
                if (field.IsConst)
                {
                    return(new VariableState(expression, VariableTaint.Constant));
                }

                if (!field.IsReadOnly)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                switch (field.GetTypeName())     // todo: move out to config of readonly values, that are constant in fact
                {
                case "System.String.Empty":
                case "System.IntPtr.Zero":
                case "System.IO.Path.AltDirectorySeparatorChar":
                case "System.IO.Path.DirectorySeparatorChar":
                case "System.IO.Path.InvalidPathChars":
                case "System.IO.Path.PathSeparator":
                case "System.IO.Path.VolumeSeparatorChar":
                    return(new VariableState(expression, VariableTaint.Constant));
                }

                return(new VariableState(expression, VariableTaint.Unknown));

            case IPropertySymbol prop:
                if (prop.IsVirtual || prop.IsOverride || prop.IsAbstract)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                // TODO: Use public API
                var syntaxNodeProperty = prop.GetMethod.GetType().GetTypeInfo().BaseType.GetTypeInfo().GetDeclaredProperty("BodySyntax");
                if (syntaxNodeProperty == null)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                var syntaxNode = (CSharpSyntaxNode)syntaxNodeProperty.GetValue(prop.GetMethod);
                switch (syntaxNode)
                {
                case BlockSyntax blockSyntax:
                    // Recursion prevention: set the value into the map if we'll get back resolving it while resolving it dependency
                    state.AddNewValue(value, new VariableState(expression, VariableTaint.Unknown));
                    return(VisitBlock(blockSyntax, state));

                case ArrowExpressionClauseSyntax arrowSyntax:
                    // Recursion prevention: set the value into the map if we'll get back resolving it while resolving it dependency
                    state.AddNewValue(value, new VariableState(expression, VariableTaint.Unknown));
                    return(VisitExpression(arrowSyntax.Expression, state));
                }

                return(new VariableState(expression, VariableTaint.Unknown));
            }

            return(new VariableState(expression, VariableTaint.Unknown));
        }
Пример #6
0
        /// <summary>
        /// Logic for each method invocation (including constructor)
        /// The argument list is required because <code>InvocationExpressionSyntax</code> and
        /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="argList"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private VariableState VisitInvocationAndCreation(ExpressionSyntax node,
                                                         ArgumentListSyntax argList,
                                                         ExecutionState state,
                                                         VariableState?initialVariableState = null)
        {
            var symbol = state.GetSymbol(node);

            if (symbol == null)
            {
                return(new VariableState(node, VariableTaint.Unknown));
            }

            var behavior    = symbol.GetMethodBehavior(state.AnalysisContext.Options.AdditionalFiles);
            var returnState = initialVariableState.HasValue && !symbol.IsStatic
                                  ? initialVariableState.Value
                                  : new VariableState(node,
                                                      behavior?.TaintFromArguments?.Any() == true ? VariableTaint.Safe
                                                                                                  : VariableTaint.Unknown);

            for (var i = 0; i < argList?.Arguments.Count; i++)
            {
                var argument      = argList.Arguments[i];
                var argumentState = VisitExpression(argument.Expression, state);

                Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState);

                if (behavior == null)
                {
                    continue;
                }

                //If the API is at risk
                if ((argumentState.Taint == VariableTaint.Tainted ||
                     argumentState.Taint == VariableTaint.Unknown) && //Tainted values
                    //If the current parameter can be injected.
                    Array.Exists(behavior.InjectablesArguments, element => element == i))
                {
                    var newRule    = LocaleUtil.GetDescriptor(behavior.LocaleInjection);
                    var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                    state.AnalysisContext.ReportDiagnostic(diagnostic);
                }
                else if (argumentState.Taint == VariableTaint.Constant && //Hard coded value
                                                                          //If the current parameter is a password
                         Array.Exists(behavior.PasswordArguments, element => element == i))
                {
                    var newRule    = LocaleUtil.GetDescriptor(behavior.LocalePassword);
                    var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                    state.AnalysisContext.ReportDiagnostic(diagnostic);
                }
                else if (Array.Exists(behavior.TaintFromArguments, element => element == i))
                {
                    returnState = returnState.Merge(argumentState);
                }

                //TODO: taint all objects passed as arguments
                //if (argument.Expression is IdentifierNameSyntax identifierNameSyntax)
                //{
                //    var argumentType = state.AnalysisContext.SemanticModel.GetTypeInfo(argument.Expression).Type;
                //    if (argumentType.IsReferenceType &&
                //        argumentType.IsType("System.String")) // string is immutable
                //    {
                //        state.MergeValue(ResolveIdentifier(identifierNameSyntax.Identifier),
                //                         argumentState.Merge(new VariableState(argument, VariableTaint.Unknown)));
                //    }
                //}
            }

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitInvocationAndCreation(node, argList, state);
            }

            return(returnState);
        }
        /// <summary>
        /// Logic for each method invocation (including constructor)
        /// The argument list is required because <code>InvocationExpressionSyntax</code> and
        /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface.
        /// </summary>
        private VariableState VisitInvocationAndCreation(ExpressionSyntax node,
                                                         ArgumentListSyntax argList,
                                                         ExecutionState state,
                                                         VariableTaint?initialTaint        = null,
                                                         VariableState memberVariableState = null)
        {
            var symbol = state.GetSymbol(node);

            if (symbol == null)
            {
                return(new VariableState(node, initialTaint ?? VariableTaint.Unknown));
            }

            var  methodSymbol      = symbol as IMethodSymbol;
            bool isExtensionMethod = methodSymbol?.ReducedFrom != null;
            var  behavior          = symbol.GetMethodBehavior(ProjectConfiguration.Behavior);
            IReadOnlyDictionary <int, PostCondition> postConditions = null;

            if (behavior != null)
            {
                postConditions = GetPostConditions(behavior, isExtensionMethod, argList, state);
            }

            PostCondition returnPostCondition = null;

            postConditions?.TryGetValue(-1, out returnPostCondition);

            VariableState returnState = initialTaint != null && !symbol.IsStatic
                                            ? new VariableState(node, initialTaint.Value)
                                            : new VariableState(node, argList?.Arguments.Count > 0 && behavior != null
                                                                          ? VariableTaint.Unset
                                                                          : VariableTaint.Unknown);

            var argCount       = argList?.Arguments.Count;
            var argumentStates = argCount.HasValue &&
                                 argCount.Value > 0 &&
                                 (postConditions?.Any(c => c.Key != -1 && (c.Value.Taint != 0ul || c.Value.TaintFromArguments.Any())) == true ||
                                  methodSymbol != null && methodSymbol.Parameters.Any(x => x.RefKind != RefKind.None))
                                     ? new VariableState[argCount.Value]
                                     : null;

            for (var i = 0; i < argList?.Arguments.Count; i++)
            {
                var argument      = argList.Arguments[i];
                var argumentState = VisitExpression(argument.GetExpression(), state);
                if (argumentStates != null)
                {
                    argumentStates[i] = argumentState;
                }

#if DEBUG
                Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState);
#endif

                var adjustedArgumentIdx = isExtensionMethod ? i + 1 : i;

                if (behavior != null)
                {
                    if ((argumentState.Taint & (ProjectConfiguration.AuditMode
                                                    ? VariableTaint.Tainted | VariableTaint.Unknown
                                                    : VariableTaint.Tainted)) != 0)
                    {
                        //If the current parameter can be injected.
                        if (behavior.InjectableArguments.TryGetValue(adjustedArgumentIdx, out var injectableArgument) &&
                            (injectableArgument.RequiredTaintBits & (ulong)argumentState.Taint) != injectableArgument.RequiredTaintBits)
                        {
                            var newRule    = LocaleUtil.GetDescriptor(injectableArgument.Locale);
                            var diagnostic = Diagnostic.Create(newRule, argument.GetExpression().GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                            state.AnalysisContext.ReportDiagnostic(diagnostic);
                        }
                    }
                    else if (argumentState.Taint == VariableTaint.Constant)
                    {
                        if (behavior.InjectableArguments.TryGetValue(adjustedArgumentIdx, out var injectableArgument) &&
                            injectableArgument.Not && (injectableArgument.RequiredTaintBits & (ulong)argumentState.Taint) != 0ul)
                        {
                            var newRule    = LocaleUtil.GetDescriptor(injectableArgument.Locale);
                            var diagnostic = Diagnostic.Create(newRule, argument.GetExpression().GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                            state.AnalysisContext.ReportDiagnostic(diagnostic);
                        }
                    }
                }

                var argumentToSearch = adjustedArgumentIdx;
                if (methodSymbol != null &&
                    i >= methodSymbol.Parameters.Length &&
                    methodSymbol.Parameters[methodSymbol.Parameters.Length - 1].IsParams)
                {
                    argumentToSearch = isExtensionMethod ? methodSymbol.Parameters.Length : methodSymbol.Parameters.Length - 1;
                }

                if (returnPostCondition == null ||
                    returnPostCondition.TaintFromArguments.Contains(argumentToSearch))
                {
                    returnState.MergeTaint(argumentState.Taint);
                }

                //TODO: taint all objects passed as arguments
            }

            if (returnPostCondition != null)
            {
                returnState.ApplyTaint(returnPostCondition.Taint);
            }

            if (argumentStates != null)
            {
                for (var i = 0; i < argList.Arguments.Count; i++)
                {
                    var adjustedPostConditionIdx = isExtensionMethod ? i + 1 : i;

                    if (postConditions != null && postConditions.TryGetValue(adjustedPostConditionIdx, out var postCondition))
                    {
                        foreach (var argIdx in postCondition.TaintFromArguments)
                        {
                            var adjustedArgumentIdx = isExtensionMethod ? argIdx + 1 : argIdx;
                            argumentStates[adjustedPostConditionIdx].MergeTaint(argumentStates[adjustedArgumentIdx].Taint);
                        }

                        argumentStates[adjustedPostConditionIdx].ApplyTaint(postCondition.Taint);
                    }
                    else if (methodSymbol != null)
                    {
                        if (i >= methodSymbol.Parameters.Length)
                        {
                            if (!methodSymbol.Parameters[methodSymbol.Parameters.Length - 1].IsParams)
                            {
                                throw new IndexOutOfRangeException();
                            }
                        }
                        else if (methodSymbol.Parameters[i].RefKind != RefKind.None)
                        {
                            argumentStates[i].MergeTaint(returnState.Taint);
                        }
                    }
                }
            }

            if (memberVariableState != null &&
                methodSymbol != null &&
                methodSymbol.ReturnsVoid &&
                !methodSymbol.IsStatic &&
                methodSymbol.Parameters.All(x => x.RefKind == RefKind.None))
            {
                memberVariableState.MergeTaint(returnState.Taint);
            }

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitInvocationAndCreation(node, argList, state);
            }

            return(returnState);
        }
        /// <summary>
        /// Logic for each method invocation (including constructor)
        /// The argument list is required because <code>InvocationExpressionSyntax</code> and
        /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="argList"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private VariableState VisitInvocationAndCreation(ExpressionSyntax node,
                                                         ArgumentListSyntax argList,
                                                         ExecutionState state)
        {
            var            symbol   = state.GetSymbol(node);
            MethodBehavior behavior = BehaviorRepo.GetMethodBehavior(symbol);

            int i = 0;

            if (argList == null)
            {
                return(new VariableState(node, VariableTaint.Unknown));
            }

            var returnState = new VariableState(node, VariableTaint.Safe);

            foreach (var argument in argList.Arguments)
            {
                var argumentState = VisitExpression(argument.Expression, state);

                if (symbol != null)
                {
                    Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState);
                }

                if (behavior != null)
                {
                    //If the API is at risk
                    if ((argumentState.Taint == VariableTaint.Tainted ||
                         argumentState.Taint == VariableTaint.Unknown) && //Tainted values
                        //If the current parameter can be injected.
                        Array.Exists(behavior.InjectablesArguments, element => element == i))
                    {
                        var newRule    = LocaleUtil.GetDescriptor(behavior.LocaleInjection);
                        var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                        state.AnalysisContext.ReportDiagnostic(diagnostic);
                    }
                    else if (argumentState.Taint == VariableTaint.Constant && //Hard coded value
                                                                              //If the current parameter is a password
                             Array.Exists(behavior.PasswordArguments, element => element == i))
                    {
                        var newRule    = LocaleUtil.GetDescriptor(behavior.LocalePassword);
                        var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                        state.AnalysisContext.ReportDiagnostic(diagnostic);
                    }
                    else if (Array.Exists(behavior.TaintFromArguments, element => element == i))
                    {
                        returnState = returnState.Merge(argumentState);
                    }
                }

                //TODO: tainted all object passed in argument

                i++;
            }

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitInvocationAndCreation(node, argList, state);
            }

            var hasTaintFromArguments = behavior?.TaintFromArguments?.Length > 0;

            return(hasTaintFromArguments ? returnState : new VariableState(node, VariableTaint.Unknown));
        }
Пример #9
0
        /// <summary>
        /// Identifier name include variable name.
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private VariableState VisitIdentifierName(IdentifierNameSyntax expression, ExecutionState state)
        {
            var value = ResolveIdentifier(expression.Identifier);

            if (state.VariableStates.TryGetValue(value, out var varState))
            {
                return(varState);
            }

            var symbol = state.GetSymbol(expression);

            if (symbol == null)
            {
                return(new VariableState(expression, VariableTaint.Unknown));
            }

            if (symbol is IFieldSymbol field)
            {
                if (field.IsConst)
                {
                    return(new VariableState(expression, VariableTaint.Constant));
                }

                if (!field.IsReadOnly)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                switch (field.ToDisplayString(SymbolExtensions.SymbolDisplayFormat))
                {
                case "System.String.Empty":
                case "System.IntPtr.Zero":
                    return(new VariableState(expression, VariableTaint.Constant));
                }

                return(new VariableState(expression, VariableTaint.Unknown));
            }

            if (symbol is IPropertySymbol prop)
            {
                if (prop.IsVirtual || prop.IsOverride || prop.IsAbstract)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                // TODO: Use public API
                var syntaxNodeProperty = prop.GetMethod.GetType().GetTypeInfo().BaseType.GetTypeInfo().GetDeclaredProperty("BodySyntax");
                if (syntaxNodeProperty == null)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                var syntaxNode = (CSharpSyntaxNode)syntaxNodeProperty.GetValue(prop.GetMethod);
                if (syntaxNode is BlockSyntax blockSyntax)
                {
                    // Recursion prevention: set the value into the map if we'll get back resolving it while resolving it dependency
                    state.AddNewValue(value, new VariableState(expression, VariableTaint.Unknown));
                    return(VisitBlock(blockSyntax, state));
                }

                if (syntaxNode is ArrowExpressionClauseSyntax arrowSyntax)
                {
                    // Recursion prevention: set the value into the map if we'll get back resolving it while resolving it dependency
                    state.AddNewValue(value, new VariableState(expression, VariableTaint.Unknown));
                    return(VisitExpression(arrowSyntax.Expression, state));
                }

                return(new VariableState(expression, VariableTaint.Unknown));
            }

            return(new VariableState(expression, VariableTaint.Unknown));
        }
        private VariableState ResolveVariableState(ExpressionSyntax expression, ExecutionState state)
        {
            var varState = GetVariableState(expression, state);

            if (varState != null)
            {
                return(varState);
            }

            var symbol = state.GetSymbol(expression);

            switch (symbol)
            {
            case null:
                return(new VariableState(expression, VariableTaint.Unknown));

            case IFieldSymbol field:
                if (field.IsConst)
                {
                    return(new VariableState(expression, VariableTaint.Constant));
                }

                if (!field.IsReadOnly)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                var contantFields = ConfigurationManager.Instance.GetProjectConfiguration(state.AnalysisContext.Options.AdditionalFiles)
                                    .ConstantFields;

                if (contantFields.Contains(field.GetTypeName()))
                {
                    return(new VariableState(expression, VariableTaint.Constant));
                }

                return(new VariableState(expression, VariableTaint.Unknown));

            case IPropertySymbol prop:
                if (prop.IsVirtual || prop.IsOverride || prop.IsAbstract)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                // TODO: Use public API
                var syntaxNodeProperty = prop.GetMethod.GetType().GetTypeInfo().BaseType.GetTypeInfo().GetDeclaredProperty("BodySyntax");
                if (syntaxNodeProperty == null)
                {
                    return(new VariableState(expression, VariableTaint.Unknown));
                }

                var syntaxNode = (CSharpSyntaxNode)syntaxNodeProperty.GetValue(prop.GetMethod);
                switch (syntaxNode)
                {
                case BlockSyntax blockSyntax:
                    // Recursion prevention: set the value into the map if we'll get back resolving it while resolving it dependency
                    MergeVariableState(expression, new VariableState(expression, VariableTaint.Unknown), state);
                    return(VisitBlock(blockSyntax, state));

                case ArrowExpressionClauseSyntax arrowSyntax:
                    // Recursion prevention: set the value into the map if we'll get back resolving it while resolving it dependency
                    MergeVariableState(expression, new VariableState(expression, VariableTaint.Unknown), state);
                    return(VisitExpression(arrowSyntax.Expression, state));
                }

                return(new VariableState(expression, VariableTaint.Unknown));
            }

            return(new VariableState(expression, VariableTaint.Unknown));
        }
        /// <summary>
        /// Logic for each method invocation (including constructor)
        /// The argument list is required because <code>InvocationExpressionSyntax</code> and
        /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="argList"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private VariableState VisitInvocationAndCreation(ExpressionSyntax node,
                                                         ArgumentListSyntax argList,
                                                         ExecutionState state,
                                                         VariableState initialVariableState = null)
        {
            var symbol = state.GetSymbol(node);

            if (symbol == null)
            {
                return(new VariableState(node, VariableTaint.Unknown));
            }

            VariableState returnState;
            var           behavior = symbol.GetMethodBehavior(state.AnalysisContext.Options.AdditionalFiles);

            if (behavior?.TaintFromArguments.Length == 1 && behavior.TaintFromArguments[0] == -1)
            {
                returnState = new VariableState(node, VariableTaint.Safe);
            }
            else
            {
                returnState = initialVariableState != null && !symbol.IsStatic
                                  ? initialVariableState
                                  : new VariableState(node,
                                                      behavior?.TaintFromArguments?.Any() == true
                                                          ? VariableTaint.Safe
                                                          : VariableTaint.Unknown);
            }

            bool isExtensionMethod = (symbol as IMethodSymbol)?.ReducedFrom != null;

            for (var i = 0; i < argList?.Arguments.Count; i++)
            {
                var argument      = argList.Arguments[i];
                var argumentState = VisitExpression(argument.GetExpression(), state);

                Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState);

                if (behavior == null)
                {
                    continue;
                }

                //If the API is at risk
                if ((argumentState.Taint == VariableTaint.Tainted ||
                     argumentState.Taint == VariableTaint.Unknown) && //Tainted values
                    //If the current parameter can be injected.
                    Array.Exists(behavior.InjectablesArguments, element => element == (isExtensionMethod ? i + 1 : i)))
                {
                    var newRule    = LocaleUtil.GetDescriptor(behavior.LocaleInjection);
                    var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                    state.AnalysisContext.ReportDiagnostic(diagnostic);
                }
                else if (argumentState.Taint == VariableTaint.Constant && //Hard coded value
                                                                          //If the current parameter is a password
                         Array.Exists(behavior.PasswordArguments, element => element == (isExtensionMethod ? i + 1 : i)))
                {
                    var newRule    = LocaleUtil.GetDescriptor(behavior.LocalePassword);
                    var diagnostic = Diagnostic.Create(newRule, node.GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                    state.AnalysisContext.ReportDiagnostic(diagnostic);
                }
                else if (Array.Exists(behavior.TaintFromArguments, element => element == (isExtensionMethod ? i + 1 : i)))
                {
                    returnState.Merge(argumentState);
                }

                //TODO: taint all objects passed as arguments
            }

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitInvocationAndCreation(node, argList, state);
            }

            return(returnState);
        }