summaryrefslogtreecommitdiff
path: root/dist/Safe/Safe.pm
diff options
context:
space:
mode:
authorTim Bunce <Tim.Bunce@pobox.com>2009-12-01 00:15:21 +0100
committerRafael Garcia-Suarez <rgs@consttype.org>2009-12-01 00:16:41 +0100
commit576b33a19ccaf98d4dfe201d529c55c3747f0cb6 (patch)
tree09782e2c22c0e7ce60311bbc0c3bb88816db6a6e /dist/Safe/Safe.pm
parent2e0a827f13b2065625fa468c74693fcff824b17f (diff)
downloadperl-576b33a19ccaf98d4dfe201d529c55c3747f0cb6.tar.gz
[rt.cpan.org #51574] Safe.pm sort {} bug accessing $a and $b with -Dusethreads
Diffstat (limited to 'dist/Safe/Safe.pm')
-rw-r--r--dist/Safe/Safe.pm25
1 files changed, 23 insertions, 2 deletions
diff --git a/dist/Safe/Safe.pm b/dist/Safe/Safe.pm
index 6926a4e369..4313263952 100644
--- a/dist/Safe/Safe.pm
+++ b/dist/Safe/Safe.pm
@@ -2,6 +2,9 @@ package Safe;
use 5.003_11;
use strict;
+use Scalar::Util qw(reftype);
+use Config qw(%Config);
+use constant is_usethreads => $Config{usethreads};
$Safe::VERSION = "2.19";
@@ -288,8 +291,26 @@ sub reval {
my ($obj, $expr, $strict) = @_;
my $root = $obj->{Root};
- my $evalsub = lexless_anon_sub($root,$strict, $expr);
- return Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub);
+ my $evalsub = lexless_anon_sub($root, $strict, $expr);
+ my @ret = (wantarray)
+ ? Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub)
+ : scalar Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub);
+
+ # RT#60374: Safe.pm sort {} bug with -Dusethreads
+ # If the Safe eval returns a code ref in a perl compiled with usethreads
+ # then wrap code ref with _safe_call_sv so that, when called, the
+ # execution will happen with the compartment fully 'in effect'.
+ # Needed to fix sort blocks that reference $a & $b and
+ # possibly other subtle issues.
+ if (is_usethreads()) {
+ for my $ret (@ret) { # edit (via alias) any CODE refs
+ next unless (reftype($ret)||'') eq 'CODE';
+ my $sub = $ret; # avoid closure problems
+ $ret = sub { Opcode::_safe_call_sv($root, $obj->{Mask}, $sub) };
+ }
+ }
+
+ return (wantarray) ? @ret : $ret[0];
}
sub rdo {