summaryrefslogtreecommitdiff
path: root/dist/Safe
diff options
context:
space:
mode:
authorRafael Garcia-Suarez <rgs@consttype.org>2010-03-06 22:30:47 +0100
committerRafael Garcia-Suarez <rgs@consttype.org>2010-03-06 22:34:53 +0100
commit16ac9e9a4185d3315152ade5286d4dd3d25bff32 (patch)
tree945130c91c4a9fd8d76de6d8706522d20c8b5432 /dist/Safe
parentefbe327085cc15510d8c261772e9ac21be3635de (diff)
downloadperl-16ac9e9a4185d3315152ade5286d4dd3d25bff32.tar.gz
Clean the stashes from the Safe compartment after evaluation of code.
This way, objects created from inside the Safe compartment won't be able to call transparently code compiled in the Safe compartment, without the restrictions being anymore in place.
Diffstat (limited to 'dist/Safe')
-rw-r--r--dist/Safe/Safe.pm30
1 files changed, 28 insertions, 2 deletions
diff --git a/dist/Safe/Safe.pm b/dist/Safe/Safe.pm
index e0b7dcaa5e..12dd77719d 100644
--- a/dist/Safe/Safe.pm
+++ b/dist/Safe/Safe.pm
@@ -3,6 +3,7 @@ package Safe;
use 5.003_11;
use strict;
use Scalar::Util qw(reftype);
+use B qw(sub_generation);
$Safe::VERSION = "2.23";
@@ -319,6 +320,19 @@ sub varglob {
return *{$obj->root()."::$var"};
}
+sub _clean_stash {
+ my ($root) = @_;
+ my @destroys;
+ no strict 'refs';
+ push @destroys, delete ${$root}{DESTROY};
+ push @destroys, delete ${$root}{AUTOLOAD};
+ push @destroys, delete ${$root}{$_} for grep /^\(/, keys %$root;
+
+ for (grep /::$/, keys %$root) {
+ next if $_ eq 'main::';
+ _clean_stash($root.$_);
+ }
+}
sub reval {
my ($obj, $expr, $strict) = @_;
@@ -326,7 +340,12 @@ sub reval {
my $evalsub = lexless_anon_sub($root, $strict, $expr);
# propagate context
- return Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub);
+ my $sg = sub_generation();
+ my @subret = (wantarray)
+ ? Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub)
+ : scalar Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub);
+ _clean_stash($root.'::') if $sg != sub_generation();
+ return (wantarray) ? @subret : $subret[0];
}
@@ -375,10 +394,12 @@ sub wrap_code_ref {
my $error;
do {
local $@; # needed due to perl_call_sv(sv, G_EVAL|G_KEEPERR)
+ my $sg = sub_generation();
@subret = (wantarray)
? Opcode::_safe_call_sv($obj->{Root}, $obj->{Mask}, $sub_with_args)
: scalar Opcode::_safe_call_sv($obj->{Root}, $obj->{Mask}, $sub_with_args);
$error = $@;
+ _clean_stash($obj->{Root}.'::') if $sg != sub_generation();
};
if ($error) { # rethrow exception
$error =~ s/\t\(in cleanup\) //; # prefix added by G_KEEPERR
@@ -395,9 +416,14 @@ sub rdo {
my ($obj, $file) = @_;
my $root = $obj->{Root};
+ my $sg = sub_generation();
my $evalsub = eval
sprintf('package %s; sub { @_ = (); do $file }', $root);
- return Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub);
+ my @subret = (wantarray)
+ ? Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub)
+ : scalar Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub);
+ _clean_stash($root.'::') if $sg != sub_generation();
+ return (wantarray) ? @subret : $subret[0];
}