JS Bangs wrote:
>
> All,
>
> I've got a module that will read an XML file that has code as the
> contents of some elements. I'd like to be able to capture this code as a
> code reference and pass that code reference to a function, without risking
> any internals. The following code works, but doesn't seem foolproof:
>
> # %code, $self, and $parse defined elsewhere
> if (exists $code{$_}) {
> my $c;
> my $code = '$c = sub {' . $parse->{$_} . '}';
>
> # Prevent $code from modifying in-scope variables we need to keep
> {
> local($self, $parse);
> eval $code;
> }
>
> if ($@) {
> err("Errors processing $_ : $@");
> }
> else {
> $self->$_($c);
> }
> }
>
> Suggestions very welcome.
use Safe;
if( exists $code{$_} ) {
(my $safe = Safe->new)->permit_only(qw(:default));
my $c = $safe->reval("return sub { $parse->{$_} }");
if ($@) {
err("Errors processing $_ : $@");
} else {
$self->$_($c);
}
}
[untested; might not *really* be Safe]
Actually, I know for a fact that in some versions of perl, you can do some
really odd things in spite of being inside of a Safe object. For example,
[Windows 95] C:\WINDOWS>perl -MSafe -wle "LOOP: { print 1; Safe->new->reval('last LOOP'); print 2 } print 3"
1
Exiting eval via last at (eval 2) line 2.
Exiting subroutine via last at (eval 2) line 2.
Exiting eval via last at (eval 2) line 2.
Exiting subroutine via last at (eval 2) line 2.
3
Can't return outside a subroutine.
Of course, since you've been wholly trusting the contents of $parse->{$_}
so far (meaning, *anything* could have been done in it's code), you wouldn't
be doing any *worse* to eval the code inside of a Safe object.
--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6

$a=pop @b))&&redo;}