Safely eval code from text file--suggestions?

J

JS Bangs

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.

--
Jesse S. Bangs (e-mail address removed)
http://students.washington.edu/jaspax/
http://students.washington.edu/jaspax/blog

Jesus asked them, "Who do you say that I am?"

And they answered, "You are the eschatological manifestation of the ground
of our being, the kerygma in which we find the ultimate meaning of our
interpersonal relationship."

And Jesus said, "What?"
 
J

James Willmore

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.
Suggestions very welcome.

Correct me if I'm wrong, but you would like to do something like SAX?
If so, there are some modules to aid you in this on CPAN.

That's my two cents.
 
C

Charles DeRykus

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);
}
}

Wouldn't you almost certainly want to use the core Safe module
in case other wickedness creeps into the code...

HTH,
 
B

Benjamin Goldberg

JS said:
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.
 
J

JS Bangs

Benjamin Goldberg sikyal:
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]

This works very well. Thank you! I hadn't ever heard of the Safe module
before, so thanks for pointing this out to me.
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.

Right. I'm actually letting general security issues within the code in
$parse->{$_} be Somebody Else's Problem. As the module writer, I need to
make sure that the code doesn't alter the internals of my module, but
making sure that the code doesn't maliciously use system() calls or do
other insecure buggery will be the responsibility of the person using the
module and providing the XML to parse.

--
Jesse S. Bangs (e-mail address removed)
http://students.washington.edu/jaspax/
http://students.washington.edu/jaspax/blog

Jesus asked them, "Who do you say that I am?"

And they answered, "You are the eschatological manifestation of the ground
of our being, the kerygma in which we find the ultimate meaning of our
interpersonal relationship."

And Jesus said, "What?"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top