public void LambdaFlow_04()
        {
            string source = @"
struct C
{
    void M(System.Action d1, System.Action<bool, bool> d2)
/*<bind>*/{
        d1 = () =>
        {
            d2 = (bool result1, bool input1) =>
            {
                result1 = input1;
            
            };
        };

        void local(bool result2, bool input2) => result2 = input2;
    }/*</bind>*/
}
";

            var compilation   = CreateCompilation(source);
            var tree          = compilation.SyntaxTrees.Single();
            var semanticModel = compilation.GetSemanticModel(tree);
            var graphM        = ControlFlowGraph.Create((IMethodBodyOperation)semanticModel.GetOperation(tree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>().Single()));

            Assert.NotNull(graphM);
            Assert.Null(graphM.Parent);

            IFlowAnonymousFunctionOperation lambdaD1 = getLambda(graphM);

            Assert.Throws <ArgumentNullException>(() => graphM.GetLocalFunctionControlFlowGraph(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetLocalFunctionControlFlowGraph(lambdaD1.Symbol));
            Assert.Throws <ArgumentNullException>(() => graphM.GetLocalFunctionControlFlowGraphInScope(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetLocalFunctionControlFlowGraphInScope(lambdaD1.Symbol));

            var graphD1 = graphM.GetAnonymousFunctionControlFlowGraph(lambdaD1);

            Assert.NotNull(graphD1);
            Assert.Same(graphM, graphD1.Parent);
            var graphD1_FromExtension = graphM.GetAnonymousFunctionControlFlowGraphInScope(lambdaD1);

            Assert.Same(graphD1, graphD1_FromExtension);

            IFlowAnonymousFunctionOperation lambdaD2 = getLambda(graphD1);
            var graphD2 = graphD1.GetAnonymousFunctionControlFlowGraph(lambdaD2);

            Assert.NotNull(graphD2);
            Assert.Same(graphD1, graphD2.Parent);

            Assert.Throws <ArgumentNullException>(() => graphM.GetAnonymousFunctionControlFlowGraph(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetAnonymousFunctionControlFlowGraph(lambdaD2));
            Assert.Throws <ArgumentNullException>(() => graphM.GetAnonymousFunctionControlFlowGraphInScope(null));
            Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetAnonymousFunctionControlFlowGraphInScope(lambdaD2));

            IFlowAnonymousFunctionOperation getLambda(ControlFlowGraph graph)
            {
                return(graph.Blocks.SelectMany(b => b.Operations.SelectMany(o => o.DescendantsAndSelf())).OfType <IFlowAnonymousFunctionOperation>().Single());
            }
        }
Example #2
0
        /// <summary>
        /// Gets or creates a control flow graph for the given <paramref name="anonymousFunction"/> defined in
        /// the given <paramref name="controlFlowGraph"/> or any of it's parent control flow graphs.
        /// </summary>
        public static ControlFlowGraph GetAnonymousFunctionControlFlowGraphInScope(
            this ControlFlowGraph controlFlowGraph,
            IFlowAnonymousFunctionOperation anonymousFunction,
            CancellationToken cancellationToken = default
            )
        {
            if (controlFlowGraph == null)
            {
                throw new ArgumentNullException(nameof(controlFlowGraph));
            }

            if (anonymousFunction == null)
            {
                throw new ArgumentNullException(nameof(anonymousFunction));
            }

            ControlFlowGraph?currentGraph = controlFlowGraph;

            do
            {
                if (
                    currentGraph.TryGetAnonymousFunctionControlFlowGraph(
                        anonymousFunction,
                        cancellationToken,
                        out ControlFlowGraph? localFunctionControlFlowGraph
                        )
                    )
                {
                    return(localFunctionControlFlowGraph);
                }
            } while ((currentGraph = currentGraph.Parent) != null);

            throw new ArgumentOutOfRangeException(nameof(anonymousFunction));
        }
Example #3
0
            public override ParameterValidationAbstractValue VisitInvocation_Lambda(
                IFlowAnonymousFunctionOperation lambda,
                ImmutableArray <IArgumentOperation> visitedArguments,
                IOperation originalOperation,
                ParameterValidationAbstractValue defaultValue)
            {
                var value = base.VisitInvocation_Lambda(lambda, visitedArguments, originalOperation, defaultValue);

                ProcessLambdaOrLocalFunctionInvocation(lambda.Symbol, originalOperation);
                return(value);
            }
Example #4
0
        public override IOperation VisitFlowAnonymousFunction(
            IFlowAnonymousFunctionOperation operation,
            object?argument
            )
        {
            var anonymous = (FlowAnonymousFunctionOperation)operation;

            return(new FlowAnonymousFunctionOperation(
                       in anonymous.Context,
                       anonymous.Original,
                       operation.IsImplicit
                       ));
        }
            public override TaintedDataAbstractValue VisitInvocation_Lambda(IFlowAnonymousFunctionOperation lambda, ImmutableArray <IArgumentOperation> visitedArguments, IOperation originalOperation, TaintedDataAbstractValue defaultValue)
            {
                // Always invoke base visit.
                TaintedDataAbstractValue baseValue = base.VisitInvocation_Lambda(lambda, visitedArguments, originalOperation, defaultValue);

                IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments);

                if (taintedArguments.Any())
                {
                    ProcessTaintedDataEnteringInvocationOrCreation(lambda.Symbol, taintedArguments, originalOperation);
                }

                return(baseValue);
            }
 public BasicBlockAnalysisData AnalyzeLambdaInvocation(IFlowAnonymousFunctionOperation lambda, CancellationToken cancellationToken)
 {
     if (!LambdaOrLocalFunctionsBeingAnalyzed.Add(lambda.Symbol))
     {
         ResetState();
         return(CurrentBlockAnalysisData);
     }
     else
     {
         var result = AnalyzeLambdaInvocationCore(lambda, cancellationToken);
         LambdaOrLocalFunctionsBeingAnalyzed.Remove(lambda.Symbol);
         return(result);
     }
 }
Example #7
0
            public override void VisitFlowAnonymousFunction(IFlowAnonymousFunctionOperation operation)
            {
                base.VisitFlowAnonymousFunction(operation);

                LogString("{");
                LogNewLine();
                var g  = _graph.GetAnonymousFunctionControlFlowGraph(operation);
                int id = _anonymousFunctionsMap.Count;

                _anonymousFunctionsMap.Add(operation, g);
                Assert.Equal(OperationKind.AnonymousFunction, g.OriginalOperation.Kind);
                GetFlowGraph(_builder, _compilation, g, _region, $"#A{id}{_idSuffix}", _currentIndent.Length + 4);
                LogString("}");
                LogNewLine();
            }
Example #8
0
        public ControlFlowGraph GetAnonymousFunctionControlFlowGraph(IFlowAnonymousFunctionOperation lambda)
        {
            // TODO: https://github.com/dotnet/roslyn-analyzers/issues/1812
            // Remove the below workaround.
            try
            {
                return(ControlFlowGraph.GetAnonymousFunctionControlFlowGraph(lambda));
            }
            catch (ArgumentOutOfRangeException)
            {
                if (ParentControlFlowGraphOpt != null && InterproceduralAnalysisDataOpt != null)
                {
                    var parentAnalysisContext = InterproceduralAnalysisDataOpt.MethodsBeingAnalyzed.FirstOrDefault(context => context.ControlFlowGraph == ParentControlFlowGraphOpt);
                    return(parentAnalysisContext?.GetAnonymousFunctionControlFlowGraph(lambda));
                }

                // Unable to find control flow graph for lambda.
                // This can happen for cases where lambda creation and invocations are in different interprocedural call trees.
                // See unit test "DisposeObjectsBeforeLosingScopeTests.InvocationOfLambdaCachedOntoField_InterproceduralAnalysis"
                // for an example.
                // Currently, we don't support interprocedural analysis of such lambda invocations.
                return(null);
            }
        }
Example #9
0
 public override void SetLambdaTargetForDelegate(IOperation write, IFlowAnonymousFunctionOperation lambdaTarget)
 => throw ExceptionUtilities.Unreachable;
Example #10
0
 // Lambda target needs flow analysis, not supported/reachable in operation tree based analysis.
 protected override BasicBlockAnalysisData AnalyzeLambdaInvocationCore(IFlowAnonymousFunctionOperation lambda, CancellationToken cancellationToken)
 => throw ExceptionUtilities.Unreachable;
Example #11
0
 public virtual void VisitFlowAnonymousFunction(IFlowAnonymousFunctionOperation operation)
 {
     DefaultVisit(operation);
 }
 public abstract void SetLambdaTargetForDelegate(IOperation write, IFlowAnonymousFunctionOperation lambdaTarget);
 protected abstract BasicBlockAnalysisData AnalyzeLambdaInvocationCore(IFlowAnonymousFunctionOperation lambda, CancellationToken cancellationToken);
Example #14
0
 public override void VisitFlowAnonymousFunction(IFlowAnonymousFunctionOperation operation)
 {
     Assert.Equal(OperationKind.FlowAnonymousFunction, operation.Kind);
     Assert.NotNull(operation.Symbol);
     Assert.Empty(operation.Children);
 }