protected override void VisitSimpleBlock(SimpleBlock block, ExplodedGraphNode node)
        {
            var newProgramState = node.ProgramState;

            if (block is UsingEndBlock usingFinalizerBlock)
            {
                newProgramState = InvokeChecks(newProgramState, (ps, check) => check.PreProcessUsingStatement(node.ProgramPoint, ps));
                newProgramState = CleanStateAfterBlock(newProgramState, block);
                EnqueueAllSuccessors(block, newProgramState);
                return;
            }

            newProgramState = CleanStateAfterBlock(newProgramState, block);

            if (block is ForeachCollectionProducerBlock)
            {
                newProgramState = newProgramState.PopValue();
                EnqueueAllSuccessors(block, newProgramState);
                return;
            }

            if (block is ForInitializerBlock forInitializerBlock)
            {
                newProgramState = newProgramState.PopValues(
                    forInitializerBlock.ForNode.Initializers.Count);

                newProgramState = newProgramState.PushValues(
                    Enumerable
                    .Range(0, forInitializerBlock.ForNode.Incrementors.Count)
                    .Select(i => new SymbolicValue()));

                EnqueueAllSuccessors(forInitializerBlock, newProgramState);
                return;
            }

            if (block is LockBlock lockBlock)
            {
                newProgramState = newProgramState.PopValue();

                newProgramState = newProgramState.RemoveSymbols(IsFieldSymbol);

                EnqueueAllSuccessors(block, newProgramState);
                return;
            }

            if (block is JumpBlock jumpBlock &&
                jumpBlock.JumpNode.IsKind(SyntaxKind.YieldReturnStatement))
            {
                newProgramState = newProgramState.RemoveSymbols(IsFieldSymbol);
            }

            base.VisitSimpleBlock(block, node);
        }
        protected virtual void VisitSimpleBlock(SimpleBlock block, ExplodedGraphNode node)
        {
            var newProgramState = CleanStateAfterBlock(node.ProgramState, block);

            if (block is JumpBlock jumpBlock &&
                IsValueConsumingStatement(jumpBlock.JumpNode))
            {
                newProgramState = newProgramState.PopValue();
            }

            EnqueueAllSuccessors(block, newProgramState);
        }
Example #3
0
        private void VisitBinaryBranch(BinaryBranchBlock binaryBranchBlock, ExplodedGraphNode node, SyntaxNode instruction)
        {
            var           ps = node.ProgramState;
            SymbolicValue sv;

            var forStatement = binaryBranchBlock.BranchingNode as ForStatementSyntax;

            if (forStatement != null)
            {
                if (forStatement.Condition == null)
                {
                    ps = ps.PushValue(SymbolicValue.True);
                }
                ps = ps.PopValue(out sv);
                ps = ps.PopValues(forStatement.Incrementors.Count);
            }
            else
            {
                ps = ps.PopValue(out sv);
            }

            foreach (var newProgramState in sv.TrySetConstraint(BoolConstraint.True, ps))
            {
                OnConditionEvaluated(instruction, evaluationValue: true);

                var nps = binaryBranchBlock.BranchingNode.IsKind(SyntaxKind.LogicalOrExpression)
                    ? newProgramState.PushValue(SymbolicValue.True)
                    : newProgramState;

                EnqueueNewNode(new ProgramPoint(binaryBranchBlock.TrueSuccessorBlock), CleanStateAfterBlock(nps, node.ProgramPoint.Block));
            }

            foreach (var newProgramState in sv.TrySetConstraint(BoolConstraint.False, ps))
            {
                OnConditionEvaluated(instruction, evaluationValue: false);

                var nps = binaryBranchBlock.BranchingNode.IsKind(SyntaxKind.LogicalAndExpression)
                    ? newProgramState.PushValue(SymbolicValue.False)
                    : newProgramState;

                EnqueueNewNode(new ProgramPoint(binaryBranchBlock.FalseSuccessorBlock), CleanStateAfterBlock(nps, node.ProgramPoint.Block));
            }
        }
        protected void EnqueueNewNode(ProgramPoint programPoint, ProgramState programState)
        {
            if (programState == null)
            {
                return;
            }

            var pos = programPoint;

            if (this.programPoints.ContainsKey(programPoint))
            {
                pos = this.programPoints[programPoint];
            }
            else
            {
                this.programPoints[pos] = pos;
            }

            ExplodedGraphNode newNode = null;

            if (programState.GetVisitedCount(pos) >= MaxProgramPointExecutionCount)
            {
                OnProgramPointVisitCountExceedLimit(pos, programState);

                // reached the max number of visit by program point, in the case of ForEach blocks, we take the foreach loop false branch with current program state,
                // if it is not a foreach loop, newNode will be null and we will stop exploring the path
                if (GetForEachExitBlock(programPoint.Block) is Block forEachExitBlock)
                {
                    newNode = new ExplodedGraphNode(new ProgramPoint(forEachExitBlock), programState);
                }
            }
            else
            {
                newNode = new ExplodedGraphNode(pos, programState.AddVisit(pos));
            }

            if (newNode != null && this.nodesAlreadyInGraph.Add(newNode))
            {
                this.workList.Enqueue(newNode);
            }
        }
