Len has asked for the wisdom of the Perl Monks concerning the following question:

I have the situation where I have to evaluate an expression which is stored in a variable.

Example:

my $output; my $expression = "5 < 7"; my $true = "String displayed if true"; my $false = "String displayed if false"; if (eval($expression)) { $output = $true; } else { $output = $false; } print $output;
$expression, $true and $false are all dynamic. This code will be used in a web-environment so eval($expression) is a very bad way to do it.

Is there a secure way to evaluate $expression without use of eval ?

Replies are listed 'Best First'.
Re: securely evaluating an expression
by Abigail-II (Bishop) on Nov 20, 2002 at 12:45 UTC
    There is nothing dangerous about the code fragment you posted.

    The only thing that is dangerous is executing code you got from the bad outside world without checking it won't do anything it shouldn't do. But that's regardless whether you use eval or some other means to execute it.

    You probably want to make use of the Safe module.

    Abigail

Re: securely evaluating an expression
by broquaint (Abbot) on Nov 20, 2002 at 13:49 UTC
    You could try out the Safe module and run the code in a Safe compartment with a restricted opset e.g
    use Safe; use Opcode; my @permit_opsets = qw(print :base_core :base_mem :base_loop :base_math); my @deny_opsets = qw(die warn); my $c = Safe->new(); $c->permit_only( @permit_opsets ); $c->deny( @deny_opsets ); $c->reval( "@ARGV" ); die("ack: $@") if $@;
    Of course you're still left with the problems of code which could mess with your machine, but that's another story.
    HTH

    _________
    broquaint

Re: securely evaluating an expression
by mirod (Canon) on Nov 20, 2002 at 12:57 UTC

    I don't think you can safely eval the expression, .

    The safest solution here is to write a parser for the expressions you want to accept and then either eval them or have the parser compute the result. This is not as hard as it sounds, you can have a look at Parse::RecDescent for example: the Parse::RecDescent Tutorial describes an expression parser that you could use as a basis. You could also use Parse::Yapp, the Perl Review has an article about it that should get you started.

    And you can also write a rudimentary regexp-based parser, which would probably be a lot less powerful (and might be less safe).

    Perl 6 will make this kind of parser a lot more easy to write BTW.

Re: securely evaluating an expression
by Chady (Priest) on Nov 20, 2002 at 12:51 UTC
    just a sidenote: (of course using eval in your context is extremely not secure, so you might want to change your code logic to include specific expressions: like if you want them to evaluate '5 < 7' then take the inputs each one alone and test them one by one to construct the expression, or something like that)
    anyway
    if (eval($expression)) { $output = $true; } else { $output = $false; }
    using eval() will not tell you what went wrong, you probably want to use the eval-BLOCK to catch errors and warnings in $@.
    eval { $expression }; $output = defined $@ ? $false : $true;

    He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

    Chady | http://chady.net/
Re: securely evaluating an expression
by shotgunefx (Parson) on Nov 20, 2002 at 12:51 UTC
    If you want to avoid passing it to Perl, you might want to look at Evaluate Expressions. (I provide no warranties :)

    -Lee

    "To be civilized is to deny one's nature."