Re: limiting scope of 'eval'??
by edan (Curate) on Aug 22, 2004 at 07:20 UTC
|
You might want to look at the Safe module, paying particular attention to the reval method:
reval (STRING)
This evaluates STRING as perl code inside the compartment.
The code can only see the compartment's namespace (as returned by the root method). The compartment's root package appears to be the main:: package to the code inside the compartment.
Update: I just saw sgifford's reply tucked away there, saying the same thing. :)
| [reply] |
Re: limiting scope of 'eval'??
by dragonchild (Archbishop) on Aug 22, 2004 at 03:16 UTC
|
One possible idea would be to scope all your variables as package-scoped variables (not using 'my' at all) and then putting all your eval'ed code within another package. Something like the untested
package Foo;
$Foo::var1 = 'VAR_A';
my $pkg = '_eval_';
$Foo::var2 = <<"__END_EVAL__";
package $pkg;
print "VAR_B( \$${pkg}::var1 )\\n";
__END_EVAL__
eval $Foo::var2;
In other words, you could, but it would be very messy and would require you to code in a completely odd style. The issue you're running into is that eval'ed code is compiled and executed within the context that the eval() call has.
More importantly - why are you wanting to do this? There most likely is a better way to do what you're trying to do ...
------
We are the carpenters and bricklayers of the Information Age.
Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose
I shouldn't have to say this, but any code, unless otherwise stated, is untested
| [reply] [d/l] |
Re: limiting scope of 'eval'??
by BrowserUk (Patriarch) on Aug 22, 2004 at 03:07 UTC
|
$a = "VAR_A";
$b = qq[
package Nowhere;
local ( $/, $_, $@, $0, $a, $b ); ## etc.
print "VAR_B (\$a)\n";
];
eval $b;
I'm not quite sure what you expect from \$a though, except an error?
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] [d/l] |
|
|
You either have to use q instead of qq, or escape all your $ signs, otherwise they will be interpolated when you assign them to b instead of at eval time.
So his use of \$a is correct afaik
| [reply] [d/l] [select] |
Re: limiting scope of 'eval'??
by sgifford (Prior) on Aug 22, 2004 at 03:32 UTC
|
If you want to completely prevent the eval'd code from accessing outside variables, maybe you should run it with the Safe module.
| [reply] [d/l] |
Re: limiting scope of 'eval'??
by SciDude (Friar) on Aug 22, 2004 at 03:18 UTC
|
$a = "VAR_A";
$b = 'print \'VAR_B (\$a)\\n\'';
eval $b;
SciDude
The first dog barks... all other dogs bark at the first dog.
| [reply] [d/l] |
Re: limiting scope of 'eval'??
by ikegami (Patriarch) on Aug 22, 2004 at 03:20 UTC
|
In fact, I'd like to hide from the eval'd code all variables and functions that were declared outside of it. Is this possible?
All 'my' variables can be hidden with the code below, but the others are trickier. If you can take the performance hit, use system to run the code in a seperate interpreter if you can.
# Before any 'my'. Put in a seperate module if necessary.
# Use eval_it instead of eval.
sub eval_it { eval shift; }
| [reply] [d/l] |
|
|
Ok, here are more details about the application...
I've got a CGI program "index.pl". This script reads from a flat-file some of the content that will be printed as the web response. However, I want to be able to interpret macros (in perl) from the static file text... So
flatfile:
Today is <% $a = localtime(time); print $a; %>
And index.pl is (basically):
my $a = "important value";
# open flatfile here...
# use index and substr to find macro strings delimited with <% ... %>
# loop through found macros
eval($macro)
# replace macro code with eval value
# print resulting text
# keep using variable $a, expecting the value will still be "important
+ value"...
So here, I'd like a user to be able to use their own variables, and not be able to (even accidentily) mess up the calling script's scoped variables/functions.
| [reply] [d/l] [select] |
|
|
Kaboom! <% system(rm *) %>
or other (possibly inadvertent) malicious code?
Will index.pl run this code?
| [reply] [d/l] |
|
|
Perhaps your are re-inventing the wheel for the furtherance of your own knowledge, or as a homework assignment. Otherwise, I can't help but wonder why you aren't using one of the existing templating systems out there, like Template Toolkit (http://template-toolkit.org)... ?
| [reply] |
|
|
|
|
Re: limiting scope of 'eval'??
by eric256 (Parson) on Aug 22, 2004 at 07:05 UTC
|
I just wanted to point out that I couldn't get any of the posted answers to work. Perhaps its a flaw in the way I implemented them so below is the code i tried and its output.
use strict;
use warnings;
my $test = q[print $a;];
my $a = "doesn't stop me\n";
sub eval_it {
eval shift;
}
{ package safezone;
sub eval_it {
eval shift;
}
}
warn "regular eval";
eval $test;
warn "eval_it";
eval_it $test;
warn "safezone::eval_it";
safezone::eval_it $test;
warn "Prepend package";
eval "package safezone; $test";
__DATA__
regular eval at eval.pl line 18.
doesn't stop me
eval_it at eval.pl line 21.
doesn't stop me
safezone::eval_it at eval.pl line 24.
doesn't stop me
Prepend package at eval.pl line 27.
doesn't stop me
| [reply] [d/l] |
|
|
{ package safezone;
local $a;
sub eval_it {
eval shift;
}
}
Of course since you need a declaration for all variables you want to hide, this can get cumbersome rather quickly, but it does work
Update: This blows up with a Can't localize lexical variable $a at x line 12. Using my $a instead of local $a does seem to work here though. | [reply] [d/l] [select] |
|
|
You need to move the sub declarations above the my declarations.
| [reply] |
Re: limiting scope of 'eval'??
by Cody Pendant (Prior) on Aug 23, 2004 at 04:48 UTC
|
I can't believe nobody's posted this -- try not to use $a and $b as variables, as they're used for sorting in Perl.
($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss')
=~y~b-v~a-z~s; print
| [reply] |
|
|
#! perl -slw
use strict;
my( $a, $b ) = ( 'mya', 'myb' );
{
our( $a, $b ) = ( 'oura', 'ourb' );
my @sorted = sort { $a <=> $b } map{ rand 100 } 0 .. 99;
print "$a : $b";
}
print "$a : $b";
__END__
P:\test>test
oura : ourb
mya : myb
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] [d/l] |
|
|
#! perl -slw
use strict;
( $a, $b ) = ( 'mya', 'myb' );
# imagine several lines of intervening code
{
our( $a, $b ) = ( 'oura', 'ourb' );
my @sorted = sort { $a <=> $b } map{ rand 100 } 0 .. 99;
print "$a : $b";
}
print "$a : $b";
__END__
C:\s>perl sortab.pl
oura : ourb
oura : ourb #no warnings, $a and $b are quietly changed
The script dies if they are declared (with my instead of our) in the same scope as the sort routine:
#! perl -slw
use strict;
my( $a, $b ) = ( 'mya', 'myb' );
{
my( $a, $b ) = ( 'oura', 'ourb' );
my @sorted = sort { $a <=> $b } map{ rand 100 } 0 .. 99;
print "$a : $b";
}
print "$a : $b";
__END__
C:\S\pl>perl sortab.pl
Can't use "my $a" in sort comparison at sortab.pl line 10.
Update: Deleted extra code tag | [reply] [d/l] [select] |