File Coverage

blib/lib/Safe/World/Compartment.pm
Criterion Covered Total %
statement 61 77 79.2
branch 12 24 50.0
condition 1 3 33.3
subroutine 13 19 68.4
pod 0 7 0.0
total 87 130 66.9


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: Compartment.pm
3             ## Purpose: Safe::World::Compartment -> Based in the Safe module.
4             ## Author: Graciliano M. P.
5             ## Modified by:
6             ## Created: 04/12/2003
7             ## RCS-ID:
8             ## Copyright: (c) 2003 Graciliano M. P.
9             ## Licence: This program is free software; you can redistribute it and/or
10             ## modify it under the same terms as Perl itself
11             #############################################################################
12              
13             package Safe::World::Compartment ;
14              
15 1     1   5 use strict qw(vars) ;
  1         2  
  1         30  
16              
17 1     1   5 no warnings ;
  1         2  
  1         31  
18              
19             ##########
20             # SCOPES #
21             ##########
22              
23 1     1   5 use vars qw($Safe_World_EVALX) ;
  1         1  
  1         77  
24              
25             *Safe_World_EVALX = \$Safe::World::EVALX ;
26              
27             ######### *** Don't declare any lexicals above this point ***
28              
29             sub reval {
30 1     1 0 3 my $__EVALCODE__ = $_[1] ;
31 1     1   5 no strict ;
  1         1  
  1         113  
32              
33 1         3 $Safe_World_EVALX += 2 ;
34              
35 1         138 return Opcode::_safe_call_sv(
36             $_[0]->{Root},
37             $_[0]->{Mask},
38             eval("package ". $_[0]->{Root} ."; sub { \@_=(); my \$EVALX = $Safe_World_EVALX; eval \$__EVALCODE__; }")
39             );
40             }
41              
42             #############################################################################
43              
44 1     1   5 use vars qw($VERSION @ISA) ;
  1         2  
  1         85  
45              
46             $VERSION = '0.02' ;
47              
48 1         620 use Opcode 1.01, qw(
49             opset opset_to_ops opmask_add
50             empty_opset full_opset invert_opset verify_opset
51             opdesc opcodes opmask define_optag opset_to_hex
52 1     1   5 );
  1         2  
53              
54             *ops_to_opset = \&opset ; # Temporary alias for old Penguins
55             *Opcode_safe_pkg_prep = \&Opcode::_safe_pkg_prep ;
56              
57             my $default_share = ['*_'] ;
58              
59             my $SCALAR_R ; tie( $SCALAR_R , 'Safe::World::Compartment::SCALAR_R') ;
60              
61             #############################################################################
62              
63             sub new {
64 1     1 0 3 my($class, $root) = @_;
65 1         5 my $obj = bless({} , $class) ;
66              
67 1         7 $obj->{Root} = $root ;
68              
69 1 50       5 return undef if !defined($root) ;
70              
71 1         6 $obj->permit_only(':default') ;
72 1         5 $obj->share_from('main', $default_share) ;
73            
74             {
75             ## (See Safe::World::Compartment::SCALAR_R at the end of this file).
76             ## Set the tied $^R to fix behavior:
77 1         2 my $tmp = $_ ;
  1         2  
78 1         3 $_ = \$SCALAR_R ;
79 1         7 $obj->reval('*^R = $_') ;
80 1         12 $_ = $tmp ;
81 1         3 $^R = undef ; ## Ensure that is reseted.
82             }
83            
84 1 50       12 Opcode_safe_pkg_prep($root) if($Opcode::VERSION > 1.04);
85            
86 1         9 return $obj;
87             }
88              
89             sub deny {
90 0     0 0 0 my $obj = shift;
91 0         0 $obj->{Mask} |= opset(@_);
92             }
93             sub deny_only {
94 1     1 0 3 my $obj = shift;
95 1         75 $obj->{Mask} = opset(@_);
96             }
97              
98             sub permit {
99 0     0 0 0 my $obj = shift;
100 0         0 $obj->{Mask} &= invert_opset opset(@_);
101             }
102              
103             sub permit_only {
104 1     1 0 2 my $obj = shift;
105 1         14 $obj->{Mask} = invert_opset opset(@_);
106             }
107              
108             sub share_from {
109 1     1 0 2 my $obj = shift;
110 1         2 my $pkg = shift;
111 1         3 my $vars = shift;
112              
113 1         2 my $root = $obj->{Root} ;
114              
115 1 50       6 return undef if ref($vars) ne 'ARRAY' ;
116            
117 1     1   6 no strict 'refs';
  1         1  
  1         2076  
118            
119 1 50       2 return undef unless keys %{"$pkg\::"} ;
  1         7  
120              
121 1         3 my $REF ;
122              
123             my $arg;
124 1         4 foreach $arg (@$vars) {
125 1 50 33     11 next unless( $arg =~ /^[\$\@%*&]?\w[\w:]*$/ || $arg =~ /^\$\W\w?$/ ) ;
126              
127 1         2 my ($var, $type);
128 1 50       10 $type = $1 if ($var = $arg) =~ s/^(\W)// ;
129              
130 1         16 *{$root."::$var"} = (!$type) ?
  0         0  
131 0         0 \&{$pkg."::$var"} : ($type eq '&') ?
132 0         0 \&{$pkg."::$var"} : ($type eq '$') ?
133 0         0 \${$pkg."::$var"} : ($type eq '@') ?
134 0         0 \@{$pkg."::$var"} : ($type eq '%') ?
135 1         4 \%{$pkg."::$var"} : ($type eq '*') ?
136 1 50       16 \*{$pkg."::$var"} : undef ;
    50          
    50          
    50          
    50          
    50          
137             }
138              
139 1         3 return 1 ;
140             }
141              
142             ######################################
143             # SAFE::WORLD::COMPARTMENT::SCALAR_R # TIE SCALAR FOR $^R
144             ######################################
145              
146             # The predefined variable $^R doesn't work like normal variables,
147             # that to be global lives in the main:: package. $^R doesn't exists
148             # at main::, soo $main::^R doesn't exists and we can't share it with
149             # the World compartment. $^R actually points to the last scalar returned
150             # by the code executed in the RE, soo $^R will point to different SCALARs
151             # during the RE, and if we change by hand the scalar reference of *^R it
152             # will be overwrited during the RE.
153             #
154             # To fix that I have used a closure in the
155             # FETCH and STORE methods of the TIESCALAR, and set the scalar of the
156             # GLOB reference inside the compartment (*^R) with the tied scalar.
157             # Soo, if an RE compiled inside the compartment make some reference to $^R
158             # it will see the external $^R through the TIED SCALAR.
159             #
160              
161             package Safe::World::Compartment::SCALAR_R ;
162              
163             sub TIESCALAR {
164 1     1   2 my $class = shift ;
165 1         2 my $ref = shift ;
166 1         6 return bless( \$ref , __PACKAGE__ ) ;
167             }
168              
169             sub STORE {
170 0     0     my $this = shift ;
171 0           $^R = $_[0] ;
172 0           return $^R ;
173             }
174              
175             sub FETCH {
176 0     0     my $this = shift ;
177 0           return $^R ;
178             }
179              
180 0     0     sub UNTIE {}
181 0     0     sub DESTROY {}
182              
183             #######
184             # END #
185             #######
186              
187             1;
188              
189