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