line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# This is an implementation of Eval::Safe that uses `eval` to execute the user |
2
|
|
|
|
|
|
|
# provided code. |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Eval::Safe::Eval; |
5
|
|
|
|
|
|
|
|
6
|
3
|
|
|
3
|
|
39
|
use 5.022; |
|
3
|
|
|
|
|
10
|
|
7
|
3
|
|
|
3
|
|
12
|
use strict; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
46
|
|
8
|
3
|
|
|
3
|
|
10
|
use warnings; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
251
|
|
9
|
|
|
|
|
|
|
|
10
|
3
|
|
|
3
|
|
1093
|
use parent 'Eval::Safe'; |
|
3
|
|
|
|
|
828
|
|
|
3
|
|
|
|
|
14
|
|
11
|
|
|
|
|
|
|
|
12
|
3
|
|
|
3
|
|
145
|
use Carp; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
132
|
|
13
|
3
|
|
|
3
|
|
1304
|
use File::Spec::Functions qw(rel2abs); |
|
3
|
|
|
|
|
2321
|
|
|
3
|
|
|
|
|
1456
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Count the number of Eval::Safe::Eval object created to assign each of them a |
16
|
|
|
|
|
|
|
# specific package name. |
17
|
|
|
|
|
|
|
my $env_count = 0; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
20
|
2
|
|
|
2
|
1
|
8
|
my ($class, %options) = @_; |
21
|
2
|
|
|
|
|
5
|
my $self = bless \%options, $class; |
22
|
2
|
50
|
|
|
|
11
|
$self->{package} = 'Eval::Safe::Eval::Env'.($env_count++) unless $self->{package}; |
23
|
2
|
|
|
|
|
10
|
return $self; |
24
|
|
|
|
|
|
|
} |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub DESTROY { |
27
|
2
|
|
|
2
|
|
1079
|
local($., $@, $!, $^E, $?); |
28
|
2
|
|
|
|
|
4
|
my ($this) = @_; |
29
|
2
|
|
|
|
|
94
|
CORE::eval('undef %'.($this->{package}).'::'); |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub eval { |
33
|
0
|
|
|
0
|
1
|
|
my ($this, $code) = @_; |
34
|
|
|
|
|
|
|
my $eval_str = sprintf "package %s; %s; %s; %s", $this->{package}, |
35
|
0
|
|
|
|
|
|
$this->{strict}, $this->{warnings}, $code; |
36
|
0
|
0
|
|
|
|
|
print {$this->{debug}} "Evaling (eval): '${eval_str}'\n" if $this->{debug}; |
|
0
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
|
my @ret; |
38
|
0
|
0
|
|
|
|
|
if (not defined wantarray) { |
|
|
0
|
|
|
|
|
|
39
|
0
|
|
|
|
|
|
CORE::eval($eval_str); |
40
|
|
|
|
|
|
|
} elsif (wantarray) { |
41
|
0
|
|
|
|
|
|
@ret = CORE::eval($eval_str); |
42
|
|
|
|
|
|
|
} else { |
43
|
0
|
|
|
|
|
|
@ret = scalar CORE::eval($eval_str); |
44
|
|
|
|
|
|
|
} |
45
|
0
|
0
|
0
|
|
|
|
print {$this->{debug}} "Eval returned an error: $@" if $this->{debug} && $@; |
|
0
|
|
|
|
|
|
|
46
|
0
|
|
|
|
|
|
return $this->_wrap_code_refs(\&_wrap_in_eval, @ret); |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub do { |
50
|
0
|
|
|
0
|
1
|
|
my ($this, $file) = @_; |
51
|
|
|
|
|
|
|
# do can open relative paths, but in that case it looks them up in the @INC |
52
|
|
|
|
|
|
|
# directory, which we want to avoid. |
53
|
|
|
|
|
|
|
# We don't use abs_path here to not die (just yet) if the file does not exist. |
54
|
0
|
|
|
|
|
|
my $abs_path = rel2abs($file); |
55
|
0
|
|
|
|
|
|
$this->eval("my \$r = do '${abs_path}'; die \$@ if \$@; \$r"); |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# To emulate the behavior of the Safe approach (where code returned by eval is |
59
|
|
|
|
|
|
|
# wrapped to trap all exception, we're using this method to wrap code returned |
60
|
|
|
|
|
|
|
# by eval in the same way). |
61
|
|
|
|
|
|
|
sub _wrap_in_eval { |
62
|
0
|
|
|
0
|
|
|
my ($this, $sub) = @_; |
63
|
|
|
|
|
|
|
# When $sub is called, we're executing it in an `eval` and also wrapping all |
64
|
|
|
|
|
|
|
# its returned code in the same way. |
65
|
|
|
|
|
|
|
return sub { |
66
|
0
|
|
|
0
|
|
|
my @ret; |
67
|
0
|
0
|
|
|
|
|
if (not defined wantarray) { |
|
|
0
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
eval { $sub->() }; |
|
0
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
} elsif (wantarray) { |
70
|
0
|
|
|
|
|
|
@ret = eval { $sub->() }; |
|
0
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
} else { |
72
|
0
|
|
|
|
|
|
@ret = scalar eval { $sub->() }; |
|
0
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
} |
74
|
0
|
|
|
|
|
|
$this->_wrap_code_refs(\&_wrap_in_eval, @ret) |
75
|
0
|
|
|
|
|
|
}; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
1; |