Example #5
0
        protected virtual void VisitSingleSuccessorBinaryBranch(BinaryBranchingSimpleBlock block, ExplodedGraphNode node)
        {
            var programState = node.ProgramState.PopValue(out var sv);

            foreach (var newProgramState in sv.TrySetConstraint(BoolConstraint.True, programState))
            {
                OnConditionEvaluated(block.BranchingInstruction, evaluationValue: true);
                var nps = newProgramState.PushValue(SymbolicValue.True);
                EnqueueNewNode(new ProgramPoint(block.SuccessorBlock), nps);
            }

            foreach (var newProgramState in sv.TrySetConstraint(BoolConstraint.False, programState))
            {
                OnConditionEvaluated(block.BranchingInstruction, evaluationValue: false);
                var nps = newProgramState.PushValue(SymbolicValue.False);
                EnqueueNewNode(new ProgramPoint(block.SuccessorBlock), nps);
            }
        }
Example #6
0
 protected abstract void VisitInstruction(ExplodedGraphNode node);
Example #7
0
 protected abstract void VisitBinaryBranch(BinaryBranchBlock binaryBranchBlock, ExplodedGraphNode node);
        protected override void VisitInstruction(ExplodedGraphNode node)
        {
            var instruction             = node.ProgramPoint.Block.Instructions[node.ProgramPoint.Offset];
            var expression              = instruction as ExpressionSyntax;
            var parenthesizedExpression = expression?.GetSelfOrTopParenthesizedExpression();
            var newProgramPoint         = new ProgramPoint(node.ProgramPoint.Block, node.ProgramPoint.Offset + 1);
            var newProgramState         = node.ProgramState;

            newProgramState = InvokeChecks(newProgramState, (ps, check) => check.PreProcessInstruction(node.ProgramPoint, ps));
            if (newProgramState == null)
            {
                return;
            }

            switch (instruction.Kind())
            {
            case SyntaxKind.VariableDeclarator:
                newProgramState = VisitVariableDeclarator((VariableDeclaratorSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.SimpleAssignmentExpression:
                newProgramState = VisitSimpleAssignment((AssignmentExpressionSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.OrAssignmentExpression:
                newProgramState = VisitBooleanBinaryOpAssignment(newProgramState, (AssignmentExpressionSyntax)instruction, (l, r) => new OrSymbolicValue(l, r));
                break;

            case SyntaxKind.AndAssignmentExpression:
                newProgramState = VisitBooleanBinaryOpAssignment(newProgramState, (AssignmentExpressionSyntax)instruction, (l, r) => new AndSymbolicValue(l, r));
                break;

            case SyntaxKind.ExclusiveOrAssignmentExpression:
                newProgramState = VisitBooleanBinaryOpAssignment(newProgramState, (AssignmentExpressionSyntax)instruction, (l, r) => new XorSymbolicValue(l, r));
                break;

            case SyntaxKind.SubtractAssignmentExpression:
            case SyntaxKind.AddAssignmentExpression:
            case SyntaxKind.DivideAssignmentExpression:
            case SyntaxKind.MultiplyAssignmentExpression:
            case SyntaxKind.ModuloAssignmentExpression:

            case SyntaxKind.LeftShiftAssignmentExpression:
            case SyntaxKind.RightShiftAssignmentExpression:
                newProgramState = VisitOpAssignment((AssignmentExpressionSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.PreIncrementExpression:
            case SyntaxKind.PreDecrementExpression:
                newProgramState = VisitPrefixIncrement((PrefixUnaryExpressionSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.PostIncrementExpression:
            case SyntaxKind.PostDecrementExpression:
                newProgramState = VisitPostfixIncrement((PostfixUnaryExpressionSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.IdentifierName:
                newProgramState = VisitIdentifier((IdentifierNameSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.BitwiseOrExpression:
                newProgramState = VisitBinaryOperator(newProgramState, (l, r) => new OrSymbolicValue(l, r));
                break;

            case SyntaxKind.BitwiseAndExpression:
                newProgramState = VisitBinaryOperator(newProgramState, (l, r) => new AndSymbolicValue(l, r));
                break;

            case SyntaxKind.ExclusiveOrExpression:
                newProgramState = VisitBinaryOperator(newProgramState, (l, r) => new XorSymbolicValue(l, r));
                break;

            case SyntaxKind.LessThanExpression:
                newProgramState = VisitComparisonBinaryOperator(newProgramState, (BinaryExpressionSyntax)instruction, (l, r) => new ComparisonSymbolicValue(ComparisonKind.Less, l, r));
                break;

            case SyntaxKind.LessThanOrEqualExpression:
                newProgramState = VisitComparisonBinaryOperator(newProgramState, (BinaryExpressionSyntax)instruction, (l, r) => new ComparisonSymbolicValue(ComparisonKind.LessOrEqual, l, r));
                break;

            case SyntaxKind.GreaterThanExpression:
                newProgramState = VisitComparisonBinaryOperator(newProgramState, (BinaryExpressionSyntax)instruction, (l, r) => new ComparisonSymbolicValue(ComparisonKind.Less, r, l));
                break;

            case SyntaxKind.GreaterThanOrEqualExpression:
                newProgramState = VisitComparisonBinaryOperator(newProgramState, (BinaryExpressionSyntax)instruction, (l, r) => new ComparisonSymbolicValue(ComparisonKind.LessOrEqual, r, l));
                break;

            case SyntaxKind.SubtractExpression:
            case SyntaxKind.AddExpression:
            case SyntaxKind.DivideExpression:
            case SyntaxKind.MultiplyExpression:
            case SyntaxKind.ModuloExpression:

            case SyntaxKind.LeftShiftExpression:
            case SyntaxKind.RightShiftExpression:

                newProgramState = newProgramState.PopValues(2);
                newProgramState = newProgramState.PushValue(new SymbolicValue());
                break;

            case SyntaxKind.EqualsExpression:
                var binary = (BinaryExpressionSyntax)instruction;
                newProgramState = IsOperatorOnObject(instruction)
                        ? VisitReferenceEquals(binary, newProgramState)
                        : VisitValueEquals(newProgramState);

                break;

            case SyntaxKind.NotEqualsExpression:
                newProgramState = IsOperatorOnObject(instruction)
                        ? VisitBinaryOperator(newProgramState, (l, r) => new ReferenceNotEqualsSymbolicValue(l, r))
                        : VisitBinaryOperator(newProgramState, (l, r) => new ValueNotEqualsSymbolicValue(l, r));
                break;

            case SyntaxKind.BitwiseNotExpression:
            case SyntaxKind.UnaryMinusExpression:
            case SyntaxKind.UnaryPlusExpression:
            case SyntaxKind.AddressOfExpression:
            case SyntaxKind.PointerIndirectionExpression:

            case SyntaxKind.MakeRefExpression:
            case SyntaxKind.RefTypeExpression:
            case SyntaxKind.RefValueExpression:

            case SyntaxKind.MemberBindingExpression:

            case SyntaxKind.AwaitExpression:
                newProgramState = newProgramState.PopValue();
                newProgramState = newProgramState.PushValue(new SymbolicValue());
                break;

            case SyntaxKind.AsExpression:
            case SyntaxKind.IsExpression:
                newProgramState = VisitSafeCastExpression((BinaryExpressionSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.SimpleMemberAccessExpression:
            {
                var memberAccess = (MemberAccessExpressionSyntax)instruction;
                var check        = explodedGraphChecks.OfType <EmptyNullableValueAccess.NullValueAccessedCheck>().FirstOrDefault();
                if (check == null ||
                    !check.TryProcessInstruction(memberAccess, newProgramState, out newProgramState))
                {
                    // Default behavior
                    newProgramState = VisitMemberAccess(memberAccess, newProgramState);
                }
            }
            break;

            case SyntaxKind.PointerMemberAccessExpression:
            {
                newProgramState = VisitMemberAccess((MemberAccessExpressionSyntax)instruction, newProgramState);
            }
            break;

            case SyntaxKind.GenericName:
            case SyntaxKind.AliasQualifiedName:
            case SyntaxKind.QualifiedName:

            case SyntaxKind.PredefinedType:
            case SyntaxKind.NullableType:

            case SyntaxKind.OmittedArraySizeExpression:

            case SyntaxKind.AnonymousMethodExpression:
            case SyntaxKind.ParenthesizedLambdaExpression:
            case SyntaxKind.SimpleLambdaExpression:
            case SyntaxKind.QueryExpression:

            case SyntaxKind.ArgListExpression:
                newProgramState = newProgramState.PushValue(new SymbolicValue());
                break;

            case SyntaxKind.LogicalNotExpression:
            {
                newProgramState = newProgramState.PopValue(out var sv);
                newProgramState = newProgramState.PushValue(new LogicalNotSymbolicValue(sv));
            }
            break;

            case SyntaxKind.TrueLiteralExpression:
                newProgramState = newProgramState.PushValue(SymbolicValue.True);
                break;

            case SyntaxKind.FalseLiteralExpression:
                newProgramState = newProgramState.PushValue(SymbolicValue.False);
                break;

            case SyntaxKind.NullLiteralExpression:
                newProgramState = newProgramState.PushValue(SymbolicValue.Null);
                break;

            case SyntaxKind.ThisExpression:
                newProgramState = newProgramState.PushValue(SymbolicValue.This);
                break;

            case SyntaxKind.BaseExpression:
                newProgramState = newProgramState.PushValue(SymbolicValue.Base);
                break;

            case SyntaxKind.CharacterLiteralExpression:
            case SyntaxKind.StringLiteralExpression:
            case SyntaxKind.NumericLiteralExpression:

            case SyntaxKind.SizeOfExpression:
            case SyntaxKind.TypeOfExpression:

            case SyntaxKind.ArrayCreationExpression:
            case SyntaxKind.ImplicitArrayCreationExpression:
            case SyntaxKind.StackAllocArrayCreationExpression:
            {
                var sv = new SymbolicValue();
                newProgramState = newProgramState.SetConstraint(sv, ObjectConstraint.NotNull);
                newProgramState = newProgramState.PushValue(sv);
                newProgramState = InvokeChecks(newProgramState,
                                               (ps, check) => check.ObjectCreated(ps, sv, instruction));
            }
            break;

            case SyntaxKind.DefaultExpression:
                newProgramState = VisitDefaultExpression((DefaultExpressionSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.AnonymousObjectCreationExpression:
            {
                var creation = (AnonymousObjectCreationExpressionSyntax)instruction;
                newProgramState = newProgramState.PopValues(creation.Initializers.Count);

                var sv = new SymbolicValue();
                newProgramState = newProgramState.SetConstraint(sv, ObjectConstraint.NotNull);
                newProgramState = newProgramState.PushValue(sv);
                newProgramState = InvokeChecks(newProgramState,
                                               (ps, check) => check.ObjectCreated(ps, sv, instruction));
            }
            break;

            case SyntaxKind.CastExpression:

            case SyntaxKind.CheckedExpression:
            case SyntaxKind.UncheckedExpression:
                // Do nothing
                break;

            case SyntaxKind.InterpolatedStringExpression:
                newProgramState = newProgramState.PopValues(((InterpolatedStringExpressionSyntax)instruction).Contents.OfType <InterpolationSyntax>().Count());
                newProgramState = newProgramState.PushValue(new SymbolicValue());
                break;

            case SyntaxKind.ObjectCreationExpression:
                newProgramState = VisitObjectCreation((ObjectCreationExpressionSyntax)instruction, newProgramState);
                break;

            case SyntaxKind.ElementAccessExpression:
                newProgramState = newProgramState.PopValues((((ElementAccessExpressionSyntax)instruction).ArgumentList?.Arguments.Count ?? 0) + 1);
                newProgramState = newProgramState.PushValue(new SymbolicValue());
                break;

            case SyntaxKind.ImplicitElementAccess:
                newProgramState = newProgramState
                                  .PopValues(((ImplicitElementAccessSyntax)instruction).ArgumentList?.Arguments.Count ?? 0)
                                  .PushValue(new SymbolicValue());
                break;

            case SyntaxKind.ObjectInitializerExpression:
            case SyntaxKind.ArrayInitializerExpression:
            case SyntaxKind.CollectionInitializerExpression:
            case SyntaxKind.ComplexElementInitializerExpression:
                newProgramState = VisitInitializer(instruction, parenthesizedExpression, newProgramState);
                break;

            case SyntaxKind.ArrayType:
                newProgramState = newProgramState.PopValues(((ArrayTypeSyntax)instruction).RankSpecifiers.SelectMany(rs => rs.Sizes).Count());
                break;

            case SyntaxKind.ElementBindingExpression:
                newProgramState = newProgramState.PopValues(((ElementBindingExpressionSyntax)instruction).ArgumentList?.Arguments.Count ?? 0);
                newProgramState = newProgramState.PushValue(new SymbolicValue());
                break;

            case SyntaxKind.InvocationExpression:
            {
                var invocation        = (InvocationExpressionSyntax)instruction;
                var invocationVisitor = new InvocationVisitor(invocation, SemanticModel, newProgramState);
                newProgramState = invocationVisitor.ProcessInvocation();

                if (invocation.Expression.IsOnThis() && !invocation.IsNameof(SemanticModel))
                {
                    newProgramState = newProgramState.RemoveSymbols(IsFieldSymbol);
                }
            }
            break;

            default:
                throw new NotImplementedException($"{instruction.Kind()}");
            }

            newProgramState = EnsureStackState(parenthesizedExpression, newProgramState);
            OnInstructionProcessed(instruction, node.ProgramPoint, newProgramState);
            EnqueueNewNode(newProgramPoint, newProgramState);
        }
        protected override void VisitBinaryBranch(BinaryBranchBlock binaryBranchBlock, ExplodedGraphNode node)
        {
            var newProgramState = CleanStateAfterBlock(node.ProgramState, node.ProgramPoint.Block);

            switch (binaryBranchBlock.BranchingNode.Kind())
            {
            case SyntaxKind.ForEachStatement:
                VisitForeachBinaryBranch(binaryBranchBlock, newProgramState);
                return;

            case SyntaxKind.CoalesceExpression:
                VisitCoalesceExpressionBinaryBranch(binaryBranchBlock, newProgramState);
                return;

            case SyntaxKind.ConditionalAccessExpression:
                VisitConditionalAccessBinaryBranch(binaryBranchBlock, newProgramState);
                return;

            case SyntaxKind.LogicalAndExpression:
            case SyntaxKind.LogicalOrExpression:
                VisitBinaryBranch(binaryBranchBlock, node, ((BinaryExpressionSyntax)binaryBranchBlock.BranchingNode).Left);
                return;

            case SyntaxKind.WhileStatement:
                VisitBinaryBranch(binaryBranchBlock, node, ((WhileStatementSyntax)binaryBranchBlock.BranchingNode).Condition);
                return;

            case SyntaxKind.DoStatement:
                VisitBinaryBranch(binaryBranchBlock, node, ((DoStatementSyntax)binaryBranchBlock.BranchingNode).Condition);
                return;

            case SyntaxKind.ForStatement:
                VisitBinaryBranch(binaryBranchBlock, node, ((ForStatementSyntax)binaryBranchBlock.BranchingNode).Condition);
                return;

            case SyntaxKind.IfStatement:
                VisitBinaryBranch(binaryBranchBlock, node, ((IfStatementSyntax)binaryBranchBlock.BranchingNode).Condition);
                return;

            case SyntaxKind.ConditionalExpression:
                VisitBinaryBranch(binaryBranchBlock, node, ((ConditionalExpressionSyntax)binaryBranchBlock.BranchingNode).Condition);
                return;

            default:
                System.Diagnostics.Debug.Fail($"Branch kind '{binaryBranchBlock.BranchingNode.Kind()}' not handled");
                VisitBinaryBranch(binaryBranchBlock, node, null);
                return;
            }
        }
        protected override void VisitBinaryBranch(BinaryBranchBlock binaryBranchBlock, ExplodedGraphNode node)
        {
            var newProgramState = CleanStateAfterBlock(node.ProgramState, node.ProgramPoint.Block);

            switch (binaryBranchBlock.BranchingNode.Kind())
            {
            case SyntaxKind.ForEachStatement:
                VisitForeachBinaryBranch(binaryBranchBlock, newProgramState);
                return;

            case SyntaxKind.CoalesceExpression:
                VisitCoalesceExpressionBinaryBranch(binaryBranchBlock, newProgramState);
                return;

            case SyntaxKind.ConditionalAccessExpression:
                VisitConditionalAccessBinaryBranch(binaryBranchBlock, newProgramState);
                return;

            case SyntaxKind.LogicalAndExpression:
            case SyntaxKind.LogicalOrExpression:
                VisitBinaryBranch(binaryBranchBlock, node, ((BinaryExpressionSyntax)binaryBranchBlock.BranchingNode).Left);
                return;

            case SyntaxKind.ForStatement:
                VisitBinaryBranch(binaryBranchBlock, node, ((ForStatementSyntax)binaryBranchBlock.BranchingNode).Condition);
                return;

            case SyntaxKind.ConditionalExpression:
                VisitBinaryBranch(binaryBranchBlock, node, ((ConditionalExpressionSyntax)binaryBranchBlock.BranchingNode).Condition);
                return;

            case SyntaxKind.CatchFilterClause:
                VisitBinaryBranch(binaryBranchBlock, node, ((CatchFilterClauseSyntax)binaryBranchBlock.BranchingNode).FilterExpression);
                return;

            default:
                VisitBinaryBranch(binaryBranchBlock, node, binaryBranchBlock.BranchingNode);
                return;
            }
        }
Example #11
0
 protected virtual void VisitBranchBlock(ExplodedGraphNode node, ProgramPoint programPoint)
 {
     var newProgramState = node.ProgramState.PopValue();
     newProgramState = CleanStateAfterBlock(newProgramState, node.ProgramPoint.Block);
     EnqueueAllSuccessors(programPoint.Block, newProgramState);
 }