/// <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); }
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)); }
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)); }