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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
|
#!perl
# Tests that all ops can be trapped by a Safe compartment
BEGIN {
if ($ENV{PERL_CORE}) {
chdir 't' if -d 't';
@INC = '../lib';
}
else {
# this won't work outside of the core, so exit
print "1..0\n"; exit 0;
}
}
use Config;
BEGIN {
if ($Config{'extensions'} !~ /\bOpcode\b/ && $Config{'osname'} ne 'VMS') {
print "1..0\n"; exit 0;
}
}
use strict;
use Test::More tests => 354;
use Safe;
# Read the op names and descriptions directly from opcode.pl
my @op;
my @opname;
open my $fh, '<', '../opcode.pl' or die "Can't open opcode.pl: $!";
while (<$fh>) {
last if /^__END__/;
}
while (<$fh>) {
chomp;
next if !$_ or /^#/;
my ($op, $opname) = split /\t+/;
push @op, $op;
push @opname, $opname;
}
close $fh;
sub testop {
my ($op, $opname, $code) = @_;
pass("$op : skipped") and return if $code =~ /^SKIP/;
my $c = new Safe;
$c->deny_only($op);
$c->reval($code);
like($@, qr/'\Q$opname\E' trapped by operation mask/, $op);
}
my $i = 0;
while (<DATA>) {
testop $op[$i], $opname[$i], $_;
++$i;
}
# lists op examples, in the same order than opcode.pl
# things that begin with SKIP are skipped, for various reasons (notably
# optree modified by the optimizer -- Safe checks are done before the
# optimizer modifies the optree)
__DATA__
SKIP # null
SKIP # stub
scalar $x # scalar
print @x # pushmark
wantarray # wantarray
42 # const
SKIP (set by optimizer) $x # gvsv
SKIP *x # gv
*x{SCALAR} # gelem
SKIP my $x # padsv
SKIP my @x # padav
SKIP my %x # padhv
SKIP (not implemented) # padany
SKIP split /foo/ # pushre
*x # rv2gv
$x # rv2sv
$#x # av2arylen
f() # rv2cv
sub { } # anoncode
prototype 'foo' # prototype
\($x,$y) # refgen
SKIP \$x # srefgen
ref # ref
bless # bless
qx/ls/ # backtick
<*.c> # glob
<FH> # readline
SKIP (set by optimizer) $x .= <F> # rcatline
SKIP (internal) # regcmaybe
SKIP (internal) # regcreset
SKIP (internal) # regcomp
/foo/ # match
qr/foo/ # qr
s/foo/bar/ # subst
SKIP (set by optimizer) # substcont
y:z:t: # trans
$x = $y # sassign
@x = @y # aassign
chop @foo # chop
chop # schop
chomp @foo # chomp
chomp # schomp
defined # defined
undef # undef
study # study
pos # pos
++$i # preinc
SKIP (set by optimizer) # i_preinc
--$i # predec
SKIP (set by optimizer) # i_predec
$i++ # postinc
SKIP (set by optimizer) # i_postinc
$i-- # postdec
SKIP (set by optimizer) # i_postdec
$x ** $y # pow
$x * $y # multiply
SKIP (set by optimizer) # i_multiply
$x / $y # divide
SKIP (set by optimizer) # i_divide
$x % $y # modulo
SKIP (set by optimizer) # i_modulo
$x x $y # repeat
$x + $y # add
SKIP (set by optimizer) # i_add
$x - $y # subtract
SKIP (set by optimizer) # i_subtract
$x . $y # concat
"$x" # stringify
$x << 1 # left_shift
$x >> 1 # right_shift
$x < $y # lt
SKIP (set by optimizer) # i_lt
$x > $y # gt
SKIP (set by optimizer) # i_gt
$i <= $y # le
SKIP (set by optimizer) # i_le
$i >= $y # ge
SKIP (set by optimizer) # i_ge
$x == $y # eq
SKIP (set by optimizer) # i_eq
$x != $y # ne
SKIP (set by optimizer) # i_ne
$i <=> $y # ncmp
SKIP (set by optimizer) # i_ncmp
$x lt $y # slt
$x gt $y # sgt
$x le $y # sle
$x ge $y # sge
$x eq $y # seq
$x ne $y # sne
$x cmp $y # scmp
$x & $y # bit_and
$x ^ $y # bit_xor
$x | $y # bit_or
-$x # negate
SKIP (set by optimizer) # i_negate
!$x # not
~$x # complement
atan2 1 # atan2
sin 1 # sin
cos 1 # cos
rand # rand
srand # srand
exp 1 # exp
log 1 # log
sqrt 1 # sqrt
int # int
hex # hex
oct # oct
abs # abs
length # length
substr $x, 1 # substr
vec # vec
index # index
rindex # rindex
sprintf '%s', 'foo' # sprintf
formline # formline
ord # ord
chr # chr
crypt 'foo','bar' # crypt
ucfirst # ucfirst
lcfirst # lcfirst
uc # uc
lc # lc
quotemeta # quotemeta
@a # rv2av
SKIP (set by optimizer) # aelemfast
$a[1] # aelem
@a[1,2] # aslice
each %h # each
values %h # values
keys %h # keys
delete $h{Key} # delete
exists $h{Key} # exists
%h # rv2hv
$h{kEy} # helem
@h{kEy} # hslice
unpack # unpack
pack # pack
split /foo/ # split
join $a, @b # join
@x = (1,2) # list
SKIP @x[1,2] # lslice
[1,2] # anonlist
{ a => 1 } # anonhash
splice @x, 1, 2, 3 # splice
push @x, $x # push
pop @x # pop
shift @x # shift
unshift @x # unshift
sort @x # sort
reverse @x # reverse
grep { $_ eq 'foo' } @x # grepstart
SKIP grep { $_ eq 'foo' } @x # grepwhile
map $_ + 1, @foo # mapstart
SKIP (set by optimizer) # mapwhile
SKIP # range
1..2 # flip
1..2 # flop
$x && $y # and
$x || $y # or
$x xor $y # xor
$x ? 1 : 0 # cond_expr
$x &&= $y # andassign
$x ||= $y # orassign
Foo->$x() # method
f() # entersub
sub f{} f() # leavesub
sub f:lvalue{return $x} f() # leavesublv
caller # caller
warn # warn
die # die
reset # reset
SKIP # lineseq
SKIP # nextstate
SKIP (needs debugger) # dbstate
while(0){} # unstack
SKIP # enter
SKIP # leave
SKIP # scope
SKIP # enteriter
SKIP # iter
SKIP # enterloop
SKIP # leaveloop
return # return
last # last
next # next
redo THIS # redo
dump # dump
goto THERE # goto
exit 0 # exit
open FOO # open
close FOO # close
pipe FOO,BAR # pipe_op
fileno FOO # fileno
umask 0755, 'foo' # umask
binmode FOO # binmode
tie # tie
untie # untie
tied # tied
dbmopen # dbmopen
dbmclose # dbmclose
SKIP (set by optimizer) # sselect
select FOO # select
getc FOO # getc
read FOO # read
write # enterwrite
SKIP # leavewrite
printf # prtf
print # print
sysopen # sysopen
sysseek # sysseek
sysread # sysread
syswrite # syswrite
send # send
recv # recv
eof FOO # eof
tell # tell
seek FH, $pos, $whence # seek
truncate FOO, 42 # truncate
fcntl # fcntl
ioctl # ioctl
flock FOO, 1 # flock
socket # socket
socketpair # sockpair
bind # bind
connect # connect
listen # listen
accept # accept
shutdown # shutdown
getsockopt # gsockopt
setsockopt # ssockopt
getsockname # getsockname
getpeername # getpeername
lstat FOO # lstat
stat FOO # stat
-R # ftrread
-W # ftrwrite
-X # ftrexec
-r # fteread
-w # ftewrite
-x # fteexec
-e # ftis
SKIP -O # fteowned
SKIP -o # ftrowned
-z # ftzero
-s # ftsize
-M # ftmtime
-A # ftatime
-C # ftctime
-S # ftsock
-c # ftchr
-b # ftblk
-f # ftfile
-d # ftdir
-p # ftpipe
-l # ftlink
-u # ftsuid
-g # ftsgid
-k # ftsvtx
-t # fttty
-T # fttext
-B # ftbinary
chdir '/' # chdir
chown # chown
chroot # chroot
unlink 'foo' # unlink
chmod 511, 'foo' # chmod
utime # utime
rename 'foo', 'bar' # rename
link 'foo', 'bar' # link
symlink 'foo', 'bar' # symlink
readlink 'foo' # readlink
mkdir 'foo' # mkdir
rmdir 'foo' # rmdir
opendir DIR # open_dir
readdir DIR # readdir
telldir DIR # telldir
seekdir DIR, $pos # seekdir
rewinddir DIR # rewinddir
closedir DIR # closedir
fork # fork
wait # wait
waitpid # waitpid
system # system
exec # exec
kill # kill
getppid # getppid
getpgrp # getpgrp
setpgrp # setpgrp
getpriority # getpriority
setpriority # setpriority
time # time
times # tms
localtime # localtime
gmtime # gmtime
alarm # alarm
sleep 1 # sleep
shmget # shmget
shmctl # shmctl
shmread # shmread
shmwrite # shmwrite
msgget # msgget
msgctl # msgctl
msgsnd # msgsnd
msgrcv # msgrcv
semget # semget
semctl # semctl
semop # semop
use strict # require
do 'file' # dofile
eval "1+1" # entereval
eval "1+1" # leaveeval
SKIP eval { 1+1 } # entertry
SKIP eval { 1+1 } # leavetry
gethostbyname 'foo' # ghbyname
gethostbyaddr 'foo' # ghbyaddr
gethostent # ghostent
getnetbyname 'foo' # gnbyname
getnetbyaddr 'foo' # gnbyaddr
getnetent # gnetent
getprotobyname 'foo' # gpbyname
getprotobynumber 42 # gpbynumber
getprotoent # gprotoent
getservbyname 'name', 'proto' # gsbyname
getservbyport 'a', 'b' # gsbyport
getservent # gservent
sethostent # shostent
setnetent # snetent
setprotoent # sprotoent
setservent # sservent
endhostent # ehostent
endnetent # enetent
endprotoent # eprotoent
endservent # eservent
getpwnam # gpwnam
getpwuid # gpwuid
getpwent # gpwent
setpwent # spwent
endpwent # epwent
getgrnam # ggrnam
getgrgid # ggrgid
getgrent # ggrent
setgrent # sgrent
endgrent # egrent
getlogin # getlogin
syscall # syscall
SKIP # lock
SKIP # threadsv
SKIP # setstate
$x->y() # method_named
$x // $y # dor
$x //= $y # dorassign
SKIP (no way) # custom
|