/// <summary>
        /// Combine the state of the two operands. Binary expression include concatenation.
        /// </summary>
        /// <param name="expression"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private VariableState VisitBinaryExpression(ExpressionSyntax expression,
                                                    ExpressionSyntax leftExpression,
                                                    ExpressionSyntax rightExrpession,
                                                    ExecutionState state)
        {
            var result = new VariableState(expression, VariableTaint.Unset);
            var left   = VisitExpression(leftExpression, state);

            result.MergeTaint(left.Taint);
            var right = VisitExpression(rightExrpession, state);

            result.MergeTaint(right.Taint);
            return(result);
        }
        private VariableState VisitMethodInvocation(InvocationExpressionSyntax node, ExecutionState state)
        {
            VariableState memberVariableState = null;

            if (node.Expression is MemberAccessExpressionSyntax memberAccessExpression)
            {
                if (memberAccessExpression.Expression != null)
                {
                    memberVariableState = VisitExpression(memberAccessExpression.Expression, state);
                }
                else
                {
                    var with = memberAccessExpression.AncestorsAndSelf().OfType <WithBlockSyntax>().First();
                    memberVariableState = VisitExpression(with.WithStatement.Expression, state);
                }

                var taintSourceState = CheckIfTaintSource(memberAccessExpression, state);
                if (taintSourceState != null)
                {
                    memberVariableState.MergeTaint(taintSourceState.Taint);
                }
            }

            return(VisitInvocationAndCreation(node, node.ArgumentList, state, memberVariableState?.Taint, memberVariableState));
        }
        /// <summary>
        /// Unwrap
        /// </summary>
        /// <param name="declaration"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        private VariableState VisitLocalDeclaration(LocalDeclarationStatementSyntax declaration, ExecutionState state)
        {
            var finalState = new VariableState(declaration, VariableTaint.Unset);

            foreach (var i in declaration.Declarators)
            {
                finalState.MergeTaint(VisitVariableDeclaration(i, state).Taint);
            }

            return(finalState);
        }
        private VariableState VisitFromClause(FromClauseSyntax fromClauseSyntax, ExecutionState state)
        {
            var finalState = new VariableState(fromClauseSyntax, VariableTaint.Unset);

            foreach (var variable in fromClauseSyntax.Variables)
            {
                finalState.MergeTaint(VisitNode(variable, state).Taint);
            }

            return(finalState);
        }
