I'm using Perl 5.22.1. Safe 2.39
I'm debugging a program which incidentally runs code in a Safe compartment. The code executes a subroutine shared from another package. I'm not interested in the code running in the compartment, but cannot avoid its execution. The Perl debugger croaks inside the compartment when the shared subroutine is executed.
Here's test code:
use warnings;
use strict;
use Safe;
sub MyPkg::foo { 33; }
my $safe= Safe->new;
$safe->share_from( 'MyPkg', [ '&foo' ] );
print $safe->reval(q[foo]), "\n";
print STDERR $@ if $@;
When run directly, I get the expected output:
% perl tdebug.pl
33
However, when run under the Perl debugger, the debugger is very unhappy:
% perl -d tdebug.pl
Loading DB routines from perl5db.pl version 1.49
Editor support available.
Enter h or 'h h' for help, or 'man perldebug' for more help.
main::(tdebug.pl:8): my $safe= Safe->new;
DB<1> c
Undefined subroutine &MyPkg::foo called at [...]/lib/5.22.1/perl5db.pl line 4183.
Debugged program terminated.
I deduce that the debugger is attempting to execute the shared subroutine by using its original name, and since that is not available in the compartment, cannot access it.
I can think of two approaches to side step this:
caller
, etc see them as being in the compartment (e.g. with Sub::Name::subname )I've attempted to implement the first approach, as follows,
use warnings;
use strict;
use Safe;
{ package MyPkg;
sub foo { 33; }
}
use Sub::Name;
use Opcode 'empty_opset';
my $safe= Safe->new;
$safe->mask( empty_opset() );
$safe->share_from( 'MyPkg', [ '&foo' ] );
$safe->reval( q[use Sub::Name;]) or die "use Sub::Name: ", $@;
$safe->reval( q[subname foo => \&foo; 1;]) or die "subname call", $@;
$safe->permit_only( ':default' );
print $safe->reval( q[ foo ] ), "\n";
print STDERR $@ if $@;
but am stymied by the following run time error:
use Sub::Name: Can't load module Sub::Name, dynamic loading not available in this perl.
(You may need to build a new perl executable which either supports
dynamic loading or has the Sub::Name module statically linked into it.)
at (eval 6) line 1.
Compilation failed in require at (eval 6) line 1.
BEGIN failed--compilation aborted at (eval 6) line 1.
As for approach 2, would anyone have any ideas on how to implement that?
Forget about Sub::Name trickery for the debugger. It's also a very broken module. Simple glob assignment (core aliases) or coderef assignment is always easier.
As @ThisSuitIsBlackNot already found out, you need to add more shares, the one from the main:: stash to the loaded module, and need to use the full name in the safe compartment.
use warnings;
use strict;
use Safe;
sub MyPkg::foo { 33; }
my $safe= Safe->new;
$safe->share_from( 'MyPkg', [ '&foo' ] );
$safe->share_from( 'main', [ 'MyPkg::foo' ] );
print $safe->reval(q[MyPkg::foo]);
print STDERR $@ if $@;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With