// So we can treat the array as tainted when it's passed to other object constructors. // See HttpRequest_Form_Array_List_Diagnostic and HttpRequest_Form_List_Diagnostic tests. public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) { HashSet <SymbolAccess> sourceOrigins = null; TaintedDataAbstractValue baseAbstractValue = base.VisitArrayInitializer(operation, argument); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { sourceOrigins = new HashSet <SymbolAccess>(baseAbstractValue.SourceOrigins); } IEnumerable <TaintedDataAbstractValue> taintedAbstractValues = operation.ElementValues .Select <IOperation, TaintedDataAbstractValue>(e => this.GetCachedAbstractValue(e)) .Where(v => v.Kind == TaintedDataAbstractValueKind.Tainted); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { taintedAbstractValues = taintedAbstractValues.Concat(baseAbstractValue); } if (taintedAbstractValues.Any()) { return(TaintedDataAbstractValue.MergeTainted(taintedAbstractValues)); } else { return(baseAbstractValue); } }
protected override TaintedDataAbstractValue VisitAssignmentOperation(IAssignmentOperation operation, object argument) { TaintedDataAbstractValue taintedDataAbstractValue = base.VisitAssignmentOperation(operation, argument); ProcessAssignmentOperation(operation); return(taintedDataAbstractValue); }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue baseVisit = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } if (this.IsSanitizingMethod(method)) { return(TaintedDataAbstractValue.NotTainted); } else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod(method)) { return(TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol)); } return(baseVisit); }
/// <summary> /// Determines if tainted data is entering a sink as a method call or constructor argument, and if so, flags it. /// </summary> /// <param name="targetMethod">Method being invoked.</param> /// <param name="taintedArguments">Arguments with tainted data to the method.</param> /// <param name="originalOperation">Original IOperation for the method/constructor invocation.</param> private void ProcessTaintedDataEnteringInvocationOrCreation( IMethodSymbol targetMethod, IEnumerable <IArgumentOperation> taintedArguments, IOperation originalOperation) { if (this.IsMethodArgumentASink(targetMethod, taintedArguments, out HashSet <SinkKind> sinkKinds)) { foreach (IArgumentOperation taintedArgument in taintedArguments) { TaintedDataAbstractValue abstractValue = this.GetCachedAbstractValue(taintedArgument); this.TrackTaintedDataEnteringSink(targetMethod, originalOperation.Syntax.GetLocation(), sinkKinds, abstractValue.SourceOrigins); } } if (this.TryGetInterproceduralAnalysisResult(originalOperation, out TaintedDataAnalysisResult subResult) && !subResult.TaintedDataSourceSinks.IsEmpty) { foreach (TaintedDataSourceSink sourceSink in subResult.TaintedDataSourceSinks) { if (!this.TaintedSourcesBySink.TryGetValue( sourceSink.Sink, out (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SymbolAccess> .Builder SourceOrigins)data)) { data = (ImmutableHashSet.CreateBuilder <SinkKind>(), ImmutableHashSet.CreateBuilder <SymbolAccess>()); this.TaintedSourcesBySink.Add(sourceSink.Sink, data); } data.SinkKinds.UnionWith(sourceSink.SinkKinds); data.SourceOrigins.UnionWith(sourceSink.SourceOrigins); } } }
protected override TaintedDataAbstractValue GetDefaultValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity) { if (this.DataFlowAnalysisContext.SourceInfos.IsSourceParameter(parameter, WellKnownTypeProvider)) { // Location of the parameter, so we can track where the tainted data appears in code. // The parameter itself may not have any DeclaringSyntaxReferences, e.g. 'value' inside property setters. SyntaxNode parameterSyntaxNode; if (!parameter.DeclaringSyntaxReferences.IsEmpty) { parameterSyntaxNode = parameter.DeclaringSyntaxReferences[0].GetSyntax(); } else if (!parameter.ContainingSymbol.DeclaringSyntaxReferences.IsEmpty) { parameterSyntaxNode = parameter.ContainingSymbol.DeclaringSyntaxReferences[0].GetSyntax(); } else { // Unless there are others, the only case we have for parameters being tainted data sources is inside // ASP.NET Core MVC controller action methods (see WebInputSources.cs), so those parameters should // always be declared somewhere. Debug.Fail("Can we have a tainted data parameter with no syntax references?"); return(ValueDomain.UnknownOrMayBeValue); } return(TaintedDataAbstractValue.CreateTainted(parameter, parameterSyntaxNode, this.OwningSymbol)); } return(ValueDomain.UnknownOrMayBeValue); }
private void SetTaintedForEntity(IOperation operation, TaintedDataAbstractValue value) { if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) { this.CurrentAnalysisData.SetAbstractValue(analysisEntity, value); } }
protected override TaintedDataAbstractValue ComputeAnalysisValueForReferenceOperation(IOperation operation, TaintedDataAbstractValue defaultValue) { // If the property/field reference itself is a tainted data source if (operation is IPropertyReferenceOperation propertyReferenceOperation && this.DataFlowAnalysisContext.SourceInfos.IsSourceProperty(propertyReferenceOperation.Property)) { return(TaintedDataAbstractValue.CreateTainted(propertyReferenceOperation.Member, propertyReferenceOperation.Syntax, this.OwningSymbol)); }
protected override TaintedDataAbstractValue GetDefaultValueForParameterOnEntry(IParameterSymbol parameter, AnalysisEntity analysisEntity) { if (this.DataFlowAnalysisContext.SourceInfos.IsSourceParameter(parameter, WellKnownTypeProvider)) { return(TaintedDataAbstractValue.CreateTainted(parameter, parameter.DeclaringSyntaxReferences[0].GetSyntax(), this.OwningSymbol)); } return(ValueDomain.UnknownOrMayBeValue); }
protected override void SetAbstractValue(AnalysisEntity analysisEntity, TaintedDataAbstractValue value) { if (value.Kind == TaintedDataAbstractValueKind.Tainted || this.CurrentAnalysisData.CoreAnalysisData.ContainsKey(analysisEntity)) { // Only track tainted data, or sanitized data. // If it's new, and it's untainted, we don't care. SetAbstractValueCore(CurrentAnalysisData, analysisEntity, value); } }
// So we can hook into constructor calls. public override TaintedDataAbstractValue VisitObjectCreation(IObjectCreationOperation operation, object argument) { TaintedDataAbstractValue baseValue = base.VisitObjectCreation(operation, argument); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(operation.Arguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(operation.Constructor, taintedArguments, operation); } return(baseValue); }
public override TaintedDataAbstractValue VisitInvocation_LocalFunction(IMethodSymbol localFunction, ImmutableArray <IArgumentOperation> visitedArguments, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue baseValue = base.VisitInvocation_LocalFunction(localFunction, visitedArguments, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(localFunction, taintedArguments, originalOperation); } return(baseValue); }
private void ProcessAssignmentOperation(IAssignmentOperation assignmentOperation) { TaintedDataAbstractValue assignmentValueAbstractValue = this.GetCachedAbstractValue(assignmentOperation.Value); if (assignmentOperation.Target != null && assignmentValueAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted && assignmentOperation.Target is IPropertyReferenceOperation propertyReferenceOperation && this.IsPropertyASink(propertyReferenceOperation, out HashSet <SinkKind> sinkKinds)) { this.TrackTaintedDataEnteringSink( propertyReferenceOperation.Member, propertyReferenceOperation.Syntax.GetLocation(), sinkKinds, assignmentValueAbstractValue.SourceOrigins); } }
public override int Compare(TaintedDataAbstractValue oldValue, TaintedDataAbstractValue newValue, bool assertMonotonicity) { // The newly computed abstract values for each basic block // must be always greater or equal than the previous value // to ensure termination. // NotTainted < Tainted if (oldValue.Kind == TaintedDataAbstractValueKind.Tainted && newValue.Kind == TaintedDataAbstractValueKind.Tainted) { return(SetAbstractDomain <SymbolAccess> .Default.Compare(oldValue.SourceOrigins, newValue.SourceOrigins)); } else { return(oldValue.Kind.CompareTo(newValue.Kind)); } }
protected override TaintedDataAbstractValue ComputeAnalysisValueForReferenceOperation(IOperation operation, TaintedDataAbstractValue defaultValue) { // If the property reference itself is a tainted data source if (operation is IPropertyReferenceOperation propertyReferenceOperation && this.DataFlowAnalysisContext.SourceInfos.IsSourceProperty(propertyReferenceOperation.Property)) { return(TaintedDataAbstractValue.CreateTainted(propertyReferenceOperation.Member, propertyReferenceOperation.Syntax, this.OwningSymbol)); } if (AnalysisEntityFactory.TryCreate(operation, out AnalysisEntity analysisEntity)) { return(this.CurrentAnalysisData.TryGetValue(analysisEntity, out TaintedDataAbstractValue value) ? value : defaultValue); } return(defaultValue); }
// So we can treat the array as tainted when it's passed to other object constructors. // See HttpRequest_Form_Array_List_Diagnostic and HttpRequest_Form_List_Diagnostic tests. public override TaintedDataAbstractValue VisitArrayInitializer(IArrayInitializerOperation operation, object argument) { HashSet <SymbolAccess> sourceOrigins = null; TaintedDataAbstractValue baseAbstractValue = base.VisitArrayInitializer(operation, argument); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { sourceOrigins = new HashSet <SymbolAccess>(baseAbstractValue.SourceOrigins); } IEnumerable <TaintedDataAbstractValue> taintedAbstractValues = operation.ElementValues .Select <IOperation, TaintedDataAbstractValue>(e => this.GetCachedAbstractValue(e)) .Where(v => v.Kind == TaintedDataAbstractValueKind.Tainted); if (baseAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted) { taintedAbstractValues = taintedAbstractValues.Concat(baseAbstractValue); } TaintedDataAbstractValue result = null; if (taintedAbstractValues.Any()) { result = TaintedDataAbstractValue.MergeTainted(taintedAbstractValues); } IArrayCreationOperation arrayCreationOperation = operation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation); if (arrayCreationOperation?.Type is IArrayTypeSymbol arrayTypeSymbol && this.DataFlowAnalysisContext.SourceInfos.IsSourceConstantArrayOfType(arrayTypeSymbol) && operation.ElementValues.All(s => GetValueContentAbstractValue(s).IsLiteralState)) { TaintedDataAbstractValue taintedDataAbstractValue = TaintedDataAbstractValue.CreateTainted(arrayTypeSymbol, arrayCreationOperation.Syntax, this.OwningSymbol); result = result == null ? taintedDataAbstractValue : TaintedDataAbstractValue.MergeTainted(result, taintedDataAbstractValue); } if (result != null) { return(result); } else { return(baseAbstractValue); } }
public override TaintedDataAbstractValue VisitConversion(IConversionOperation operation, object?argument) { TaintedDataAbstractValue operandValue = Visit(operation.Operand, argument); if (!operation.Conversion.Exists) { return(ValueDomain.UnknownOrMayBeValue); } if (operation.Conversion.IsImplicit) { return(operandValue); } // Conservative for error code and user defined operator. return(!operation.Conversion.IsUserDefined ? operandValue : ValueDomain.UnknownOrMayBeValue); }
/// <summary> /// Computes abstract value for out or ref arguments when not performing interprocedural analysis. /// </summary> /// <param name="analysisEntity">Analysis entity.</param> /// <param name="operation">IArgumentOperation.</param> /// <param name="defaultValue">Default TaintedDataAbstractValue if we don't need to override.</param> /// <returns>Abstract value of the output parameter.</returns> protected override TaintedDataAbstractValue ComputeAnalysisValueForEscapedRefOrOutArgument( AnalysisEntity analysisEntity, IArgumentOperation operation, TaintedDataAbstractValue defaultValue) { // Note this method is only called when interprocedural DFA is *NOT* performed. if (operation.Parent is IInvocationOperation invocationOperation) { Debug.Assert(!this.TryGetInterproceduralAnalysisResult(invocationOperation, out TaintedDataAnalysisResult _)); // Treat ref or out arguments as the same as the invocation operation. TaintedDataAbstractValue returnValueAbstractValue = this.GetCachedAbstractValue(invocationOperation); return(returnValueAbstractValue); } else { return(defaultValue); } }
public override TaintedDataAbstractValue DefaultVisit(IOperation operation, object argument) { // This handles most cases of tainted data flowing from child operations to parent operations. // Examples: // - tainted input parameters to method calls returns, and out/ref parameters, tainted (assuming no interprocedural) // - adding a tainted value to something makes the result tainted // - instantiating an object with tainted data makes the new object tainted List <TaintedDataAbstractValue> taintedValues = null; foreach (IOperation childOperation in operation.Children) { TaintedDataAbstractValue childValue = Visit(childOperation, argument); if (childValue.Kind == TaintedDataAbstractValueKind.Tainted) { if (taintedValues == null) { taintedValues = new List <TaintedDataAbstractValue>(); } taintedValues.Add(childValue); } } if (taintedValues != null) { if (taintedValues.Count == 1) { return(taintedValues[0]); } else { return(TaintedDataAbstractValue.MergeTainted(taintedValues)); } } else { return(ValueDomain.UnknownOrMayBeValue); } }
private void ProcessAssignmentOperation(IAssignmentOperation assignmentOperation) { TaintedDataAbstractValue assignmentValueAbstractValue = this.GetCachedAbstractValue(assignmentOperation.Value); if (assignmentOperation.Target != null && assignmentValueAbstractValue.Kind == TaintedDataAbstractValueKind.Tainted && assignmentOperation.Target is IPropertyReferenceOperation propertyReferenceOperation) { if (this.IsPropertyASink(propertyReferenceOperation, out HashSet <SinkKind>?sinkKinds)) { this.TrackTaintedDataEnteringSink( propertyReferenceOperation.Member, propertyReferenceOperation.Syntax.GetLocation(), sinkKinds, assignmentValueAbstractValue.SourceOrigins); } if (this.DataFlowAnalysisContext.SourceInfos.IsSourceTransferProperty(propertyReferenceOperation)) { SetTaintedForEntity(propertyReferenceOperation.Instance, assignmentValueAbstractValue); } } }
public override TaintedDataAbstractValue Merge(TaintedDataAbstractValue value1, TaintedDataAbstractValue value2) { // N T // +---- // N | N T // T | T T if (value1 == null) { return(value2); } else if (value2 == null) { return(value1); } if (value1.Kind == TaintedDataAbstractValueKind.Tainted && value2.Kind == TaintedDataAbstractValueKind.Tainted) { // If both are tainted, we need to merge their origins. return(TaintedDataAbstractValue.MergeTainted(value1, value2)); } return(value1.Kind > value2.Kind ? value1 : value2); }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue baseVisit = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } PooledHashSet <IsInvocationTaintedWithPointsToAnalysis> evaluateWithPointsToAnalysis = null; PooledHashSet <IsInvocationTaintedWithValueContentAnalysis> evaluateWithValueContentAnalysis = null; try { if (this.IsSanitizingMethod(method)) { return(TaintedDataAbstractValue.NotTainted); } else if (visitedInstance != null && this.IsSanitizingInstanceMethod(method)) { if (AnalysisEntityFactory.TryCreate(visitedInstance, out AnalysisEntity analysisEntity)) { this.CurrentAnalysisData.SetAbstractValue(analysisEntity, TaintedDataAbstractValue.NotTainted); } return(TaintedDataAbstractValue.NotTainted); } else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, out evaluateWithPointsToAnalysis, out evaluateWithValueContentAnalysis)) { ImmutableArray <IArgumentOperation> argumentOperation = (originalOperation as IInvocationOperation).Arguments; IEnumerable <PointsToAbstractValue> pointsToAnalysisResult = argumentOperation.Select(o => GetPointsToAbstractValue(o.Value)); IEnumerable <ValueContentAbstractValue> valueContentAnalysisResult = argumentOperation.Select(o => GetValueContentAbstractValue(o.Value)); if ((evaluateWithPointsToAnalysis != null && evaluateWithPointsToAnalysis.Any(o => o(pointsToAnalysisResult))) || (evaluateWithValueContentAnalysis != null && evaluateWithValueContentAnalysis.Any(o => o(pointsToAnalysisResult, valueContentAnalysisResult)))) { return(TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol)); } return(TaintedDataAbstractValue.NotTainted); } } finally { if (evaluateWithPointsToAnalysis != null) { evaluateWithPointsToAnalysis.Free(); } if (evaluateWithValueContentAnalysis != null) { evaluateWithValueContentAnalysis.Free(); } } return(baseVisit); }
protected override void SetAbstractValue(AnalysisEntity analysisEntity, TaintedDataAbstractValue value) { SetAbstractValueCore(CurrentAnalysisData, analysisEntity, value); }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue result = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } PooledHashSet <string> taintedTargets = null; PooledHashSet <(string, string)> taintedParameterPairs = null; try { if (this.IsSanitizingMethod(method)) { result = TaintedDataAbstractValue.NotTainted; } else if (visitedInstance != null && this.IsSanitizingInstanceMethod(method)) { result = TaintedDataAbstractValue.NotTainted; SetTaintedForEntity(visitedInstance, result); } else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, visitedArguments, new Lazy <PointsToAnalysisResult>(() => DataFlowAnalysisContext.PointsToAnalysisResultOpt), new Lazy <ValueContentAnalysisResult>(() => DataFlowAnalysisContext.ValueContentAnalysisResultOpt), out taintedTargets)) { foreach (string taintedTarget in taintedTargets) { if (taintedTarget != TaintedTargetValue.Return) { IArgumentOperation argumentOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == taintedTarget); if (argumentOperation != null) { this.CacheAbstractValue(argumentOperation, TaintedDataAbstractValue.CreateTainted(argumentOperation.Parameter, argumentOperation.Syntax, method)); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } else { result = TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol); } } } if (this.DataFlowAnalysisContext.SourceInfos.IsSourceTransferMethod( method, visitedArguments, visitedArguments .Where(s => this.GetCachedAbstractValue(s).Kind == TaintedDataAbstractValueKind.Tainted) .Select(s => s.Parameter.Name) .ToImmutableArray(), out taintedParameterPairs)) { foreach ((string ifTaintedParameter, string thenTaintedTarget) in taintedParameterPairs) { IArgumentOperation thenTaintedTargetOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == thenTaintedTarget); if (thenTaintedTargetOperation != null) { SetTaintedForEntity( thenTaintedTargetOperation, this.GetCachedAbstractValue( visitedArguments.FirstOrDefault(o => o.Parameter.Name == ifTaintedParameter))); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } } } finally { taintedTargets?.Free(); taintedParameterPairs?.Free(); } return(result); }
private static void SetAbstractValueCore(TaintedDataAnalysisData taintedAnalysisData, AnalysisEntity analysisEntity, TaintedDataAbstractValue value) => taintedAnalysisData.SetAbstractValue(analysisEntity, value);
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation?visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue result = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } PooledHashSet <string>? taintedTargets = null; PooledHashSet <(string, string)>?taintedParameterPairs = null; PooledHashSet <(string, string)>?sanitizedParameterPairs = null; PooledHashSet <string>? taintedParameterNamesCached = null; try { IEnumerable <string> GetTaintedParameterNames() { IEnumerable <string> taintedParameterNames = visitedArguments .Where(s => this.GetCachedAbstractValue(s).Kind == TaintedDataAbstractValueKind.Tainted) .Select(s => s.Parameter.Name); if (visitedInstance != null && this.GetCachedAbstractValue(visitedInstance).Kind == TaintedDataAbstractValueKind.Tainted) { taintedParameterNames = taintedParameterNames.Concat(TaintedTargetValue.This); } return(taintedParameterNames); } taintedParameterNamesCached = PooledHashSet <string> .GetInstance(); taintedParameterNamesCached.UnionWith(GetTaintedParameterNames()); if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, visitedArguments, new Lazy <PointsToAnalysisResult?>(() => DataFlowAnalysisContext.PointsToAnalysisResult), new Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)>(() => (DataFlowAnalysisContext.PointsToAnalysisResult, DataFlowAnalysisContext.ValueContentAnalysisResult)), out taintedTargets)) { bool rebuildTaintedParameterNames = false; foreach (string taintedTarget in taintedTargets) { if (taintedTarget != TaintedTargetValue.Return) { IArgumentOperation argumentOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == taintedTarget); if (argumentOperation != null) { rebuildTaintedParameterNames = true; this.CacheAbstractValue(argumentOperation, TaintedDataAbstractValue.CreateTainted(argumentOperation.Parameter, argumentOperation.Syntax, method)); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } else { result = TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol); } } if (rebuildTaintedParameterNames) { taintedParameterNamesCached.Clear(); taintedParameterNamesCached.UnionWith(GetTaintedParameterNames()); } } if (this.DataFlowAnalysisContext.SourceInfos.IsSourceTransferMethod( method, visitedArguments, taintedParameterNamesCached, out taintedParameterPairs)) { foreach ((string ifTaintedParameter, string thenTaintedTarget) in taintedParameterPairs) { IOperation thenTaintedTargetOperation = visitedInstance != null && thenTaintedTarget == TaintedTargetValue.This ? visitedInstance : visitedArguments.FirstOrDefault(o => o.Parameter.Name == thenTaintedTarget); if (thenTaintedTargetOperation != null) { SetTaintedForEntity( thenTaintedTargetOperation, this.GetCachedAbstractValue( visitedInstance != null && ifTaintedParameter == TaintedTargetValue.This ? visitedInstance : visitedArguments.FirstOrDefault(o => o.Parameter.Name == ifTaintedParameter))); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } } if (visitedInstance != null && this.IsSanitizingInstanceMethod(method)) { SetTaintedForEntity(visitedInstance, TaintedDataAbstractValue.NotTainted); } if (this.IsSanitizingMethod( method, visitedArguments, taintedParameterNamesCached, out sanitizedParameterPairs)) { if (sanitizedParameterPairs.Count == 0) { // it was either sanitizing constructor or // the short form or registering sanitizer method by just the name result = TaintedDataAbstractValue.NotTainted; } else { foreach ((string ifTaintedParameter, string thenSanitizedTarget) in sanitizedParameterPairs) { if (thenSanitizedTarget == TaintedTargetValue.Return) { result = TaintedDataAbstractValue.NotTainted; continue; } IArgumentOperation thenSanitizedTargetOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == thenSanitizedTarget); if (thenSanitizedTargetOperation != null) { SetTaintedForEntity(thenSanitizedTargetOperation, TaintedDataAbstractValue.NotTainted); } else { Debug.Fail("Are the tainted data sanitizers misconfigured?"); } } } } } finally { taintedTargets?.Dispose(); taintedParameterPairs?.Dispose(); sanitizedParameterPairs?.Dispose(); taintedParameterNamesCached?.Dispose(); } return(result); }