pluginscan 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.gitlab-ci.yml +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +46 -0
- data/.rubocop_todo.yml +36 -0
- data/CHANGELOG.md +89 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +90 -0
- data/README.md +56 -0
- data/Rakefile +2 -0
- data/TODO.md +8 -0
- data/bin/pluginscan +53 -0
- data/lib/file_creator.rb +18 -0
- data/lib/pluginscan.rb +69 -0
- data/lib/pluginscan/error.rb +9 -0
- data/lib/pluginscan/error_printer.rb +17 -0
- data/lib/pluginscan/file_finder.rb +42 -0
- data/lib/pluginscan/printer.rb +14 -0
- data/lib/pluginscan/reports/cloc_report.rb +27 -0
- data/lib/pluginscan/reports/cloc_report/cloc.rb +21 -0
- data/lib/pluginscan/reports/cloc_report/cloc_printer.rb +42 -0
- data/lib/pluginscan/reports/cloc_report/cloc_scanner.rb +41 -0
- data/lib/pluginscan/reports/cloc_report/system_cloc.rb +33 -0
- data/lib/pluginscan/reports/issues_report.rb +24 -0
- data/lib/pluginscan/reports/issues_report/error_list_printer.rb +99 -0
- data/lib/pluginscan/reports/issues_report/issue_checks.rb +382 -0
- data/lib/pluginscan/reports/issues_report/issue_checks/check.rb +55 -0
- data/lib/pluginscan/reports/issues_report/issue_checks/comment_checker.rb +13 -0
- data/lib/pluginscan/reports/issues_report/issue_checks/function_check.rb +32 -0
- data/lib/pluginscan/reports/issues_report/issue_checks/variable_check.rb +14 -0
- data/lib/pluginscan/reports/issues_report/issue_checks/variable_safety_checker.rb +112 -0
- data/lib/pluginscan/reports/issues_report/issues_models/check_findings.rb +29 -0
- data/lib/pluginscan/reports/issues_report/issues_models/issues.rb +31 -0
- data/lib/pluginscan/reports/issues_report/issues_printer.rb +34 -0
- data/lib/pluginscan/reports/issues_report/issues_printer/check_findings_printer.rb +37 -0
- data/lib/pluginscan/reports/issues_report/issues_printer/file_issues_printer.rb +36 -0
- data/lib/pluginscan/reports/issues_report/issues_printer/finding_printer.rb +38 -0
- data/lib/pluginscan/reports/issues_report/issues_printer_factory.rb +19 -0
- data/lib/pluginscan/reports/issues_report/issues_scanner.rb +49 -0
- data/lib/pluginscan/reports/issues_report/issues_scanner/file_issues_scanner.rb +39 -0
- data/lib/pluginscan/reports/issues_report/issues_scanner/line_issues_scanner.rb +15 -0
- data/lib/pluginscan/reports/issues_report/issues_scanner/utf8_checker.rb +14 -0
- data/lib/pluginscan/reports/sloccount_report.rb +26 -0
- data/lib/pluginscan/reports/sloccount_report/sloccount.rb +19 -0
- data/lib/pluginscan/reports/sloccount_report/sloccount_printer.rb +22 -0
- data/lib/pluginscan/reports/sloccount_report/sloccount_scanner.rb +86 -0
- data/lib/pluginscan/reports/vulnerability_report.rb +28 -0
- data/lib/pluginscan/reports/vulnerability_report/advisories_api.rb +23 -0
- data/lib/pluginscan/reports/vulnerability_report/vulnerabilities_printer.rb +55 -0
- data/lib/pluginscan/reports/vulnerability_report/vulnerability_scanner.rb +17 -0
- data/lib/pluginscan/reports/vulnerability_report/wp_vuln_db_api.rb +77 -0
- data/lib/pluginscan/version.rb +3 -0
- data/pluginscan.gemspec +31 -0
- data/spec/acceptance/cloc_spec.rb +54 -0
- data/spec/acceptance/create_error_list_file_spec.rb +29 -0
- data/spec/acceptance/issues_spec.rb +197 -0
- data/spec/acceptance/pluginscan_spec.rb +18 -0
- data/spec/acceptance/sloccount_spec.rb +39 -0
- data/spec/acceptance/vulnerabilities_spec.rb +57 -0
- data/spec/acceptance_spec_helper.rb +10 -0
- data/spec/checks_examples_spec.rb +352 -0
- data/spec/file_creator_spec.rb +51 -0
- data/spec/pluginscan/cloc_scanner/cloc_scanner_spec.rb +64 -0
- data/spec/pluginscan/cloc_scanner/cloc_spec.rb +30 -0
- data/spec/pluginscan/file_finder_spec.rb +91 -0
- data/spec/pluginscan/issues_scanner/check_findings_spec.rb +22 -0
- data/spec/pluginscan/issues_scanner/error_list_printer_ignores_spec.rb +35 -0
- data/spec/pluginscan/issues_scanner/error_list_printer_spec.rb +42 -0
- data/spec/pluginscan/issues_scanner/file_issues_scanner_spec.rb +25 -0
- data/spec/pluginscan/issues_scanner/issues_printer_factory_spec.rb +9 -0
- data/spec/pluginscan/issues_scanner/issues_spec.rb +55 -0
- data/spec/pluginscan/issues_scanner/variable_check_spec.rb +13 -0
- data/spec/pluginscan/issues_scanner/variable_safety_checker_spec.rb +81 -0
- data/spec/pluginscan/issues_scanner_spec.rb +21 -0
- data/spec/pluginscan/sloccount_scanner/sloccount_scanner_spec.rb +95 -0
- data/spec/pluginscan/sloccount_scanner/sloccount_spec.rb +72 -0
- data/spec/pluginscan/vulnerability_scanner_spec.rb +96 -0
- data/spec/process_spec_helper.rb +6 -0
- data/spec/spec_helper.rb +70 -0
- data/spec/support/acceptance_helpers.rb +68 -0
- data/spec/support/file_helpers.rb +35 -0
- data/spec/support/heredoc_helper.rb +7 -0
- data/spec/support/process_helpers.rb +25 -0
- data/spec/support/shared_examples_for_issue_checks.rb +31 -0
- data/spec/support/vcr_helper.rb +6 -0
- data/vcr_cassettes/wpvulndb/relevanssi.yml +78 -0
- metadata +342 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
require "pluginscan/reports/issues_report/issue_checks/check"
|
|
2
|
+
require "pluginscan/reports/issues_report/issue_checks/function_check"
|
|
3
|
+
require "pluginscan/reports/issues_report/issue_checks/variable_check"
|
|
4
|
+
require "pluginscan/reports/issues_report/issue_checks/variable_safety_checker"
|
|
5
|
+
require "pluginscan/reports/issues_report/issue_checks/comment_checker"
|
|
6
|
+
|
|
7
|
+
module Pluginscan
|
|
8
|
+
THE_CHECKS = [
|
|
9
|
+
#
|
|
10
|
+
# Look for superglobal arrays. Use of data from these arrays should be checked for unsanitised or unescaped use.
|
|
11
|
+
#
|
|
12
|
+
VariableCheck.new(
|
|
13
|
+
name: 'Superglobal',
|
|
14
|
+
message: 'Superglobal requires manual review',
|
|
15
|
+
variables: %w(
|
|
16
|
+
$_GET
|
|
17
|
+
$_POST
|
|
18
|
+
$_SERVER
|
|
19
|
+
$_REQUEST
|
|
20
|
+
$_COOKIE
|
|
21
|
+
$_ENV
|
|
22
|
+
$_FILES
|
|
23
|
+
),
|
|
24
|
+
),
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# Check for SQLi
|
|
28
|
+
#
|
|
29
|
+
Check.new(
|
|
30
|
+
name: 'Database access',
|
|
31
|
+
message: 'Database access requires manual review',
|
|
32
|
+
patterns: [
|
|
33
|
+
/\$wpdb/,
|
|
34
|
+
],
|
|
35
|
+
ignores: [
|
|
36
|
+
/global.+\$wpdb/,
|
|
37
|
+
lambda do |line|
|
|
38
|
+
# Try to exclude some things that are definitely not injectable
|
|
39
|
+
# safe_things = %w(prefix postmeta comments commentmeta links options posts terms term_relationships term_taxonomy usermeta users blogs blog_versions registration_log signups site sitecategories sitemeta).each do |safe|
|
|
40
|
+
# line.gsub!(/\$wpdb->#{safe}/, '')
|
|
41
|
+
# end
|
|
42
|
+
|
|
43
|
+
# If it doesn't look like the whole call is on this line, all bets are off
|
|
44
|
+
return false if line.count('(') != line.count(')')
|
|
45
|
+
|
|
46
|
+
# If it looks like they might be concatenating a string, all bets are off
|
|
47
|
+
return false if line.match(/["']{1}\s*\./) || line.match(/\.\s['"]{1}/)
|
|
48
|
+
|
|
49
|
+
# If the first occurrence of $wpdb is a function call ($wpdb->thing())
|
|
50
|
+
# then we don't care about it or anything before it
|
|
51
|
+
line = line.gsub(/^.*?\$wpdb-/, '')
|
|
52
|
+
|
|
53
|
+
# If there's anything before the first wpdb, which can't result in it getting
|
|
54
|
+
# assigned to something else, then we can delete all of that
|
|
55
|
+
line = line.gsub(/^[^(=]*?\$wpdb/, '')
|
|
56
|
+
|
|
57
|
+
# $wpdb->whatever is safe
|
|
58
|
+
line = line.gsub(Regexp.new(Regexp.escape("$wpdb->")), '')
|
|
59
|
+
|
|
60
|
+
# Are there any variables left?
|
|
61
|
+
!line.match(/\$[a-z]{1}[a-z0-9_]*/)
|
|
62
|
+
end,
|
|
63
|
+
]
|
|
64
|
+
),
|
|
65
|
+
|
|
66
|
+
FunctionCheck.new(
|
|
67
|
+
name: 'MySQL functions',
|
|
68
|
+
message: 'People shouldn\'t use MySQL functions in WordPress.',
|
|
69
|
+
patterns: [
|
|
70
|
+
/mysqli?_[a-z0-9_]+/,
|
|
71
|
+
]
|
|
72
|
+
),
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Arbitrary code execution
|
|
76
|
+
#
|
|
77
|
+
FunctionCheck.new(
|
|
78
|
+
name: 'PHP code generation',
|
|
79
|
+
message: 'Code generation functions might be bad',
|
|
80
|
+
function_names: %w(
|
|
81
|
+
eval
|
|
82
|
+
create_function
|
|
83
|
+
assert
|
|
84
|
+
),
|
|
85
|
+
),
|
|
86
|
+
|
|
87
|
+
FunctionCheck.new(
|
|
88
|
+
name: 'User-controllable function calls',
|
|
89
|
+
message: 'What functions are they calling?',
|
|
90
|
+
patterns: [
|
|
91
|
+
/\$\$[a-zA-Z0-9_]+\s*\(/,
|
|
92
|
+
],
|
|
93
|
+
function_names: %w(
|
|
94
|
+
call_user_func
|
|
95
|
+
call_user_func_array
|
|
96
|
+
),
|
|
97
|
+
),
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# Execution of system commands
|
|
101
|
+
#
|
|
102
|
+
FunctionCheck.new(
|
|
103
|
+
name: 'System calls',
|
|
104
|
+
message: 'Executing system commands might be bad',
|
|
105
|
+
patterns: [
|
|
106
|
+
/`.+`/,
|
|
107
|
+
],
|
|
108
|
+
function_names: %w(
|
|
109
|
+
popen
|
|
110
|
+
expect_popen
|
|
111
|
+
proc_optioni
|
|
112
|
+
exec
|
|
113
|
+
shell_exec
|
|
114
|
+
system
|
|
115
|
+
passthru
|
|
116
|
+
),
|
|
117
|
+
),
|
|
118
|
+
|
|
119
|
+
#
|
|
120
|
+
# File manipulation: arbitrary code, altering system configs, info leakage
|
|
121
|
+
#
|
|
122
|
+
FunctionCheck.new(
|
|
123
|
+
name: 'File operations',
|
|
124
|
+
message: 'File operations require manual review',
|
|
125
|
+
patterns: [
|
|
126
|
+
/xdiff_[a-z0-9_]+/,
|
|
127
|
+
],
|
|
128
|
+
function_names: %w(
|
|
129
|
+
bzwrite
|
|
130
|
+
chmod
|
|
131
|
+
chgrp
|
|
132
|
+
chown
|
|
133
|
+
copy
|
|
134
|
+
file_put_contents
|
|
135
|
+
fputscv
|
|
136
|
+
fputs
|
|
137
|
+
fprintf
|
|
138
|
+
ftruncate
|
|
139
|
+
fwrite
|
|
140
|
+
gzwrite
|
|
141
|
+
gzputs
|
|
142
|
+
loadXML
|
|
143
|
+
makedir
|
|
144
|
+
move_uploaded_file
|
|
145
|
+
rename
|
|
146
|
+
unlink
|
|
147
|
+
vfprintf
|
|
148
|
+
yaml_emit_file
|
|
149
|
+
fread
|
|
150
|
+
fget
|
|
151
|
+
fgets
|
|
152
|
+
fgetss
|
|
153
|
+
fgetc
|
|
154
|
+
fpassthru
|
|
155
|
+
glob
|
|
156
|
+
file_get_contents
|
|
157
|
+
fgetcsv
|
|
158
|
+
file
|
|
159
|
+
bzread
|
|
160
|
+
gzread
|
|
161
|
+
gzgets
|
|
162
|
+
gzgetss
|
|
163
|
+
gzgetc
|
|
164
|
+
gzpassthru
|
|
165
|
+
finfo_file
|
|
166
|
+
highlight_file
|
|
167
|
+
show_source
|
|
168
|
+
readlink
|
|
169
|
+
),
|
|
170
|
+
),
|
|
171
|
+
|
|
172
|
+
#
|
|
173
|
+
# Attempts to obfuscate badware
|
|
174
|
+
#
|
|
175
|
+
FunctionCheck.new(
|
|
176
|
+
name: 'Possible obfuscation',
|
|
177
|
+
message: 'Are these obfuscating code or other badstuff?',
|
|
178
|
+
function_names: %w(
|
|
179
|
+
str_rot13
|
|
180
|
+
uudecode
|
|
181
|
+
base64_decode
|
|
182
|
+
base64_encode
|
|
183
|
+
),
|
|
184
|
+
),
|
|
185
|
+
|
|
186
|
+
#
|
|
187
|
+
# Network activity - remote shells, information leakage
|
|
188
|
+
#
|
|
189
|
+
FunctionCheck.new(
|
|
190
|
+
name: 'Network functions',
|
|
191
|
+
message: 'Who\'s sending what and where?',
|
|
192
|
+
patterns: [
|
|
193
|
+
/ftp_[a-z0-9_]+/,
|
|
194
|
+
/socket_[a-z0-9_]+/,
|
|
195
|
+
],
|
|
196
|
+
function_names: %w(
|
|
197
|
+
curl_exec
|
|
198
|
+
curl_setopt
|
|
199
|
+
fsockopen
|
|
200
|
+
get_headers
|
|
201
|
+
wp_get_http
|
|
202
|
+
wp_get_http_headers
|
|
203
|
+
wp_remote_get
|
|
204
|
+
wp_remote_post
|
|
205
|
+
wp_remote_request
|
|
206
|
+
wp_remote_head
|
|
207
|
+
),
|
|
208
|
+
),
|
|
209
|
+
|
|
210
|
+
#
|
|
211
|
+
# Potentially unsafe wordpress functions
|
|
212
|
+
#
|
|
213
|
+
FunctionCheck.new(
|
|
214
|
+
name: 'Potentially unsafe wordpress functions',
|
|
215
|
+
message: 'Some wordpress functions are not inherently safe, this functions return value may not be safe.',
|
|
216
|
+
function_names: %w(
|
|
217
|
+
wp_unslash
|
|
218
|
+
wp_get_referer
|
|
219
|
+
wp_get_original_referer
|
|
220
|
+
esc_sql
|
|
221
|
+
),
|
|
222
|
+
),
|
|
223
|
+
|
|
224
|
+
#
|
|
225
|
+
# PHP object injection
|
|
226
|
+
#
|
|
227
|
+
FunctionCheck.new(
|
|
228
|
+
name: 'PHP object injection',
|
|
229
|
+
message: "If an object can be created where this function does something dangerous, that's bad",
|
|
230
|
+
function_names: %w(
|
|
231
|
+
__wakeup
|
|
232
|
+
__destruct
|
|
233
|
+
__toString
|
|
234
|
+
unserialize
|
|
235
|
+
),
|
|
236
|
+
),
|
|
237
|
+
|
|
238
|
+
#
|
|
239
|
+
# These functions parse strings into variables
|
|
240
|
+
#
|
|
241
|
+
FunctionCheck.new(
|
|
242
|
+
name: 'Variable parsing',
|
|
243
|
+
message: 'These functions parse strings into varables. Could be used as part of an Arbitrary Code Execution',
|
|
244
|
+
function_names: %w(
|
|
245
|
+
parse_str
|
|
246
|
+
extract
|
|
247
|
+
),
|
|
248
|
+
),
|
|
249
|
+
|
|
250
|
+
#
|
|
251
|
+
# Using primitives where the WordPress API provides a better alternative
|
|
252
|
+
#
|
|
253
|
+
FunctionCheck.new(
|
|
254
|
+
name: 'Redundant functions',
|
|
255
|
+
message: 'People using these should probably be using the WordPress API instead',
|
|
256
|
+
function_names: %w(
|
|
257
|
+
htmlspecialchars
|
|
258
|
+
mail
|
|
259
|
+
),
|
|
260
|
+
# Should we ignore user-created mail() functions?
|
|
261
|
+
# Or is the point of this test to check for those? -dgms
|
|
262
|
+
),
|
|
263
|
+
|
|
264
|
+
#
|
|
265
|
+
# What it says on the tin. WTF. lolwat.
|
|
266
|
+
#
|
|
267
|
+
FunctionCheck.new(
|
|
268
|
+
name: 'Batshit weird',
|
|
269
|
+
message: 'What on earth is it doing?',
|
|
270
|
+
patterns: [
|
|
271
|
+
/runkit_[a-z0-9_]+/,
|
|
272
|
+
/ldap_[a-z0-9_]+/,
|
|
273
|
+
],
|
|
274
|
+
function_names: %w(
|
|
275
|
+
ini_set
|
|
276
|
+
put_env
|
|
277
|
+
sleep
|
|
278
|
+
|
|
279
|
+
apache_set_env
|
|
280
|
+
|
|
281
|
+
session_decode
|
|
282
|
+
),
|
|
283
|
+
),
|
|
284
|
+
|
|
285
|
+
#
|
|
286
|
+
# Accidents
|
|
287
|
+
#
|
|
288
|
+
Check.new(
|
|
289
|
+
name: 'Accidents',
|
|
290
|
+
message: 'Did someone do a silly?',
|
|
291
|
+
patterns: [
|
|
292
|
+
/\btodo\b/i,
|
|
293
|
+
/\bfixme\b/i,
|
|
294
|
+
/\bfuck\b/i,
|
|
295
|
+
/\bshit\b/i,
|
|
296
|
+
/\bcrap\b/i,
|
|
297
|
+
/\bbroken\b/i,
|
|
298
|
+
/\bhack\b/i,
|
|
299
|
+
/\bxxx\b/i,
|
|
300
|
+
/\bugly\b/i,
|
|
301
|
+
/\bscary\b/i,
|
|
302
|
+
/\bwtf\b/i,
|
|
303
|
+
/\bsecurity\b/i,
|
|
304
|
+
/\bbodge\b/i,
|
|
305
|
+
/\bhardening\b/i,
|
|
306
|
+
]
|
|
307
|
+
),
|
|
308
|
+
|
|
309
|
+
#
|
|
310
|
+
# Security Policy
|
|
311
|
+
#
|
|
312
|
+
Check.new(
|
|
313
|
+
name: 'Inline JavaScript',
|
|
314
|
+
message: 'Is there inline javascript which would prevent us enforcing a content security policy?',
|
|
315
|
+
patterns: [
|
|
316
|
+
/<script/i,
|
|
317
|
+
],
|
|
318
|
+
ignores: [
|
|
319
|
+
/<script[^>]*\ +src=/i # tags containing src don't include inline JS
|
|
320
|
+
]
|
|
321
|
+
),
|
|
322
|
+
|
|
323
|
+
Check.new(
|
|
324
|
+
name: 'Inline CSS',
|
|
325
|
+
message: 'Is there inline css which would prevent us enforcing a content security policy?',
|
|
326
|
+
patterns: [
|
|
327
|
+
/<style/i,
|
|
328
|
+
],
|
|
329
|
+
),
|
|
330
|
+
|
|
331
|
+
Check.new(
|
|
332
|
+
name: 'Event Attributes',
|
|
333
|
+
message: 'Are there HTML event attributes which can execute inline JavaScript and thus prevent us enforcing a content security policy?',
|
|
334
|
+
patterns: [
|
|
335
|
+
/<[^>]* (on[[:alpha:]]+)=/i, # All event attributes start with "on" e.g. "onclick"
|
|
336
|
+
],
|
|
337
|
+
),
|
|
338
|
+
|
|
339
|
+
#
|
|
340
|
+
# Direct Loading of files
|
|
341
|
+
#
|
|
342
|
+
Check.new(
|
|
343
|
+
name: 'Direct loading',
|
|
344
|
+
message: 'Is someone trying to make a file that can be included directly?',
|
|
345
|
+
patterns: [
|
|
346
|
+
/wp-load\.php/,
|
|
347
|
+
],
|
|
348
|
+
),
|
|
349
|
+
|
|
350
|
+
#
|
|
351
|
+
# Unreliable IP addresses
|
|
352
|
+
#
|
|
353
|
+
Check.new(
|
|
354
|
+
name: 'Unreliable IP',
|
|
355
|
+
message: 'Are they making unsafe assumptions about client IP addresses?',
|
|
356
|
+
patterns: [
|
|
357
|
+
/HTTP_X_FORWARDED_FOR/,
|
|
358
|
+
/HTTP_CLIENT_IP/,
|
|
359
|
+
/HTTP_X_CLUSTER_CLIENT_IP/,
|
|
360
|
+
/HTTP_X_FORWARDED/,
|
|
361
|
+
/HTTP_FORWARDED_FOR/,
|
|
362
|
+
/HTTP_CF_CONNECTING_IP/,
|
|
363
|
+
/HTTP_X_REAL_IP/,
|
|
364
|
+
/HTTP_FORWARDED/,
|
|
365
|
+
]
|
|
366
|
+
),
|
|
367
|
+
|
|
368
|
+
#
|
|
369
|
+
# Version leaks
|
|
370
|
+
#
|
|
371
|
+
FunctionCheck.new(
|
|
372
|
+
name: 'Version leaks',
|
|
373
|
+
message: 'Are they leaking secrets to the enemy?',
|
|
374
|
+
function_names: [
|
|
375
|
+
'phpversion',
|
|
376
|
+
],
|
|
377
|
+
patterns: [
|
|
378
|
+
/(?:get_)?bloginfo\(.*?version/,
|
|
379
|
+
],
|
|
380
|
+
),
|
|
381
|
+
].freeze
|
|
382
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Pluginscan
|
|
2
|
+
# Responsible for checking a string against set of rexgexps and returning all matches
|
|
3
|
+
class Check
|
|
4
|
+
attr_reader :name, :message, :patterns, :ignores
|
|
5
|
+
|
|
6
|
+
def initialize(check_hash)
|
|
7
|
+
@name = check_hash[:name]
|
|
8
|
+
@message = check_hash[:message]
|
|
9
|
+
@patterns = Array(check_hash[:patterns])
|
|
10
|
+
@ignores = Array(check_hash[:ignores]).map do |ignore_thing|
|
|
11
|
+
IgnoreThing.new(ignore_thing)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def run(content)
|
|
16
|
+
pattern_matches(content).map{ |matchdata| match(matchdata) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def ignore?(_match, content)
|
|
20
|
+
# `match` is not used in the default case, but is included
|
|
21
|
+
# so that classes inheriting from this one can use it when deciding
|
|
22
|
+
# whether or not to ignore content by overriding this function
|
|
23
|
+
ignores.any? { |ignore_thing| ignore_thing.ignore?(content) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def pattern_matches(content)
|
|
29
|
+
@patterns.map { |pattern| content.match(pattern) }.compact
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
IgnoreThing = Struct.new(:ignore_thing) do
|
|
33
|
+
def ignore?(content)
|
|
34
|
+
case ignore_thing
|
|
35
|
+
when Regexp
|
|
36
|
+
content.match(ignore_thing)
|
|
37
|
+
when Proc
|
|
38
|
+
ignore_thing.call(content)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def match(matchdata)
|
|
44
|
+
# Select the string we were interested in from the matchdata
|
|
45
|
+
matchdata.to_a.last
|
|
46
|
+
# This will return what we want assuming that we have either:
|
|
47
|
+
# a single item from a simple regex:
|
|
48
|
+
# #<MatchData "$_POST">.to_a
|
|
49
|
+
# => ["$_POST"]
|
|
50
|
+
# a whole match and a specific match, from a function_list item:
|
|
51
|
+
# #<MatchData "@unlink(" 1:"unlink">.to_a
|
|
52
|
+
# => ["@unlink(", "unlink"]
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Pluginscan
|
|
2
|
+
# Responsible for deciding whether usages of a variable in a string are in a comment
|
|
3
|
+
module CommentChecker
|
|
4
|
+
COMMENT_REGEXPS = [
|
|
5
|
+
%r{^\s*//}, # line comment
|
|
6
|
+
/^\s*\*/, # block comment
|
|
7
|
+
].freeze
|
|
8
|
+
|
|
9
|
+
def self.commented?(content)
|
|
10
|
+
COMMENT_REGEXPS.any? { |regexp| content.match(regexp) }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|