jeremyh has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I'm using Safe->reval to check if a generated perl expression is true.
I want to allow that perl expression to use a method from a custom perl module.
This method also uses Safe->reval (in a new compartment).
I can't get the nested reval to work (it works fine if called directly).

Here is the code:

The method in the custom module WOU_Util
my $compartment = new Safe; # module level $compartment->permit(qw()); # module level sub date_compare { my ($date, $op, $refdate) = @_; my ($mm_date, $dd_date, $yyyy_date) = split(/\//, $date); my ($mm_ref, $dd_ref, $yyyy_ref) = split(/\//, $refdate); my $date_str = $yyyy_date . $mm_date . $dd_date; my $ref_str = $yyyy_ref . $mm_ref . $dd_ref; $compartment->reval( qq{ ($date_str $op $ref_str) || return 0; # fall-through return 1; } ); }

And here's some test code that calls the method:
#!/usr/bin/perl -w use strict; use Safe; use WOU_Util; my $compartment = new Safe; $compartment->share_from('WOU_Util', [ 'date_compare' ] ); $compartment->permit( qw() ); my ($date1, $op, $date2); $date1 = '01/02/2004'; $date2 = '01/01/2004'; $op = 'gt'; # this prints $compartment->reval( "print 'greater' if \"$date1\" $op \"$date2\"" ); $op = '>'; # this doesn't print, throws error $compartment->reval( "print 'greater' if date_compare(\"$date1\",\"$op +\",\"$date2\")" );

The error is:
Use of uninitialized value in null operation at /usr/lib/perl5/5.6.1/i386-linux/ line 222.
(in cleanup) Undefined subroutine &Safe::Root0:: called at /usr/lib/perl5/5.6.1/i386-linux/ line 222.

Replies are listed 'Best First'.
Re: nested Safe->reval and method from custom Module
by gmpassos (Priest) on Sep 15, 2004 at 17:43 UTC
    The permit() method allow new operators over the already allowed list of operators, so, permit(qw()) does nothing.

    If you want to permit all you should use deny_only() without arguments, that will allow everything.

    Graciliano M. P.
    "Creativity is the expression of the liberty".

      Answered my own question thanks to a hint from samtregar about eval and $@ (on a different thread!).
      It needed
      $compartment->permit( qw( entereval ) );

      the nested eval was trapped by the opcode mask of the first eval.
      Thanks, I discovered that the other day when I was reading the documentation.

      What I had wanted was to deny everything so I guess I want permit_only