Beispiel #5
0
        private VariableState VisitElementAccess(ElementAccessExpressionSyntax elementAccess,
                                                 BracketedArgumentListSyntax argumentList,
                                                 ExecutionState state)
        {
            var finalState = new VariableState(elementAccess, VariableTaint.Unset);

            foreach (var argument in argumentList.Arguments)
            {
                finalState.MergeTaint(VisitExpression(argument.Expression, state).Taint);
            }

            finalState.MergeTaint(VisitExpression(elementAccess.Expression, state).Taint);

            var taintSourceState = CheckIfTaintSource(elementAccess, state);

            if (taintSourceState != null)
            {
                finalState.MergeTaint(taintSourceState.Taint);
            }

            return(finalState);
        }
        private VariableState VisitInterpolatedString(InterpolatedStringExpressionSyntax interpolatedString,
                                                      ExecutionState state)
        {
            var varState = new VariableState(interpolatedString, VariableTaint.Constant);

            foreach (var content in interpolatedString.Contents)
            {
                if (content is InterpolatedStringTextSyntax)
                {
                    varState.MergeTaint(VariableTaint.Constant);
                }

                if (!(content is InterpolationSyntax interpolation))
                {
                    continue;
                }

                var expressionState = VisitExpression(interpolation.Expression, state);
                varState.MergeTaint(expressionState.Taint);
            }

            return(varState);
        }
        private VariableState VisitArrayCreation(SyntaxNode node, CollectionInitializerSyntax arrayInit, ExecutionState state)
        {
            var finalState = new VariableState(node, VariableTaint.Safe);

            if (arrayInit == null)
            {
                return(finalState);
            }

            foreach (var ex in arrayInit.Initializers)
            {
                var exprState = VisitExpression(ex, state);
                finalState.MergeTaint(exprState.Taint);
            }

            return(finalState);
        }
        /// <summary>
        /// Logic for each method invocation (including constructor)
        /// The argument list is required because <code>InvocationExpressionSyntax</code> and
        /// <code>ObjectCreationExpressionSyntax</code> do not share a common interface.
        /// </summary>
        private VariableState VisitInvocationAndCreation(ExpressionSyntax node,
                                                         ArgumentListSyntax argList,
                                                         ExecutionState state,
                                                         VariableTaint?initialTaint        = null,
                                                         VariableState memberVariableState = null)
        {
            var symbol = state.GetSymbol(node);

            if (symbol == null)
            {
                return(new VariableState(node, initialTaint ?? VariableTaint.Unknown));
            }

            var  methodSymbol      = symbol as IMethodSymbol;
            bool isExtensionMethod = methodSymbol?.ReducedFrom != null;
            var  behavior          = symbol.GetMethodBehavior(ProjectConfiguration.Behavior);
            IReadOnlyDictionary <int, PostCondition> postConditions = null;

            if (behavior != null)
            {
                postConditions = GetPostConditions(behavior, isExtensionMethod, argList, state);
            }

            PostCondition returnPostCondition = null;

            postConditions?.TryGetValue(-1, out returnPostCondition);

            VariableState returnState = initialTaint != null && !symbol.IsStatic
                                            ? new VariableState(node, initialTaint.Value)
                                            : new VariableState(node, argList?.Arguments.Count > 0 && behavior != null
                                                                          ? VariableTaint.Unset
                                                                          : VariableTaint.Unknown);

            var argCount       = argList?.Arguments.Count;
            var argumentStates = argCount.HasValue &&
                                 argCount.Value > 0 &&
                                 (postConditions?.Any(c => c.Key != -1 && (c.Value.Taint != 0ul || c.Value.TaintFromArguments.Any())) == true ||
                                  methodSymbol != null && methodSymbol.Parameters.Any(x => x.RefKind != RefKind.None))
                                     ? new VariableState[argCount.Value]
                                     : null;

            for (var i = 0; i < argList?.Arguments.Count; i++)
            {
                var argument      = argList.Arguments[i];
                var argumentState = VisitExpression(argument.GetExpression(), state);
                if (argumentStates != null)
                {
                    argumentStates[i] = argumentState;
                }

#if DEBUG
                Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState);
#endif

                var adjustedArgumentIdx = isExtensionMethod ? i + 1 : i;

                if (behavior != null)
                {
                    if ((argumentState.Taint & (ProjectConfiguration.AuditMode
                                                    ? VariableTaint.Tainted | VariableTaint.Unknown
                                                    : VariableTaint.Tainted)) != 0)
                    {
                        //If the current parameter can be injected.
                        if (behavior.InjectableArguments.TryGetValue(adjustedArgumentIdx, out var injectableArgument) &&
                            (injectableArgument.RequiredTaintBits & (ulong)argumentState.Taint) != injectableArgument.RequiredTaintBits)
                        {
                            var newRule    = LocaleUtil.GetDescriptor(injectableArgument.Locale);
                            var diagnostic = Diagnostic.Create(newRule, argument.GetExpression().GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                            state.AnalysisContext.ReportDiagnostic(diagnostic);
                        }
                    }
                    else if (argumentState.Taint == VariableTaint.Constant)
                    {
                        if (behavior.InjectableArguments.TryGetValue(adjustedArgumentIdx, out var injectableArgument) &&
                            injectableArgument.Not && (injectableArgument.RequiredTaintBits & (ulong)argumentState.Taint) != 0ul)
                        {
                            var newRule    = LocaleUtil.GetDescriptor(injectableArgument.Locale);
                            var diagnostic = Diagnostic.Create(newRule, argument.GetExpression().GetLocation(), GetMethodName(node), (i + 1).ToNthString());
                            state.AnalysisContext.ReportDiagnostic(diagnostic);
                        }
                    }
                }

                var argumentToSearch = adjustedArgumentIdx;
                if (methodSymbol != null &&
                    i >= methodSymbol.Parameters.Length &&
                    methodSymbol.Parameters[methodSymbol.Parameters.Length - 1].IsParams)
                {
                    argumentToSearch = isExtensionMethod ? methodSymbol.Parameters.Length : methodSymbol.Parameters.Length - 1;
                }

                if (returnPostCondition == null ||
                    returnPostCondition.TaintFromArguments.Contains(argumentToSearch))
                {
                    returnState.MergeTaint(argumentState.Taint);
                }

                //TODO: taint all objects passed as arguments
            }

            if (returnPostCondition != null)
            {
                returnState.ApplyTaint(returnPostCondition.Taint);
            }

            if (argumentStates != null)
            {
                for (var i = 0; i < argList.Arguments.Count; i++)
                {
                    var adjustedPostConditionIdx = isExtensionMethod ? i + 1 : i;

                    if (postConditions != null && postConditions.TryGetValue(adjustedPostConditionIdx, out var postCondition))
                    {
                        foreach (var argIdx in postCondition.TaintFromArguments)
                        {
                            var adjustedArgumentIdx = isExtensionMethod ? argIdx + 1 : argIdx;
                            argumentStates[adjustedPostConditionIdx].MergeTaint(argumentStates[adjustedArgumentIdx].Taint);
                        }

                        argumentStates[adjustedPostConditionIdx].ApplyTaint(postCondition.Taint);
                    }
                    else if (methodSymbol != null)
                    {
                        if (i >= methodSymbol.Parameters.Length)
                        {
                            if (!methodSymbol.Parameters[methodSymbol.Parameters.Length - 1].IsParams)
                            {
                                throw new IndexOutOfRangeException();
                            }
                        }
                        else if (methodSymbol.Parameters[i].RefKind != RefKind.None)
                        {
                            argumentStates[i].MergeTaint(returnState.Taint);
                        }
                    }
                }
            }

            if (memberVariableState != null &&
                methodSymbol != null &&
                methodSymbol.ReturnsVoid &&
                !methodSymbol.IsStatic &&
                methodSymbol.Parameters.All(x => x.RefKind == RefKind.None))
            {
                memberVariableState.MergeTaint(returnState.Taint);
            }

            //Additional analysis by extension
            foreach (var ext in Extensions)
            {
                ext.VisitInvocationAndCreation(node, argList, state);
            }

            return(returnState);
        }
        private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state)
        {
            // TODO: Review other expression types that are unique to VB.
            // TODO: Write tests to cover all these.

            switch (expression)
            {
            case ParenthesizedExpressionSyntax parenthesizedExpressionSyntax:
                return(VisitExpression(parenthesizedExpressionSyntax.Expression, state));

            case InvocationExpressionSyntax invocationExpressionSyntax:
                return(VisitMethodInvocation(invocationExpressionSyntax, state));

            case ObjectCreationExpressionSyntax objectCreationExpressionSyntax:
                return(VisitObjectCreation(objectCreationExpressionSyntax, state));

            case LiteralExpressionSyntax literalExpressionSyntax:
                return(new VariableState(literalExpressionSyntax, VariableTaint.Constant, literalExpressionSyntax.Token.Value));

            case IdentifierNameSyntax identifierNameSyntax:
                return(VisitIdentifierName(identifierNameSyntax, state));

            case BinaryExpressionSyntax binaryExpressionSyntax:
                return(VisitBinaryExpression(binaryExpressionSyntax, binaryExpressionSyntax.Left, binaryExpressionSyntax.Right, state));

            case BinaryConditionalExpressionSyntax binaryConditionalExpressionSyntax:
                return(VisitBinaryExpression(binaryConditionalExpressionSyntax,
                                             binaryConditionalExpressionSyntax.FirstExpression,
                                             binaryConditionalExpressionSyntax.SecondExpression, state));

            case MemberAccessExpressionSyntax memberAccessExpressionSyntax:
                return(VisitMemberAccessExpression(memberAccessExpressionSyntax, state));

            case ArrayCreationExpressionSyntax arrayCreationExpressionSyntax:
                return(VisitArrayCreation(arrayCreationExpressionSyntax, arrayCreationExpressionSyntax.Initializer, state));

            case CollectionInitializerSyntax collectionInitializerSyntax:
                return(VisitArrayCreation(collectionInitializerSyntax, collectionInitializerSyntax, state));

            case TypeOfExpressionSyntax typeOfExpressionSyntax:
                return(new VariableState(typeOfExpressionSyntax, VariableTaint.Safe));

            case GetTypeExpressionSyntax getTypeExpressionSyntax:
                return(new VariableState(getTypeExpressionSyntax, VariableTaint.Safe));

            case TernaryConditionalExpressionSyntax ternaryConditionalExpressionSyntax:
            {
                VisitExpression(ternaryConditionalExpressionSyntax.Condition, state);
                var finalState = new VariableState(ternaryConditionalExpressionSyntax, VariableTaint.Unset);

                var whenTrueState = VisitExpression(ternaryConditionalExpressionSyntax.WhenTrue, state);
                finalState.MergeTaint(whenTrueState.Taint);
                var whenFalseState = VisitExpression(ternaryConditionalExpressionSyntax.WhenFalse, state);
                finalState.MergeTaint(whenFalseState.Taint);

                return(finalState);
            }

            case QueryExpressionSyntax queryExpressionSyntax:
            {
                var finalState = new VariableState(queryExpressionSyntax, VariableTaint.Unset);
                foreach (var clause in queryExpressionSyntax.Clauses)
                {
                    finalState.MergeTaint(VisitNode(clause, state).Taint);
                }

                return(finalState);
            }

            case InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax:
                return(VisitInterpolatedString(interpolatedStringExpressionSyntax, state));

            case DirectCastExpressionSyntax directCastExpressionSyntax:
                return(VisitExpression(directCastExpressionSyntax.Expression, state));

            case CTypeExpressionSyntax cTypeExpressionSyntax:
                return(VisitExpression(cTypeExpressionSyntax.Expression, state));

            case UnaryExpressionSyntax unaryExpressionSyntax:
                return(VisitExpression(unaryExpressionSyntax.Operand, state));
            }

#if DEBUG
            Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression + ")");
