Help -- how to execute "computed Perl code"

S

Steve D

My code dynamically creates a scalar with a text string that is a
valid Perl code line.

How can I get Perl to execute the line contained in that scalar?

I could write it to a temp file and then "do <file>", but I want to
avoid that overhead. It does not seem eval and "do BLOCK" are the
answer.

Any good solutions?

Regards,
Steve D

Basic idea:

$x = "Send A message 13 ;" ;
# how can I execute $x to call (defined in a different module) the
subroutine:
# Send ($;@) {...}

Just putting
Send A message 13 ;
at the point of interest does run "Send", so visibility is not a
problem, at least at that point.
 
J

James Willmore

On 1 Sep 2003 18:41:31 -0700
My code dynamically creates a scalar with a text string that is a
valid Perl code line.

How can I get Perl to execute the line contained in that scalar?

I could write it to a temp file and then "do <file>", but I want to
avoid that overhead. It does not seem eval and "do BLOCK" are the
answer.

Any good solutions?

Not sure if this i what you're looking for or not:

==untested==
#!/usr/bin/perl -w
use strict;
#create a reference to a subroutine
#execute the system command 'ls' (Windows, it would be 'dir')
my $code = sub { system("ls") };
#call to the subroutine
$code->();
==untested==

You can apply this idea to whatever it is that you're doing.

HTH
Jim
 
J

James Willmore

On 1 Sep 2003 18:41:31 -0700


Not sure if this i what you're looking for or not:

==untested==
#!/usr/bin/perl -w
use strict;
#create a reference to a subroutine
#execute the system command 'ls' (Windows, it would be 'dir')
my $code = sub { system("ls") };
#call to the subroutine
$code->();
==untested==

You can apply this idea to whatever it is that you're doing.

After I posted, I got to thinking (uh-oh). If you want to see other
examples of what I posted, take a look at the CGI module. Most, if
not all, the code is done the way you (I think) would like to do.

HTH
 
A

Anno Siegel

Steve D said:
My code dynamically creates a scalar with a text string that is a
valid Perl code line.

How can I get Perl to execute the line contained in that scalar?

I could write it to a temp file and then "do <file>", but I want to
avoid that overhead. It does not seem eval and "do BLOCK" are the
answer.

"eval" is the answer, in the string-eval form. What have you tried?

Anno
 
B

Brian McCauley

My code dynamically creates a scalar with a text string that is a
valid Perl code line.

This is a powerful technique but one that should only be used in very
special circumstances.

Unlike some of the regulars here I'm not gripped by a rabid fear of
this technique, indeed I embrace it. But before you use it you must
understand how parsing data as code can easily produce obscure hidden
bugs or security holes.
How can I get Perl to execute the line contained in that scalar?

It does not seem eval [is] the answer.

