I'm curious if there is any good information on performing restricted evals.
Looking at the docs, there is a use Safe
that has a reval
method, but I'm not sure how safe that is.
What I want to do is to be able to pass various conditional statements as a string to a function w/o the source abusing the eval.
For instance:
sub foo {
my $stmt = shift;
my $a = 3;
say eval($stmt)?"correct":"wrong") , "($stmt)";
}
foo( q{1 == $a} );
foo( q{$a =~ /3/ );
foo( q{(sub {return 3})->() eq 3} );
Would use Safe
be good for this? All I need to be able to do is comparisons, no disk access, or variable manipulations.
As indicated in the docs, eval($stmt)
evaluates $stmt
"in the lexical context of the current Perl program, so that any variable settings or subroutine and format definitions remain afterwards." This is useful for delaying execution of $stmt
until runtime.
If you reval($stmt)
in a Safe compartment, essentially the same thing happens, the statement is eval'd, but it's eval'd in a new lexical context which can only see the Safe compartment's namespace, and in which you can control what sorts of operators are allowed.
So, yes, if you declare a Safe compartment and reval($stmt)
in that compartment, then (a) execution of $stmt
won't change the functioning of your program without your consent (I guess this is what you mean by "w/o the source abusing the eval"). And, (b) yes, $stmt
won't be able to access the disk without your consent if you reval($stmt)
. In (a) "your consent" requires explicitly playing with the symbol table, and in (b) "your consent" would require specifying a set of op codes that would allow disk access.
I'm not really sure how safe this is either. However, you can see it in action if you set it up and step through it in the debugger.