-
Notifications
You must be signed in to change notification settings - Fork 5
/
executor.pm
56 lines (43 loc) · 1.28 KB
/
executor.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/usr/bin/perl
# Project : TryPerl
# Author : Thibault Duponchelle
# executor.pm is a kind of safe online REPL
use strict; # Not heavily tested with this
use warnings;
no warnings 'once';
use 5.10.1; # Thank you xeeeeeeeeeeeeeeeeenu (do I missed a "e" ? xD)
use Safe;
sub execute_this($) {
my $cmd = shift;
(!$cmd) and print "Nothing to execute\n\r" and exit;
$| = 1; # Force flush
# Redirect output
my $output;
open(my $outputFH, '>', \$output) or die; # This shouldn't fail
my $oldFH = select $outputFH;
my $compartment = new Safe("jail");
$compartment->deny(qw(:base_io :ownprocess :subprocess :filesys_read :sys_db :filesys_open :filesys_write :dangerous));
$compartment->permit(qw(:base_math print say pack unpack require caller sort));
my $ret;
# This eval is for timeout
eval {
local $SIG{ALRM} = sub { print "Oh fuck ! We reached the timeout ! Fuck fuck fuck !"; die "alarm\n" }; # print captured into $ret as everything else due to select !
alarm 3; # 3 sec
$ret = $compartment->reval($cmd); # This reval is for code execution
alarm 0;
die $@ if $@;
};
# Exception
my $e = $@;
select $oldFH;
close $outputFH;
if($e) {
chomp $e;
return "=> Exception : $e\n\r";
} elsif($output) {
return "=> $output\n\r";
} else{
return "=> $ret\n\r";
}
}
1;