line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Safe; |
2
|
|
|
|
|
|
|
|
3
|
10
|
|
|
10
|
|
229654
|
use 5.003_11; |
|
10
|
|
|
|
|
37
|
|
|
10
|
|
|
|
|
449
|
|
4
|
10
|
|
|
10
|
|
61
|
use Scalar::Util qw(reftype refaddr); |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
2031
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
$Safe::VERSION = "2.35"; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# *** Don't declare any lexicals above this point *** |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# This function should return a closure which contains an eval that can't |
11
|
|
|
|
|
|
|
# see any lexicals in scope (apart from __ExPr__ which is unavoidable) |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
sub lexless_anon_sub { |
14
|
|
|
|
|
|
|
# $_[0] is package; |
15
|
|
|
|
|
|
|
# $_[1] is strict flag; |
16
|
42
|
|
|
42
|
0
|
71
|
my $__ExPr__ = $_[2]; # must be a lexical to create the closure that |
17
|
|
|
|
|
|
|
# can be used to pass the value into the safe |
18
|
|
|
|
|
|
|
# world |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# Create anon sub ref in root of compartment. |
21
|
|
|
|
|
|
|
# Uses a closure (on $__ExPr__) to pass in the code to be executed. |
22
|
|
|
|
|
|
|
# (eval on one line to keep line numbers as expected by caller) |
23
|
42
|
50
|
|
|
|
4225
|
eval sprintf |
24
|
|
|
|
|
|
|
'package %s; %s sub { @_=(); eval q[local *SIG; my $__ExPr__;] . $__ExPr__; }', |
25
|
|
|
|
|
|
|
$_[0], $_[1] ? 'use strict;' : ''; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
10
|
|
|
10
|
|
51
|
use strict; |
|
10
|
|
|
|
|
22
|
|
|
10
|
|
|
|
|
317
|
|
29
|
10
|
|
|
10
|
|
49
|
use Carp; |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
727
|
|
30
|
10
|
|
|
10
|
|
669
|
BEGIN { eval q{ |
|
10
|
|
|
10
|
|
8382
|
|
|
10
|
|
|
|
|
1506
|
|
|
10
|
|
|
|
|
332
|
|
31
|
|
|
|
|
|
|
use Carp::Heavy; |
32
|
|
|
|
|
|
|
} } |
33
|
|
|
|
|
|
|
|
34
|
10
|
|
|
10
|
|
55
|
use B (); |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
225
|
|
35
|
|
|
|
|
|
|
BEGIN { |
36
|
10
|
|
|
10
|
|
44
|
no strict 'refs'; |
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
723
|
|
37
|
10
|
50
|
|
10
|
|
46
|
if (defined &B::sub_generation) { |
38
|
10
|
|
|
|
|
287
|
*sub_generation = \&B::sub_generation; |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
else { |
41
|
|
|
|
|
|
|
# fake sub generation changing for perls < 5.8.9 |
42
|
0
|
|
|
|
|
0
|
my $sg; *sub_generation = sub { ++$sg }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
10
|
|
|
|
|
7495
|
use Opcode 1.01, qw( |
47
|
|
|
|
|
|
|
opset opset_to_ops opmask_add |
48
|
|
|
|
|
|
|
empty_opset full_opset invert_opset verify_opset |
49
|
|
|
|
|
|
|
opdesc opcodes opmask define_optag opset_to_hex |
50
|
10
|
|
|
10
|
|
6826
|
); |
|
10
|
|
|
|
|
42463
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
*ops_to_opset = \&opset; # Temporary alias for old Penguins |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Regular expressions and other unicode-aware code may need to call |
55
|
|
|
|
|
|
|
# utf8->SWASHNEW (via perl's utf8.c). That will fail unless we share the |
56
|
|
|
|
|
|
|
# SWASHNEW method. |
57
|
|
|
|
|
|
|
# Sadly we can't just add utf8::SWASHNEW to $default_share because perl's |
58
|
|
|
|
|
|
|
# utf8.c code does a fetchmethod on SWASHNEW to check if utf8.pm is loaded, |
59
|
|
|
|
|
|
|
# and sharing makes it look like the method exists. |
60
|
|
|
|
|
|
|
# The simplest and most robust fix is to ensure the utf8 module is loaded when |
61
|
|
|
|
|
|
|
# Safe is loaded. Then we can add utf8::SWASHNEW to $default_share. |
62
|
|
|
|
|
|
|
require utf8; |
63
|
|
|
|
|
|
|
# we must ensure that utf8_heavy.pl, where SWASHNEW is defined, is loaded |
64
|
|
|
|
|
|
|
# but without depending on too much knowledge of that implementation detail. |
65
|
|
|
|
|
|
|
# This code (//i on a unicode string) should ensure utf8 is fully loaded |
66
|
|
|
|
|
|
|
# and also loads the ToFold SWASH, unless things change so that these |
67
|
|
|
|
|
|
|
# particular code points don't cause it to load. |
68
|
|
|
|
|
|
|
# (Swashes are cached internally by perl in PL_utf8_* variables |
69
|
|
|
|
|
|
|
# independent of being inside/outside of Safe. So once loaded they can be) |
70
|
10
|
|
|
10
|
|
48
|
do { my $a = pack('U',0x100); my $b = chr 0x101; utf8::upgrade $b; $a =~ /$b/i }; |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
123
|
|
71
|
|
|
|
|
|
|
# now we can safely include utf8::SWASHNEW in $default_share defined below. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
my $default_root = 0; |
74
|
|
|
|
|
|
|
# share *_ and functions defined in universal.c |
75
|
|
|
|
|
|
|
# Don't share stuff like *UNIVERSAL:: otherwise code from the |
76
|
|
|
|
|
|
|
# compartment can 0wn functions in UNIVERSAL |
77
|
|
|
|
|
|
|
my $default_share = [qw[ |
78
|
|
|
|
|
|
|
*_ |
79
|
|
|
|
|
|
|
&PerlIO::get_layers |
80
|
|
|
|
|
|
|
&UNIVERSAL::isa |
81
|
|
|
|
|
|
|
&UNIVERSAL::can |
82
|
|
|
|
|
|
|
&UNIVERSAL::VERSION |
83
|
|
|
|
|
|
|
&utf8::is_utf8 |
84
|
|
|
|
|
|
|
&utf8::valid |
85
|
|
|
|
|
|
|
&utf8::encode |
86
|
|
|
|
|
|
|
&utf8::decode |
87
|
|
|
|
|
|
|
&utf8::upgrade |
88
|
|
|
|
|
|
|
&utf8::downgrade |
89
|
|
|
|
|
|
|
&utf8::native_to_unicode |
90
|
|
|
|
|
|
|
&utf8::unicode_to_native |
91
|
|
|
|
|
|
|
&utf8::SWASHNEW |
92
|
|
|
|
|
|
|
$version::VERSION |
93
|
|
|
|
|
|
|
$version::CLASS |
94
|
|
|
|
|
|
|
$version::STRICT |
95
|
|
|
|
|
|
|
$version::LAX |
96
|
|
|
|
|
|
|
@version::ISA |
97
|
|
|
|
|
|
|
], ($] < 5.010 && qw[ |
98
|
|
|
|
|
|
|
&utf8::SWASHGET |
99
|
|
|
|
|
|
|
]), ($] >= 5.008001 && qw[ |
100
|
|
|
|
|
|
|
&Regexp::DESTROY |
101
|
|
|
|
|
|
|
]), ($] >= 5.010 && qw[ |
102
|
|
|
|
|
|
|
&re::is_regexp |
103
|
|
|
|
|
|
|
&re::regname |
104
|
|
|
|
|
|
|
&re::regnames |
105
|
|
|
|
|
|
|
&re::regnames_count |
106
|
|
|
|
|
|
|
&UNIVERSAL::DOES |
107
|
|
|
|
|
|
|
&version::() |
108
|
|
|
|
|
|
|
&version::new |
109
|
|
|
|
|
|
|
&version::("" |
110
|
|
|
|
|
|
|
&version::stringify |
111
|
|
|
|
|
|
|
&version::(0+ |
112
|
|
|
|
|
|
|
&version::numify |
113
|
|
|
|
|
|
|
&version::normal |
114
|
|
|
|
|
|
|
&version::(cmp |
115
|
|
|
|
|
|
|
&version::(<=> |
116
|
|
|
|
|
|
|
&version::vcmp |
117
|
|
|
|
|
|
|
&version::(bool |
118
|
|
|
|
|
|
|
&version::boolean |
119
|
|
|
|
|
|
|
&version::(nomethod |
120
|
|
|
|
|
|
|
&version::noop |
121
|
|
|
|
|
|
|
&version::is_alpha |
122
|
|
|
|
|
|
|
&version::qv |
123
|
|
|
|
|
|
|
&version::vxs::declare |
124
|
|
|
|
|
|
|
&version::vxs::qv |
125
|
|
|
|
|
|
|
&version::vxs::_VERSION |
126
|
|
|
|
|
|
|
&version::vxs::stringify |
127
|
|
|
|
|
|
|
&version::vxs::new |
128
|
|
|
|
|
|
|
&version::vxs::parse |
129
|
|
|
|
|
|
|
&version::vxs::VCMP |
130
|
|
|
|
|
|
|
]), ($] >= 5.011 && qw[ |
131
|
|
|
|
|
|
|
&re::regexp_pattern |
132
|
|
|
|
|
|
|
]), ($] >= 5.010 && $] < 5.014 && qw[ |
133
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::FETCH |
134
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::STORE |
135
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::DELETE |
136
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::CLEAR |
137
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::EXISTS |
138
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::FIRSTKEY |
139
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::NEXTKEY |
140
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::SCALAR |
141
|
|
|
|
|
|
|
&Tie::Hash::NamedCapture::flags |
142
|
|
|
|
|
|
|
])]; |
143
|
|
|
|
|
|
|
if (defined $Devel::Cover::VERSION) { |
144
|
|
|
|
|
|
|
push @$default_share, '&Devel::Cover::use_file'; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub new { |
148
|
17
|
|
|
17
|
1
|
5192
|
my($class, $root, $mask) = @_; |
149
|
17
|
|
|
|
|
37
|
my $obj = {}; |
150
|
17
|
|
|
|
|
42
|
bless $obj, $class; |
151
|
|
|
|
|
|
|
|
152
|
17
|
100
|
|
|
|
235
|
if (defined($root)) { |
153
|
5
|
50
|
33
|
|
|
66
|
croak "Can't use \"$root\" as root name" |
154
|
|
|
|
|
|
|
if $root =~ /^main\b/ or $root !~ /^\w[:\w]*$/; |
155
|
5
|
|
|
|
|
48
|
$obj->{Root} = $root; |
156
|
5
|
|
|
|
|
14
|
$obj->{Erase} = 0; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
else { |
159
|
12
|
|
|
|
|
77
|
$obj->{Root} = "Safe::Root".$default_root++; |
160
|
12
|
|
|
|
|
31
|
$obj->{Erase} = 1; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# use permit/deny methods instead till interface issues resolved |
164
|
|
|
|
|
|
|
# XXX perhaps new Safe 'Root', mask => $mask, foo => bar, ...; |
165
|
17
|
50
|
|
|
|
54
|
croak "Mask parameter to new no longer supported" if defined $mask; |
166
|
17
|
|
|
|
|
90
|
$obj->permit_only(':default'); |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# We must share $_ and @_ with the compartment or else ops such |
169
|
|
|
|
|
|
|
# as split, length and so on won't default to $_ properly, nor |
170
|
|
|
|
|
|
|
# will passing argument to subroutines work (via @_). In fact, |
171
|
|
|
|
|
|
|
# for reasons I don't completely understand, we need to share |
172
|
|
|
|
|
|
|
# the whole glob *_ rather than $_ and @_ separately, otherwise |
173
|
|
|
|
|
|
|
# @_ in non default packages within the compartment don't work. |
174
|
17
|
|
|
|
|
68
|
$obj->share_from('main', $default_share); |
175
|
|
|
|
|
|
|
|
176
|
17
|
50
|
|
|
|
195
|
Opcode::_safe_pkg_prep($obj->{Root}) if($Opcode::VERSION > 1.04); |
177
|
|
|
|
|
|
|
|
178
|
17
|
|
|
|
|
50
|
return $obj; |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub DESTROY { |
182
|
17
|
|
|
17
|
|
10853
|
my $obj = shift; |
183
|
17
|
100
|
|
|
|
640
|
$obj->erase('DESTROY') if $obj->{Erase}; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub erase { |
187
|
15
|
|
|
15
|
0
|
28
|
my ($obj, $action) = @_; |
188
|
15
|
|
|
|
|
36
|
my $pkg = $obj->root(); |
189
|
15
|
|
|
|
|
21
|
my ($stem, $leaf); |
190
|
|
|
|
|
|
|
|
191
|
10
|
|
|
10
|
|
171
|
no strict 'refs'; |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
6151
|
|
192
|
15
|
|
|
|
|
42
|
$pkg = "main::$pkg\::"; # expand to full symbol table name |
193
|
15
|
|
|
|
|
102
|
($stem, $leaf) = $pkg =~ m/(.*::)(\w+::)$/; |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# The 'my $foo' is needed! Without it you get an |
196
|
|
|
|
|
|
|
# 'Attempt to free unreferenced scalar' warning! |
197
|
15
|
|
|
|
|
28
|
my $stem_symtab = *{$stem}{HASH}; |
|
15
|
|
|
|
|
71
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
#warn "erase($pkg) stem=$stem, leaf=$leaf"; |
200
|
|
|
|
|
|
|
#warn " stem_symtab hash ".scalar(%$stem_symtab)."\n"; |
201
|
|
|
|
|
|
|
# ", join(', ', %$stem_symtab),"\n"; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# delete $stem_symtab->{$leaf}; |
204
|
|
|
|
|
|
|
|
205
|
15
|
|
|
|
|
57
|
my $leaf_glob = $stem_symtab->{$leaf}; |
206
|
15
|
|
|
|
|
19
|
my $leaf_symtab = *{$leaf_glob}{HASH}; |
|
15
|
|
|
|
|
37
|
|
207
|
|
|
|
|
|
|
# warn " leaf_symtab ", join(', ', %$leaf_symtab),"\n"; |
208
|
15
|
|
|
|
|
590
|
%$leaf_symtab = (); |
209
|
|
|
|
|
|
|
#delete $leaf_symtab->{'__ANON__'}; |
210
|
|
|
|
|
|
|
#delete $leaf_symtab->{'foo'}; |
211
|
|
|
|
|
|
|
#delete $leaf_symtab->{'main::'}; |
212
|
|
|
|
|
|
|
# my $foo = undef ${"$stem\::"}{"$leaf\::"}; |
213
|
|
|
|
|
|
|
|
214
|
15
|
100
|
66
|
|
|
188
|
if ($action and $action eq 'DESTROY') { |
215
|
12
|
|
|
|
|
93
|
delete $stem_symtab->{$leaf}; |
216
|
|
|
|
|
|
|
} else { |
217
|
3
|
|
|
|
|
10
|
$obj->share_from('main', $default_share); |
218
|
|
|
|
|
|
|
} |
219
|
15
|
|
|
|
|
695
|
1; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub reinit { |
224
|
0
|
|
|
0
|
0
|
0
|
my $obj= shift; |
225
|
0
|
|
|
|
|
0
|
$obj->erase; |
226
|
0
|
|
|
|
|
0
|
$obj->share_redo; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub root { |
230
|
52
|
|
|
52
|
1
|
68
|
my $obj = shift; |
231
|
52
|
50
|
|
|
|
159
|
croak("Safe root method now read-only") if @_; |
232
|
52
|
|
|
|
|
173
|
return $obj->{Root}; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub mask { |
237
|
3
|
|
|
3
|
1
|
599
|
my $obj = shift; |
238
|
3
|
100
|
|
|
|
15
|
return $obj->{Mask} unless @_; |
239
|
1
|
|
|
|
|
4
|
$obj->deny_only(@_); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# v1 compatibility methods |
243
|
1
|
|
|
1
|
1
|
9
|
sub trap { shift->deny(@_) } |
244
|
0
|
|
|
0
|
1
|
0
|
sub untrap { shift->permit(@_) } |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub deny { |
247
|
3
|
|
|
3
|
1
|
13
|
my $obj = shift; |
248
|
3
|
|
|
|
|
29
|
$obj->{Mask} |= opset(@_); |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
sub deny_only { |
251
|
2
|
|
|
2
|
1
|
8
|
my $obj = shift; |
252
|
2
|
|
|
|
|
19
|
$obj->{Mask} = opset(@_); |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub permit { |
256
|
3
|
|
|
3
|
1
|
16
|
my $obj = shift; |
257
|
|
|
|
|
|
|
# XXX needs testing |
258
|
3
|
|
|
|
|
37
|
$obj->{Mask} &= invert_opset opset(@_); |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
sub permit_only { |
261
|
19
|
|
|
19
|
1
|
35
|
my $obj = shift; |
262
|
19
|
|
|
|
|
171
|
$obj->{Mask} = invert_opset opset(@_); |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
sub dump_mask { |
267
|
0
|
|
|
0
|
0
|
0
|
my $obj = shift; |
268
|
0
|
|
|
|
|
0
|
print opset_to_hex($obj->{Mask}),"\n"; |
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub share { |
273
|
5
|
|
|
5
|
1
|
565
|
my($obj, @vars) = @_; |
274
|
5
|
|
|
|
|
18
|
$obj->share_from(scalar(caller), \@vars); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub share_from { |
279
|
25
|
|
|
25
|
1
|
42
|
my $obj = shift; |
280
|
25
|
|
|
|
|
39
|
my $pkg = shift; |
281
|
25
|
|
|
|
|
33
|
my $vars = shift; |
282
|
25
|
|
50
|
|
|
138
|
my $no_record = shift || 0; |
283
|
25
|
|
|
|
|
98
|
my $root = $obj->root(); |
284
|
25
|
50
|
|
|
|
94
|
croak("vars not an array ref") unless ref $vars eq 'ARRAY'; |
285
|
10
|
|
|
10
|
|
61
|
no strict 'refs'; |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
5623
|
|
286
|
|
|
|
|
|
|
# Check that 'from' package actually exists |
287
|
25
|
|
|
|
|
101
|
croak("Package \"$pkg\" does not exist") |
288
|
25
|
50
|
|
|
|
32
|
unless keys %{"$pkg\::"}; |
289
|
25
|
|
|
|
|
32
|
my $arg; |
290
|
25
|
|
|
|
|
67
|
foreach $arg (@$vars) { |
291
|
|
|
|
|
|
|
# catch some $safe->share($var) errors: |
292
|
1029
|
|
|
|
|
995
|
my ($var, $type); |
293
|
1029
|
100
|
|
|
|
4219
|
$type = $1 if ($var = $arg) =~ s/^(\W)//; |
294
|
|
|
|
|
|
|
# warn "share_from $pkg $type $var"; |
295
|
1029
|
|
|
|
|
1659
|
for (1..2) { # assign twice to avoid any 'used once' warnings |
296
|
2058
|
|
|
|
|
8888
|
*{$root."::$var"} = (!$type) ? \&{$pkg."::$var"} |
|
82
|
|
|
|
|
179
|
|
|
1720
|
|
|
|
|
4439
|
|
297
|
170
|
|
|
|
|
495
|
: ($type eq '&') ? \&{$pkg."::$var"} |
298
|
42
|
|
|
|
|
147
|
: ($type eq '$') ? \${$pkg."::$var"} |
299
|
2
|
|
|
|
|
4
|
: ($type eq '@') ? \@{$pkg."::$var"} |
300
|
42
|
|
|
|
|
101
|
: ($type eq '%') ? \%{$pkg."::$var"} |
301
|
2058
|
50
|
|
|
|
4220
|
: ($type eq '*') ? *{$pkg."::$var"} |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
302
|
|
|
|
|
|
|
: croak(qq(Can't share "$type$var" of unknown type)); |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
} |
305
|
25
|
50
|
33
|
|
|
206
|
$obj->share_record($pkg, $vars) unless $no_record or !$vars; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
sub share_record { |
310
|
25
|
|
|
25
|
0
|
42
|
my $obj = shift; |
311
|
25
|
|
|
|
|
50
|
my $pkg = shift; |
312
|
25
|
|
|
|
|
33
|
my $vars = shift; |
313
|
25
|
|
100
|
|
|
35
|
my $shares = \%{$obj->{Shares} ||= {}}; |
|
25
|
|
|
|
|
173
|
|
314
|
|
|
|
|
|
|
# Record shares using keys of $obj->{Shares}. See reinit. |
315
|
25
|
50
|
|
|
|
203
|
@{$shares}{@$vars} = ($pkg) x @$vars if @$vars; |
|
25
|
|
|
|
|
761
|
|
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub share_redo { |
320
|
0
|
|
|
0
|
0
|
0
|
my $obj = shift; |
321
|
0
|
|
0
|
|
|
0
|
my $shares = \%{$obj->{Shares} ||= {}}; |
|
0
|
|
|
|
|
0
|
|
322
|
0
|
|
|
|
|
0
|
my($var, $pkg); |
323
|
0
|
|
|
|
|
0
|
while(($var, $pkg) = each %$shares) { |
324
|
|
|
|
|
|
|
# warn "share_redo $pkg\:: $var"; |
325
|
0
|
|
|
|
|
0
|
$obj->share_from($pkg, [ $var ], 1); |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
sub share_forget { |
331
|
0
|
|
|
0
|
0
|
0
|
delete shift->{Shares}; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub varglob { |
336
|
12
|
|
|
12
|
1
|
3524
|
my ($obj, $var) = @_; |
337
|
10
|
|
|
10
|
|
51
|
no strict 'refs'; |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
749
|
|
338
|
12
|
|
|
|
|
14
|
return *{$obj->root()."::$var"}; |
|
12
|
|
|
|
|
23
|
|
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub _clean_stash { |
342
|
446
|
|
|
446
|
|
560
|
my ($root, $saved_refs) = @_; |
343
|
446
|
|
100
|
|
|
938
|
$saved_refs ||= []; |
344
|
10
|
|
|
10
|
|
49
|
no strict 'refs'; |
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
9696
|
|
345
|
446
|
|
|
|
|
2569
|
foreach my $hook (qw(DESTROY AUTOLOAD), grep /^\(/, keys %$root) { |
346
|
990
|
|
|
|
|
1055
|
push @$saved_refs, \*{$root.$hook}; |
|
990
|
|
|
|
|
3548
|
|
347
|
990
|
|
|
|
|
962
|
delete ${$root}{$hook}; |
|
990
|
|
|
|
|
2823
|
|
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
446
|
|
|
|
|
3901
|
for (grep /::$/, keys %$root) { |
351
|
446
|
100
|
|
|
|
438
|
next if \%{$root.$_} eq \%$root; |
|
446
|
|
|
|
|
1880
|
|
352
|
401
|
|
|
|
|
874
|
_clean_stash($root.$_, $saved_refs); |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub reval { |
357
|
42
|
|
|
42
|
1
|
8940
|
my ($obj, $expr, $strict) = @_; |
358
|
42
|
50
|
|
|
|
267
|
die "Bad Safe object" unless $obj->isa('Safe'); |
359
|
|
|
|
|
|
|
|
360
|
42
|
|
|
|
|
75
|
my $root = $obj->{Root}; |
361
|
|
|
|
|
|
|
|
362
|
42
|
|
|
|
|
230
|
my $evalsub = lexless_anon_sub($root, $strict, $expr); |
363
|
|
|
|
|
|
|
# propagate context |
364
|
42
|
|
|
|
|
137
|
my $sg = sub_generation(); |
365
|
42
|
100
|
|
|
|
3092
|
my @subret = (wantarray) |
366
|
|
|
|
|
|
|
? Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub) |
367
|
|
|
|
|
|
|
: scalar Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub); |
368
|
42
|
50
|
|
|
|
572
|
_clean_stash($root.'::') if $sg != sub_generation(); |
369
|
42
|
|
|
|
|
154
|
$obj->wrap_code_refs_within(@subret); |
370
|
42
|
100
|
|
|
|
492
|
return (wantarray) ? @subret : $subret[0]; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
my %OID; |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
sub wrap_code_refs_within { |
376
|
44
|
|
|
44
|
1
|
1225
|
my $obj = shift; |
377
|
|
|
|
|
|
|
|
378
|
44
|
|
|
|
|
85
|
%OID = (); |
379
|
44
|
|
|
|
|
116
|
$obj->_find_code_refs('wrap_code_ref', @_); |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
sub _find_code_refs { |
384
|
47
|
|
|
47
|
|
57
|
my $obj = shift; |
385
|
47
|
|
|
|
|
58
|
my $visitor = shift; |
386
|
|
|
|
|
|
|
|
387
|
47
|
|
|
|
|
86
|
for my $item (@_) { |
388
|
50
|
100
|
100
|
|
|
508
|
my $reftype = $item && reftype $item |
389
|
|
|
|
|
|
|
or next; |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# skip references already seen |
392
|
4
|
50
|
|
|
|
21
|
next if ++$OID{refaddr $item} > 1; |
393
|
|
|
|
|
|
|
|
394
|
4
|
100
|
|
|
|
14
|
if ($reftype eq 'ARRAY') { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
395
|
2
|
|
|
|
|
11
|
$obj->_find_code_refs($visitor, @$item); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
elsif ($reftype eq 'HASH') { |
398
|
1
|
|
|
|
|
7
|
$obj->_find_code_refs($visitor, values %$item); |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
# XXX GLOBs? |
401
|
|
|
|
|
|
|
elsif ($reftype eq 'CODE') { |
402
|
1
|
|
|
|
|
4
|
$item = $obj->$visitor($item); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub wrap_code_ref { |
409
|
2
|
|
|
2
|
1
|
1168
|
my ($obj, $sub) = @_; |
410
|
2
|
50
|
|
|
|
23
|
die "Bad safe object" unless $obj->isa('Safe'); |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
# wrap code ref $sub with _safe_call_sv so that, when called, the |
413
|
|
|
|
|
|
|
# execution will happen with the compartment fully 'in effect'. |
414
|
|
|
|
|
|
|
|
415
|
2
|
50
|
|
|
|
12
|
croak "Not a CODE reference" |
416
|
|
|
|
|
|
|
if reftype $sub ne 'CODE'; |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
my $ret = sub { |
419
|
2
|
|
|
2
|
|
1042
|
my @args = @_; # lexical to close over |
420
|
2
|
|
|
|
|
9
|
my $sub_with_args = sub { $sub->(@args) }; |
|
2
|
|
|
|
|
7
|
|
421
|
|
|
|
|
|
|
|
422
|
2
|
|
|
|
|
4
|
my @subret; |
423
|
|
|
|
|
|
|
my $error; |
424
|
2
|
|
|
|
|
4
|
do { |
425
|
2
|
|
|
|
|
3
|
local $@; # needed due to perl_call_sv(sv, G_EVAL|G_KEEPERR) |
426
|
2
|
|
|
|
|
8
|
my $sg = sub_generation(); |
427
|
2
|
50
|
|
|
|
43
|
@subret = (wantarray) |
428
|
|
|
|
|
|
|
? Opcode::_safe_call_sv($obj->{Root}, $obj->{Mask}, $sub_with_args) |
429
|
|
|
|
|
|
|
: scalar Opcode::_safe_call_sv($obj->{Root}, $obj->{Mask}, $sub_with_args); |
430
|
2
|
|
|
|
|
78
|
$error = $@; |
431
|
2
|
50
|
|
|
|
18
|
_clean_stash($obj->{Root}.'::') if $sg != sub_generation(); |
432
|
|
|
|
|
|
|
}; |
433
|
2
|
50
|
|
|
|
10
|
if ($error) { # rethrow exception |
434
|
2
|
|
|
|
|
5
|
$error =~ s/\t\(in cleanup\) //; # prefix added by G_KEEPERR |
435
|
2
|
|
|
|
|
20
|
die $error; |
436
|
|
|
|
|
|
|
} |
437
|
0
|
0
|
|
|
|
0
|
return (wantarray) ? @subret : $subret[0]; |
438
|
2
|
|
|
|
|
13
|
}; |
439
|
|
|
|
|
|
|
|
440
|
2
|
|
|
|
|
10
|
return $ret; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
sub rdo { |
445
|
1
|
|
|
1
|
1
|
205
|
my ($obj, $file) = @_; |
446
|
1
|
50
|
|
|
|
11
|
die "Bad Safe object" unless $obj->isa('Safe'); |
447
|
|
|
|
|
|
|
|
448
|
1
|
|
|
|
|
3
|
my $root = $obj->{Root}; |
449
|
|
|
|
|
|
|
|
450
|
1
|
|
|
|
|
6
|
my $sg = sub_generation(); |
451
|
1
|
|
|
|
|
110
|
my $evalsub = eval |
452
|
|
|
|
|
|
|
sprintf('package %s; sub { @_ = (); do $file }', $root); |
453
|
1
|
50
|
|
|
|
417
|
my @subret = (wantarray) |
454
|
|
|
|
|
|
|
? Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub) |
455
|
|
|
|
|
|
|
: scalar Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub); |
456
|
1
|
50
|
|
|
|
15
|
_clean_stash($root.'::') if $sg != sub_generation(); |
457
|
1
|
|
|
|
|
6
|
$obj->wrap_code_refs_within(@subret); |
458
|
1
|
50
|
|
|
|
13
|
return (wantarray) ? @subret : $subret[0]; |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
1; |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
__END__ |