File Coverage

blib/lib/Safe.pm
Criterion Covered Total %
statement 183 200 91.5
branch 56 82 68.2
condition 12 20 60.0
subroutine 37 42 88.1
pod 16 23 69.5
total 304 367 82.8


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__