Exemplo n.º 1
0
            // 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);
            }
Exemplo n.º 3
0
            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);
     }
 }
Exemplo n.º 7
0
 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));
     }
Exemplo n.º 8
0
            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);
            }
Exemplo n.º 22
0
 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);
            }