How to limit expression access to types external in Roslyn?

Viewed 136

So I read thru the ways of how to evaluate expressions with Roslyn and I wonder if it is possible and how to limit expression to a set of basic math operations and operations on a reduced set of types provided by me (no Console.Writeline, singletons, external Dlls etc). How to force and check such expression capabilities reduction for Roslyn expressions?

1 Answers

One possible solution is evaluate code as expression and analyze the expression, e.g. Expression<Func<Album, bool>>.

Expression<Func<Album, bool>> discountFilterExpression = await CSharpScript.EvaluateAsync<Expression<Func<Album, bool>>>(discountFilter, options);

Then use an ExpressionVisitor to visit nodes of the expression and check if the expression contains only valid/allowed nodes and types.

For example, the below visitor checks if Math is being used within the code evaluated, and set the expression to invalid if so:

class NoMathExpressionVisitor : ExpressionVisitor
{
    public bool IsValid { get; private set; } = true;

    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        if (node.Method.DeclaringType == typeof(Math))
        {
            IsValid = false;
        }

        return base.VisitMethodCall(node);
    }
}

In total:

// Generate expression
Expression<Func<Album, bool>> discountFilterExpression = await CSharpScript.EvaluateAsync<Expression<Func<Album, bool>>>(discountFilter, options);

// Visit each node using NoMathExpressionVisitor
var expressionVisitor = new NoMathExpressionVisitor();
expressionVisitor.Visit(discountFilterExpression);

// Check result
// For code: a => Math.Abs(a.Quality) > 10, IsValid returns false
if (expressionVisitor.IsValid)
{
    // If the expression is valid, compile the expression to
    // Func<> and run.
    var result = discountFilterExpression.Compile()(album);
}

See https://docs.microsoft.com/en-us/dotnet/csharp/expression-trees-interpreting

Related