line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Perl::Lint::Policy::InputOutput::RequireCheckedSyscalls; |
2
|
134
|
|
|
134
|
|
72695
|
use strict; |
|
134
|
|
|
|
|
205
|
|
|
134
|
|
|
|
|
3247
|
|
3
|
134
|
|
|
134
|
|
420
|
use warnings; |
|
134
|
|
|
|
|
190
|
|
|
134
|
|
|
|
|
3007
|
|
4
|
134
|
|
|
134
|
|
470
|
use List::Util qw/any/; |
|
134
|
|
|
|
|
182
|
|
|
134
|
|
|
|
|
7155
|
|
5
|
134
|
|
|
134
|
|
863
|
use Perl::Lint::Constants::Type; |
|
134
|
|
|
|
|
523
|
|
|
134
|
|
|
|
|
61458
|
|
6
|
134
|
|
|
134
|
|
915
|
use Perl::Lint::Constants::Kind; |
|
134
|
|
|
|
|
182
|
|
|
134
|
|
|
|
|
6169
|
|
7
|
134
|
|
|
134
|
|
953
|
use B::Keywords; |
|
134
|
|
|
|
|
1041
|
|
|
134
|
|
|
|
|
4049
|
|
8
|
134
|
|
|
134
|
|
450
|
use parent "Perl::Lint::Policy"; |
|
134
|
|
|
|
|
168
|
|
|
134
|
|
|
|
|
630
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use constant { |
11
|
134
|
|
|
|
|
125002
|
DESC => 'Return value of flagged function ignored', |
12
|
|
|
|
|
|
|
EXPL => [208, 278], |
13
|
134
|
|
|
134
|
|
7241
|
}; |
|
134
|
|
|
|
|
203
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub evaluate { |
16
|
42
|
|
|
42
|
0
|
53
|
my ($class, $file, $tokens, $src, $args) = @_; |
17
|
|
|
|
|
|
|
|
18
|
42
|
|
|
|
|
34
|
my $is_target_all = 0; |
19
|
42
|
|
|
|
|
65
|
my @target_functions = qw/open close say/; |
20
|
42
|
|
|
|
|
29
|
my $allowed_functions; |
21
|
42
|
100
|
|
|
|
84
|
if (my $required_checked_syscalls_arg = $args->{require_checked_syscalls}) { |
22
|
7
|
50
|
|
|
|
17
|
if (my $functions = $required_checked_syscalls_arg->{functions}) { |
23
|
7
|
100
|
|
|
|
15
|
if ($functions eq ':builtins') { |
|
|
100
|
|
|
|
|
|
24
|
3
|
|
|
|
|
45
|
@target_functions = @B::Keywords::Functions; |
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
elsif ($functions eq ':all') { |
27
|
3
|
|
|
|
|
4
|
$is_target_all = 1; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
else { |
30
|
1
|
|
|
|
|
2
|
@target_functions = ($functions); |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
7
|
100
|
|
|
|
15
|
if ($allowed_functions = $required_checked_syscalls_arg->{exclude_functions}) { |
35
|
3
|
|
|
|
|
5
|
@target_functions = grep {$_ ne $allowed_functions} @target_functions; |
|
485
|
|
|
|
|
380
|
|
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
} |
38
|
|
|
|
|
|
|
|
39
|
42
|
|
|
|
|
40
|
my $is_in_assign_context = 0; |
40
|
42
|
|
|
|
|
28
|
my $is_in_statement_context = 0; |
41
|
42
|
|
|
|
|
31
|
my $is_called_syscalls_in_void = 0; |
42
|
42
|
|
|
|
|
28
|
my $is_enabled_autodie = 0; |
43
|
42
|
|
|
|
|
25
|
my @violations; |
44
|
42
|
|
|
|
|
93
|
for (my $i = 0; my $token = $tokens->[$i]; $i++) { |
45
|
665
|
|
|
|
|
466
|
my $token_type = $token->{type}; |
46
|
665
|
|
|
|
|
399
|
my $token_kind = $token->{kind}; |
47
|
665
|
|
|
|
|
452
|
my $token_data = $token->{data}; |
48
|
|
|
|
|
|
|
|
49
|
665
|
100
|
|
|
|
742
|
if ($token_type == ASSIGN) { |
50
|
9
|
|
|
|
|
9
|
$is_in_assign_context = 1; |
51
|
9
|
|
|
|
|
12
|
next; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
656
|
100
|
|
|
|
708
|
if ($token_type == USED_NAME) { |
55
|
20
|
100
|
|
|
|
42
|
if ($token_data eq 'Fatal') { |
|
|
100
|
|
|
|
|
|
56
|
8
|
|
|
|
|
11
|
my $next_token = $tokens->[$i+1]; |
57
|
8
|
|
|
|
|
6
|
my $next_token_type = $next_token->{type}; |
58
|
8
|
|
|
|
|
11
|
my $next_token_data = $next_token->{data}; |
59
|
8
|
100
|
33
|
|
|
29
|
if ($next_token_type == REG_LIST) { |
|
|
100
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
60
|
4
|
|
|
|
|
8
|
for ($i += 3; my $token = $tokens->[$i]; $i++) { |
61
|
8
|
|
|
|
|
8
|
my $token_type = $token->{type}; |
62
|
8
|
|
|
|
|
5
|
my $token_data = $token->{data}; |
63
|
8
|
100
|
|
|
|
21
|
if ($token_type == REG_EXP) { |
|
|
50
|
|
|
|
|
|
64
|
4
|
|
|
|
|
5
|
@target_functions = grep {$_ ne $token_data} @target_functions |
|
12
|
|
|
|
|
23
|
|
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
elsif ($token_type == REG_DELIM) { |
67
|
4
|
|
|
|
|
7
|
last; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
elsif ($next_token_type == LEFT_PAREN) { |
72
|
2
|
|
|
|
|
3
|
my $left_paren_num = 1; |
73
|
2
|
|
|
|
|
7
|
for ($i += 2; my $token = $tokens->[$i]; $i++) { |
74
|
2
|
|
|
|
|
3
|
my $token_type = $token->{type}; |
75
|
2
|
|
|
|
|
3
|
my $token_data = $token->{data}; |
76
|
2
|
50
|
33
|
|
|
19
|
if ($token_type == LEFT_PAREN) { |
|
|
50
|
33
|
|
|
|
|
77
|
0
|
|
|
|
|
0
|
$left_paren_num++; |
78
|
|
|
|
|
|
|
} |
79
|
3
|
|
|
3
|
|
7
|
elsif (($token_type == STRING || $token_type == RAW_STRING) && any {$_ eq $token_data} @target_functions) { |
80
|
2
|
|
|
|
|
12
|
return []; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
else { |
83
|
0
|
0
|
|
|
|
0
|
last if --$left_paren_num <= 0; |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
} |
87
|
3
|
|
|
3
|
|
8
|
elsif (($next_token_type == STRING || $next_token_type == RAW_STRING) && any {$_ eq $next_token_data} @target_functions) { |
88
|
2
|
|
|
|
|
4
|
last; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
elsif ($token_data eq 'autodie') { |
92
|
4
|
100
|
|
|
|
11
|
if ($tokens->[$i+1]->{type} == REG_LIST) { |
93
|
2
|
|
|
|
|
6
|
for ($i += 3; my $token = $tokens->[$i]; $i++) { |
94
|
4
|
|
|
|
|
3
|
my $token_type = $token->{type}; |
95
|
4
|
100
|
100
|
|
|
20
|
if ($token_type == REG_EXP && $token->{data} =~ /\A\s*:io\s*\Z/) { |
|
|
100
|
|
|
|
|
|
96
|
1
|
|
|
|
|
3
|
$is_enabled_autodie = 1; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
elsif ($token_type == REG_DELIM) { |
99
|
2
|
|
|
|
|
3
|
last; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
else { |
104
|
2
|
|
|
|
|
2
|
$is_enabled_autodie = 1; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
16
|
|
|
|
|
26
|
next; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
636
|
100
|
66
|
|
|
778
|
if ($token_type == NAMESPACE && $token_data eq 'Fatal') { |
112
|
2
|
|
|
|
|
3
|
my $skipped_token = $tokens->[$i+2]; |
113
|
2
|
50
|
33
|
|
|
14
|
if ($skipped_token && $skipped_token->{type} == NAMESPACE && $skipped_token->{data} eq 'Exception') { |
|
|
|
33
|
|
|
|
|
114
|
2
|
|
|
|
|
5
|
for ($i += 3; my $token = $tokens->[$i]; $i++) { |
115
|
8
|
|
|
|
|
9
|
my $token_type = $token->{type}; |
116
|
8
|
|
|
|
|
9
|
my $token_data = $token->{data}; |
117
|
8
|
100
|
66
|
|
|
38
|
if ($token_type == REG_LIST) { |
|
|
50
|
66
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
118
|
2
|
|
|
|
|
4
|
for ($i += 2; my $token = $tokens->[$i]; $i++) { |
119
|
4
|
|
|
|
|
4
|
my $token_type = $token->{type}; |
120
|
4
|
|
|
|
|
5
|
my $token_data = $token->{data}; |
121
|
4
|
100
|
|
|
|
15
|
if ($token_type == REG_EXP) { |
|
|
50
|
|
|
|
|
|
122
|
2
|
|
|
|
|
3
|
@target_functions = grep {$_ ne $token_data} @target_functions |
|
6
|
|
|
|
|
12
|
|
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
elsif ($token_type == REG_DELIM) { |
125
|
2
|
|
|
|
|
5
|
last; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
elsif ($token_type == LEFT_PAREN) { |
130
|
0
|
|
|
|
|
0
|
my $left_paren_num = 1; |
131
|
0
|
|
|
|
|
0
|
for ($i++; my $token = $tokens->[$i]; $i++) { |
132
|
0
|
|
|
|
|
0
|
my $token_type = $token->{type}; |
133
|
0
|
|
|
|
|
0
|
my $token_data = $token->{data}; |
134
|
0
|
0
|
0
|
|
|
0
|
if ($token_type == LEFT_PAREN) { |
|
|
0
|
0
|
|
|
|
|
135
|
0
|
|
|
|
|
0
|
$left_paren_num++; |
136
|
|
|
|
|
|
|
} |
137
|
0
|
|
|
0
|
|
0
|
elsif (($token_type == STRING || $token_type == RAW_STRING) && any {$_ eq $token_data} @target_functions) { |
138
|
0
|
|
|
|
|
0
|
return []; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
else { |
141
|
0
|
0
|
|
|
|
0
|
last if --$left_paren_num <= 0; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
} |
145
|
6
|
|
|
6
|
|
17
|
elsif (($token_type == STRING || $token_type == RAW_STRING) && any {$_ eq $token_data} @target_functions) { |
146
|
0
|
|
|
|
|
0
|
last; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
elsif ($token->{kind} == KIND_STMT_END) { |
149
|
2
|
|
|
|
|
2
|
last; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
2
|
|
|
|
|
4
|
next; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
634
|
100
|
|
|
|
643
|
if ($token_kind == KIND_STMT) { |
158
|
27
|
|
|
|
|
19
|
$is_in_statement_context = 1; |
159
|
|
|
|
|
|
|
|
160
|
27
|
100
|
|
|
|
46
|
if ($tokens->[$i+1]->{type} == LEFT_PAREN) { |
161
|
3
|
|
|
|
|
4
|
$i++; |
162
|
3
|
|
|
|
|
4
|
my $left_paren_num = 1; |
163
|
3
|
|
|
|
|
8
|
for ($i++; my $token = $tokens->[$i]; $i++) { |
164
|
3
|
|
|
|
|
5
|
my $token_type = $token->{type}; |
165
|
3
|
50
|
|
|
|
6
|
if ($token_type == LEFT_PAREN) { |
166
|
0
|
|
|
|
|
0
|
$left_paren_num++; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
else { |
169
|
3
|
50
|
|
|
|
8
|
last if --$left_paren_num <= 0; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
} |
173
|
27
|
|
|
|
|
40
|
next; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
607
|
100
|
100
|
|
|
1139
|
if ($token_type == BUILTIN_FUNC || ($is_target_all && $token_type == RETURN)) { |
|
|
|
66
|
|
|
|
|
177
|
97
|
100
|
100
|
430
|
|
405
|
if ($is_target_all || any {$_ eq $token_data} @target_functions) { |
|
430
|
100
|
|
|
|
421
|
|
178
|
69
|
100
|
66
|
|
|
126
|
if (!$is_in_assign_context && !$is_in_statement_context) { |
179
|
35
|
|
|
|
|
34
|
$is_called_syscalls_in_void = 1; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
elsif ($token_data eq 'no') { |
183
|
1
|
|
|
|
|
2
|
my $next_token = $tokens->[++$i]; |
184
|
1
|
50
|
33
|
|
|
6
|
if ($next_token->{type} == KEY && $next_token->{data} eq 'autodie') { |
185
|
1
|
|
|
|
|
1
|
$is_enabled_autodie = 0; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} |
188
|
97
|
|
|
|
|
243
|
next; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
510
|
100
|
66
|
|
|
558
|
if ( |
|
|
|
66
|
|
|
|
|
192
|
|
|
|
|
|
|
$is_target_all && |
193
|
|
|
|
|
|
|
($token_type == CALL || ($token_type == KEY && $tokens->[++$i]->{type} == LEFT_PAREN)) |
194
|
|
|
|
|
|
|
) { |
195
|
3
|
100
|
66
|
|
|
33
|
if ($allowed_functions && $token_data =~ /\A$allowed_functions\s*\(?/) { |
|
|
50
|
33
|
|
|
|
|
196
|
1
|
|
|
|
|
4
|
next; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
elsif (!$is_in_assign_context && !$is_in_statement_context) { |
199
|
2
|
|
|
|
|
2
|
$is_called_syscalls_in_void = 1; |
200
|
|
|
|
|
|
|
} |
201
|
2
|
|
|
|
|
4
|
next; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
507
|
100
|
|
|
|
528
|
if ($token_kind == KIND_OP) { |
205
|
16
|
|
|
|
|
8
|
$is_in_statement_context = 1; |
206
|
16
|
|
|
|
|
13
|
$is_called_syscalls_in_void = 0; |
207
|
16
|
|
|
|
|
24
|
next; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
491
|
100
|
|
|
|
867
|
if ($token_kind == KIND_STMT_END) { |
211
|
100
|
100
|
|
|
|
134
|
next if $is_enabled_autodie; |
212
|
|
|
|
|
|
|
|
213
|
95
|
100
|
|
|
|
127
|
if ($is_called_syscalls_in_void) { |
214
|
|
|
|
|
|
|
push @violations, { |
215
|
|
|
|
|
|
|
filename => $file, |
216
|
|
|
|
|
|
|
line => $token->{line}, |
217
|
21
|
|
|
|
|
70
|
description => DESC, |
218
|
|
|
|
|
|
|
explanation => EXPL, |
219
|
|
|
|
|
|
|
policy => __PACKAGE__, |
220
|
|
|
|
|
|
|
}; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
95
|
|
|
|
|
61
|
$is_in_assign_context = 0; |
224
|
95
|
|
|
|
|
60
|
$is_in_statement_context = 0; |
225
|
95
|
|
|
|
|
59
|
$is_called_syscalls_in_void = 0; |
226
|
95
|
|
|
|
|
154
|
next; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
40
|
|
|
|
|
150
|
return \@violations; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
1; |
235
|
|
|
|
|
|
|
|