#!/usr/bin/perl -w use strict; use Opcode qw(opset opmask_add opset_to_ops invert_opset); my $code = shift; defined $code or die "Usage: $0 ...\n"; # skip some masks from prev operations my %skip; $skip{$_}++ for @ARGV; my @all = opset_to_ops(invert_opset(opset())); # Try all opcodes, print error if eval failed foreach ( @all ) { $skip{$_} and next; opmask_add(opset($_)); eval $code and next; print "Eval failed on opcode: $_ with error: $@\n"; exit 1; }; print "Eval OK\n"; #### #!/usr/bin/perl -w use strict; use warnings; use 5.012; use Safe; use Carp; my $code = shift; die "Usage: $0 ..." unless defined $code; my @perm = @ARGV; print "Trying: $code\n"; my $compartment = Safe->new; $compartment->share('*STDIN'); $compartment->share('&Dumper'); $compartment->permit_only(@perm); # Trap detailed stack trace my $stack; local $SIG{__DIE__} = sub { $stack = Carp::longmess(shift) }; print $compartment->reval($code); if ($@) { print "Unsafe code detected: $@"; print "At: $stack"; } #### bash$ perl safe2.pl 1 Trying: 1 Unsafe code detected: 'private value' trapped by operation mask at (eval 5) line 1. At: 'private value' trapped by operation mask at (eval 5) line 1. at (eval 5) line 1 eval 'my $__ExPr__;1 ;' called at (eval 4) line 1 main::__ANON__(** Incomplete caller override detected; @DB::args were not set **) called at /usr/share/perl/5.14/Safe.pm line 358 eval {...} called at /usr/share/perl/5.14/Safe.pm line 358 Safe::reval(** Incomplete caller override detected; @DB::args were not set **) called at safe2.pl line 26 #### bash$ perl safe2.pl 1 padany const leaveeval lineseq Trying: 1 1