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 InvocationExpressionSyntax invocationExpressionSyntax: return(VisitMethodInvocation(invocationExpressionSyntax, state)); case ObjectCreationExpressionSyntax objectCreationExpressionSyntax: return(VisitObjectCreation(objectCreationExpressionSyntax, state)); case LiteralExpressionSyntax _: return(new VariableState(expression, VariableTaint.Constant)); case IdentifierNameSyntax identifierNameSyntax: return(VisitIdentifierName(identifierNameSyntax, state)); case BinaryExpressionSyntax binaryExpressionSyntax: return(VisitBinaryExpression(binaryExpressionSyntax, state)); case MemberAccessExpressionSyntax memberAccessExpressionSyntax: return(VisitExpression(memberAccessExpressionSyntax.Name, 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 TernaryConditionalExpressionSyntax ternaryConditionalExpressionSyntax: { VisitExpression(ternaryConditionalExpressionSyntax.Condition, state); var finalState = new VariableState(ternaryConditionalExpressionSyntax, VariableTaint.Safe); var whenTrueState = VisitExpression(ternaryConditionalExpressionSyntax.WhenTrue, state); finalState = finalState.Merge(whenTrueState); var whenFalseState = VisitExpression(ternaryConditionalExpressionSyntax.WhenFalse, state); finalState = finalState.Merge(whenFalseState); return(finalState); } case QueryExpressionSyntax queryExpressionSyntax: return(new VariableState(queryExpressionSyntax, VariableTaint.Unknown)); case DirectCastExpressionSyntax directCastExpressionSyntax: return(VisitExpression(directCastExpressionSyntax.Expression, state)); case CTypeExpressionSyntax cTypeExpressionSyntax: return(VisitExpression(cTypeExpressionSyntax.Expression, state)); } Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression.ToString() + ")"); return(new VariableState(expression, VariableTaint.Unknown)); }
private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state) { switch (expression) { case InvocationExpressionSyntax invocationExpressionSyntax: return(VisitMethodInvocation(invocationExpressionSyntax, state)); case ObjectCreationExpressionSyntax objectCreationExpressionSyntax: return(VisitObjectCreation(objectCreationExpressionSyntax, state)); case LiteralExpressionSyntax _: return(new VariableState(expression, VariableTaint.Constant)); case IdentifierNameSyntax identifierNameSyntax: return(VisitIdentifierName(identifierNameSyntax, state)); case BinaryExpressionSyntax binaryExpressionSyntax: return(VisitBinaryExpression(binaryExpressionSyntax, state)); case AssignmentExpressionSyntax assignmentExpressionSyntax: return(VisitAssignment(assignmentExpressionSyntax, state)); case MemberAccessExpressionSyntax memberAccessExpressionSyntax: var leftExpression = memberAccessExpressionSyntax.Expression; return(VisitExpression(leftExpression, state)); case ElementAccessExpressionSyntax elementAccessExpressionSyntax: return(VisitElementAccess(elementAccessExpressionSyntax, elementAccessExpressionSyntax.ArgumentList, state)); case ArrayCreationExpressionSyntax arrayCreationExpressionSyntax: return(VisitArrayCreation(arrayCreationExpressionSyntax, state)); case TypeOfExpressionSyntax typeOfExpressionSyntax: return(new VariableState(typeOfExpressionSyntax, VariableTaint.Safe)); case ConditionalExpressionSyntax conditionalExpressionSyntax: VisitExpression(conditionalExpressionSyntax.Condition, state); var finalState = new VariableState(conditionalExpressionSyntax, VariableTaint.Safe); var whenTrueState = VisitExpression(conditionalExpressionSyntax.WhenTrue, state); finalState = finalState.Merge(whenTrueState); var whenFalseState = VisitExpression(conditionalExpressionSyntax.WhenFalse, state); finalState = finalState.Merge(whenFalseState); return(finalState); case CheckedExpressionSyntax checkedExpressionSyntax: return(VisitExpression(checkedExpressionSyntax.Expression, state)); case QueryExpressionSyntax queryExpressionSyntax: return(new VariableState(queryExpressionSyntax, VariableTaint.Unknown)); case InterpolatedStringExpressionSyntax interpolatedStringExpressionSyntax: return(VisitInterpolatedString(interpolatedStringExpressionSyntax, state)); } Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression.ToString() + ")"); return(new VariableState(expression, VariableTaint.Unknown)); }
/// <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(BinaryExpressionSyntax expression, ExecutionState state) { VariableState left = VisitExpression(expression.Left, state); VariableState right = VisitExpression(expression.Right, state); return(left.Merge(right)); }
public void Merge(ExecutionState other) { var queue = new Queue <KeyValuePair <VariableState, VariableState> >(); var otherToSelf = new Dictionary <VariableState, VariableState>(); foreach (var otherVariableState in other.VariableStates) { if (!Variables.TryGetValue(otherVariableState.Key, out var selfVariableState)) { selfVariableState = new VariableState(otherVariableState.Value.Node, otherVariableState.Value.Taint, otherVariableState.Value.Value); Variables.Add(otherVariableState.Key, selfVariableState); } if (!otherToSelf.ContainsKey(otherVariableState.Value)) { queue.Enqueue(new KeyValuePair <VariableState, VariableState>(otherVariableState.Value, selfVariableState)); otherToSelf.Add(otherVariableState.Value, selfVariableState); } } VariableState.Merge(queue, otherToSelf); }
private VariableState VisitInterpolatedString(InterpolatedStringExpressionSyntax interpolatedString, ExecutionState state) { var varState = new VariableState(interpolatedString, VariableTaint.Constant); foreach (var content in interpolatedString.Contents) { if (content is InterpolatedStringTextSyntax textString) { varState = varState.Merge(new VariableState(textString, VariableTaint.Constant)); } if (!(content is InterpolationSyntax interpolation)) { continue; } var expressionState = VisitExpression(interpolation.Expression, state); varState = varState.Merge(expressionState); } return(varState); }
private VariableState VisitArrayCreation(SyntaxNode node, InitializerExpressionSyntax arrayInit, ExecutionState state) { var finalState = new VariableState(node, VariableTaint.Safe); if (arrayInit == null) { return(finalState); } foreach (var ex in arrayInit.Expressions) { var exprState = VisitExpression(ex, state); finalState = finalState.Merge(exprState); } return(finalState); }
private VariableState VisitObjectCreation(ObjectCreationExpressionSyntax node, ExecutionState state) { VariableState finalState = VisitInvocationAndCreation(node, node.ArgumentList, state); foreach (SyntaxNode child in node.DescendantNodes()) { if (child is AssignmentExpressionSyntax assignmentExpressionSyntax) { finalState = finalState.Merge(VisitAssignment(assignmentExpressionSyntax, state)); } else { Logger.Log(child.GetText().ToString().Trim() + " -> " + finalState); } } 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> /// <param name="node"></param> /// <param name="argList"></param> /// <param name="state"></param> /// <returns></returns> private VariableState VisitInvocationAndCreation(ExpressionSyntax node, ArgumentListSyntax argList, ExecutionState state) { var symbol = state.GetSymbol(node); MethodBehavior behavior = BehaviorRepo.GetMethodBehavior(symbol); int i = 0; if (argList == null) { return(new VariableState(node, VariableTaint.Unknown)); } var returnState = new VariableState(node, VariableTaint.Safe); foreach (var argument in argList.Arguments) { var argumentState = VisitExpression(argument.Expression, state); if (symbol != null) { Logger.Log(symbol.ContainingType + "." + symbol.Name + " -> " + argumentState); } if (behavior != null) { //If the API is at risk if ((argumentState.Taint == VariableTaint.Tainted || argumentState.Taint == VariableTaint.Unknown) && //Tainted values //If the current parameter can be injected. Array.Exists(behavior.InjectablesArguments, element => element == i)) { var newRule = LocaleUtil.GetDescriptor(behavior.LocaleInjection); var diagnostic = Diagnostic.Create(newRule, node.GetLocation()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (argumentState.Taint == VariableTaint.Constant && //Hard coded value //If the current parameter is a password Array.Exists(behavior.PasswordArguments, element => element == i)) { var newRule = LocaleUtil.GetDescriptor(behavior.LocalePassword); var diagnostic = Diagnostic.Create(newRule, node.GetLocation()); state.AnalysisContext.ReportDiagnostic(diagnostic); } else if (Array.Exists(behavior.TaintFromArguments, element => element == i)) { returnState = returnState.Merge(argumentState); } } //TODO: tainted all object passed in argument i++; } //Additional analysis by extension foreach (var ext in Extensions) { ext.VisitInvocationAndCreation(node, argList, state); } var hasTaintFromArguments = behavior?.TaintFromArguments?.Length > 0; return(hasTaintFromArguments ? returnState : new VariableState(node, VariableTaint.Unknown)); }
private VariableState VisitExpression(ExpressionSyntax expression, ExecutionState state) { switch (expression) { 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, state)); } case AssignmentExpressionSyntax assignmentExpressionSyntax: var assigmentState = VisitAssignment(assignmentExpressionSyntax, state); return(MergeVariableState(assignmentExpressionSyntax.Left, assigmentState, 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.Safe); var whenTrueState = VisitExpression(conditionalExpressionSyntax.WhenTrue, state); finalState.Merge(whenTrueState); var whenFalseState = VisitExpression(conditionalExpressionSyntax.WhenFalse, state); finalState.Merge(whenFalseState); return(finalState); case CheckedExpressionSyntax checkedExpressionSyntax: return(VisitExpression(checkedExpressionSyntax.Expression, state)); case QueryExpressionSyntax queryExpressionSyntax: return(new VariableState(queryExpressionSyntax, VariableTaint.Unknown)); 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)); } Logger.Log("Unsupported expression " + expression.GetType() + " (" + expression + ")"); return(new VariableState(expression, VariableTaint.Unknown)); }