Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: How to use Safe to compile anonymous subs

by moritz (Cardinal)
on Jul 30, 2008 at 19:01 UTC ( [id://701237]=note: print w/replies, xml ) Need Help??


in reply to How to use Safe to compile anonymous subs

I don't know if that works for you, but you could try to move the evaluation into the subroutine:
#!/usr/bin/perl use Safe; use IO::File; my $code =<<'END'; my $a = ''; my $f = IO::File->new('/etc/passwd'); while (my $l = $f->getline) { $a .= $l } return $a; END my $compartment = Safe->new; $safe = sub { $compartment->reval($code) || die $@}; print $safe->();

This way the reval complains with Can't locate object method "new" via package "IO::File", which seems to me what you want (and a use is caught).

Replies are listed 'Best First'.
Re^2: How to use Safe to compile anonymous subs
by lstein (Novice) on Jul 30, 2008 at 19:27 UTC
    Thanks, but using the suggested pattern, I don't understand how to pass arguments to the inner code:
    my $code = 'my $a = shift; warn $a'; my $compartment = Safe->new(':default'); $safe = sub { $compartment->reval($code) || die $@ }; $safe->(42);
    Is there any way to do this?
      You can by sharing variables. Somehow I didn't manage to do with simply sharing a variable and localizing it, but I'm quite sure it can be done.

      This is my workaround for now:

      #!/usr/bin/perl use Safe; use IO::File; our @args; my $code =<<'END'; my @args = pass_options(); return "Arguments: @args\n"; END my $compartment = Safe->new; sub pass_options { @args }; $compartment->share('&pass_options'); $safe = sub { local @args = @_; $compartment->reval($code) || die $@}; print $safe->(1, 2, 3); __END__ Arguments: 123

      This takes the sideway of sharing a sub that returns the arguments. Not ideal, but at least it works.

      This seems to work. The localised copy is shared into the compartments namespace.
      #!/usr/bin/perl use Safe; use IO::File; my $compartment = Safe->new; my $safe = sub { local @SHAREDARGS = @_; $compartment->share('@SHAREDARGS'); my $code = 'print "Got: ", join (", ", @SHAREDARGS),"\n" +'; $compartment->reval($code) || die "die $@" }; print $safe->(42, 47, 11 , "xyz"); __END__ Got: 42, 47, 11, xyz
      What you want is probably:

      my $code = 'sub { my $arg = shift; warn $arg; }';

      Update: Since the above looks alot like your original post, here is more.

      I've never used Safe but my doc's indicate that you need a namespace as the first arg to Safe->new.

      use Safe; my $code = 'sub { my $arg = shift; warn $arg; }'; my $safe = Safe->new(); my $ssub = $safe->reval( $code) || die ; $ssub->( "hello$/" ); &$ssub( "hello$/" );

      Be well,
      rir

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://701237]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2024-04-24 00:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found