#endif
            return(new VariableState(expression, VariableTaint.Unknown));
        }
Beispiel #10
0
        private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state)
        {
            switch (expression)
            {
            case ParenthesizedExpressionSyntax parenthesizedExpressionSyntax:
                return(VisitExpression(parenthesizedExpressionSyntax.Expression, state));

            case InvocationExpressionSyntax invocationExpressionSyntax:
                return(VisitMethodInvocation(invocationExpressionSyntax, state));

            case ObjectCreationExpressionSyntax objectCreationExpressionSyntax:
                return(VisitObjectCreation(objectCreationExpressionSyntax, state));

            case LiteralExpressionSyntax literalExpressionSyntax:
                return(new VariableState(literalExpressionSyntax, VariableTaint.Constant, literalExpressionSyntax.Token.Value));

            case IdentifierNameSyntax identifierNameSyntax:
                return(VisitIdentifierName(identifierNameSyntax, state));

            case BinaryExpressionSyntax binaryExpressionSyntax:
            {
                switch (binaryExpressionSyntax.Kind())
                {
                case SyntaxKind.AsExpression:
                case SyntaxKind.IsExpression:
                    return(VisitNode(binaryExpressionSyntax.Left, state));
                }

                return(VisitBinaryExpression(binaryExpressionSyntax, binaryExpressionSyntax.Left, binaryExpressionSyntax.Right, state));
            }

            case AssignmentExpressionSyntax assignmentExpressionSyntax:
                if (assignmentExpressionSyntax.Kind() != SyntaxKind.SimpleAssignmentExpression)
                {
                    var left            = VisitExpression(assignmentExpressionSyntax.Left, state);
                    var assignmentState = VisitAssignment(assignmentExpressionSyntax, state);
                    left.MergeTaint(assignmentState.Taint);
                    return(left);
                }
                else
                {
                    var assignmentState = VisitAssignment(assignmentExpressionSyntax, state);
                    return(MergeVariableState(assignmentExpressionSyntax.Left, assignmentState, state));
                }

            case MemberAccessExpressionSyntax memberAccessExpressionSyntax:
                return(VisitMemberAccessExpression(memberAccessExpressionSyntax, state));

            case ElementAccessExpressionSyntax elementAccessExpressionSyntax:
                return(VisitElementAccess(elementAccessExpressionSyntax, elementAccessExpressionSyntax.ArgumentList, state));

            case ArrayCreationExpressionSyntax arrayCreationExpressionSyntax:
                return(VisitArrayCreation(arrayCreationExpressionSyntax, arrayCreationExpressionSyntax.Initializer, state));

            case ImplicitArrayCreationExpressionSyntax implicitArrayCreationExpressionSyntax:
                return(VisitArrayCreation(implicitArrayCreationExpressionSyntax, implicitArrayCreationExpressionSyntax.Initializer, state));

            case TypeOfExpressionSyntax typeOfExpressionSyntax:
                return(new VariableState(typeOfExpressionSyntax, VariableTaint.Safe));

            case ConditionalExpressionSyntax conditionalExpressionSyntax:
            {
                VisitExpression(conditionalExpressionSyntax.Condition, state);
                var finalState = new VariableState(conditionalExpressionSyntax, VariableTaint.Unset);

                var whenTrueState = VisitExpression(conditionalExpressionSyntax.WhenTrue, state);
                finalState.MergeTaint(whenTrueState.Taint);
                var whenFalseState = VisitExpression(conditionalExpressionSyntax.WhenFalse, state);
                finalState.MergeTaint(whenFalseState.Taint);

                return(finalState);
            }

            case CheckedExpressionSyntax checkedExpressionSyntax:
                return(VisitExpression(checkedExpressionSyntax.Expression, state));

            case QueryExpressionSyntax queryExpressionSyntax:
            {
                var finalState = new VariableState(queryExpressionSyntax, VariableTaint.Unset);
                var fromState  = VisitNode(queryExpressionSyntax.FromClause, state);
                finalState.MergeTaint(fromState.Taint);
                var bodyState = VisitNode(queryExpressionSyntax.Body, state);
                finalState.MergeTaint(bodyState.Taint);
                return(finalState);
            }

            case InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax:
                return(VisitInterpolatedString(interpolatedStringExpressionSyntax, state));

            case CastExpressionSyntax castExpressionSyntax:
                return(VisitExpression(castExpressionSyntax.Expression, state));

            case DefaultExpressionSyntax defaultExpressionSyntax:
                var value = state.AnalysisContext.SemanticModel.GetConstantValue(defaultExpressionSyntax);
                return(new VariableState(defaultExpressionSyntax, VariableTaint.Constant, value.HasValue ? value.Value : null));

            case PrefixUnaryExpressionSyntax prefixUnaryExpressionSyntax:
                return(VisitExpression(prefixUnaryExpressionSyntax.Operand, state));
            }
#if DEBUG
            Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression + ")");
#endif
            return(new VariableState(expression, VariableTaint.Unknown));
        }