Why? (Oh and don't forget #line)
Any good solutions?

Dunno. The solution you have rejected (for no apparent reason) is the
solution to your "Y" but there's a fairly good chance it's not a good
solution to your "X"[1].

Since you do not tell us anything about your "X" we can't advise on a
good solution.

[1] An "XY" problem is where you want to do "X" but ask "How do I do
Y?" because you think that doing "Y" is part of doing "X" but actually
doing "Y" is something more complex/riskly/whatever than the direct
solution to doing "X".

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
S

Steve D

NOPE. Your "solution" requires the code text to be known at COMPILE
time.

I need to compile code text that has been create at RUN time. The
following is a complete program example of what I want to do (the
@code_text is just a simple way to define strings -- in reality they
are composed from much more complex circumstances).

As I said, I *could* write @code_text to a file, then "do <file>" to
get the effect I need, but want to avoid writing and reading a file
just to get evaluation of the code.

Regards,
Steve

#! /bin/perl
use strict ; use warnings ;

my $a = 1 ;
my @code_text = ( '$a += 3 ;', '$a /= 2 ;', 'print $a ; ' ) ;

for my $code_text ( @code_text ) {
my $code = sub { $code_text } ;
print "$code_text\n" ;
# DOES NOT WORK
# I want to evaluate the "code" contained in $code_text
# NOT the "value" of $code_text. $a should get 3 added,
# then be divided by 2, and then printed.
$code->() ;
} ;

print "$a should be 2 ( 1 plus 3 divided by 2 )\n"
 
S

Steve D

James,
Your code gave me some ideas. Some more experimentation did finally
come up with a solution:

#! /bin/perl
use strict ; use warnings ;

my $a = 1 ;
my @code_text = ( '$a += 3 ;', '$a /= 2 ;', 'print "$a\n" ; ' ) ;

for my $code_text ( @code_text ) {
my $code = sub { eval "$code_text" } ; # Just need eval to make it
work
print "Executing $code_text\n" ;
$code->() ;
} ;

print "$a should be 2 ( 1 plus 3 divided by 2 )\n"

=================================
The eval in the sub def is the key. I had tried a do of an eval, an
eval of an eval, but never a sub of an eval. That's the key.

Thanks for your help.

Regards,
Steve
 
S

Sam Holden

# I want to evaluate the "code" contained in $code_text
^^^^
And that is what you should do...

(and make sure you understand the risks associated with executing
arbitrary code).
 
S

Simon Taylor

Steve said:
My code dynamically creates a scalar with a text string that is a
valid Perl code line.

How can I get Perl to execute the line contained in that scalar?

I could write it to a temp file and then "do <file>", but I want to
avoid that overhead. It does not seem eval and "do BLOCK" are the
answer.

Any good solutions?

I won't elaborate on the answers in this thread to date, but simply
mention the 'Safe' module. I've found it to be very handy in some
circumstances when you want to execute arbitrary (dynamically created) code.

It allows you to run code in a reasonably safe 'compartment'.

Regards,

Simon Taylor
 
U

Uri Guttman

BM> Unlike some of the regulars here I'm not gripped by a rabid fear of
BM> this technique, indeed I embrace it. But before you use it you must
BM> understand how parsing data as code can easily produce obscure hidden
BM> bugs or security holes.

then you misunderstand why we always say it is evil. i have used string
eval but only as a last resort or where is provides a distinct
advantage. most newbies hear about it and start to use it for every nail
they see when they can usually use perl structures or other concepts
instead of eval. so the mantra here is don't use it (unless you know why
you are using it).

in this thread i still have no clear understanding of the problem
itself, let alone why eval is needed or even better, why it didn't work
at all.

BM> Dunno. The solution you have rejected (for no apparent reason) is the
BM> solution to your "Y" but there's a fairly good chance it's not a good
BM> solution to your "X"[1].

i smell XY problem as well. poorly articulated problems with eval as a
potential (and rejected!) solution reeks of XY.

uri
 
U

Uri Guttman

SD> my $a = 1 ;
SD> my @code_text = ( '$a += 3 ;', '$a /= 2 ;', 'print $a ; ' ) ;

XY all the way.

use a dispatch table. search google for examples with that very
phrase. it crops up every month here. eval is the wrong way to solve it
(and eval would work if you did it correctly. i won't help there since
it is the wrong path for you).

uri
 
U

Uri Guttman

SD> my $a = 1 ;
SD> my @code_text = ( '$a += 3 ;', '$a /= 2 ;', 'print "$a\n" ; ' ) ;

SD> for my $code_text ( @code_text ) {
SD> my $code = sub { eval "$code_text" } ; # Just need eval to make it
SD> work

GACK! that is fugly. use a dispatch table already. you are jumping
through 3 hoops for no reason.

SD> print "Executing $code_text\n" ;
SD> $code->() ;
SD> } ;

you are making closures (and don't even realize it), calling eval in the
wrong place (even as eval is not needed)

SD> The eval in the sub def is the key. I had tried a do of an eval, an
SD> eval of an eval, but never a sub of an eval. That's the key.

no it is not the key.

use a dispatch table.

uri
 
B

Bart Lateur

Steve said:
My code dynamically creates a scalar with a text string that is a
valid Perl code line.

How can I get Perl to execute the line contained in that scalar?

I could write it to a temp file and then "do <file>", but I want to
avoid that overhead. It does not seem eval and "do BLOCK" are the
answer.

"eval" it is.

$string = 'print 3+3;';
print "Let's do it:\n";
eval $string;

Saving it to a temp file and then run "do $file;" would indeed do pretty
much the same.
 
B

Brian McCauley

my $code = sub { eval "$code_text" } ; # Just need eval to make it
$code->() ;

That is pointless.

May as well just:

eval $code_text;

I suspect what you were tring to do was:

my $code = eval "sub { $code_text }";

Apply standard admionishments about being damn sure that $code_text
can never contain any text from any source that would not be trusted
to run their own scripts under the current user ID.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 

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,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top