fuzzr 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fuzzr might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.rdoc +28 -0
- data/bin/fuzz +11 -0
- data/fuzzers/check_ace_error.excludes +5 -0
- data/fuzzers/check_ace_error.rb +37 -0
- data/fuzzers/check_catch_ex_as_const.rb +41 -0
- data/fuzzers/check_cout_cerr.excludes +5 -0
- data/fuzzers/check_cout_cerr.rb +37 -0
- data/fuzzers/check_executablebit.rb +37 -0
- data/fuzzers/check_exit_keyword.excludes +2 -0
- data/fuzzers/check_exit_keyword.rb +37 -0
- data/fuzzers/check_fileheader.excludes +5 -0
- data/fuzzers/check_fileheader.rb +92 -0
- data/fuzzers/check_filename.excludes +8 -0
- data/fuzzers/check_filename.rb +33 -0
- data/fuzzers/check_id_tag.excludes +3 -0
- data/fuzzers/check_id_tag.rb +34 -0
- data/fuzzers/check_new_delete.excludes +6 -0
- data/fuzzers/check_new_delete.rb +37 -0
- data/fuzzers/check_printf_keyword.excludes +2 -0
- data/fuzzers/check_printf_keyword.rb +37 -0
- data/fuzzers/check_taox11_namespace.excludes +5 -0
- data/fuzzers/check_taox11_namespace.rb +38 -0
- data/lib/fuzz/console.rb +52 -0
- data/lib/fuzz/fuzz.rb +402 -0
- data/lib/fuzz/fuzzers/check_whitespace.rb +62 -0
- data/lib/fuzz/fzzr.rb +258 -0
- data/lib/fuzz/log.rb +97 -0
- data/lib/fuzz/options.rb +208 -0
- data/lib/fuzz/screen.rb +85 -0
- data/lib/fuzz/system.rb +57 -0
- data/lib/fuzz/version.rb +17 -0
- metadata +81 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# -------------------------------------------------------------------
|
3
|
+
# check_new_delete.rb - TAOX11 new delete checker
|
4
|
+
#
|
5
|
+
# Author: Martin Corino
|
6
|
+
#
|
7
|
+
# Copyright (c) Remedy IT Expertise BV
|
8
|
+
# -------------------------------------------------------------------
|
9
|
+
|
10
|
+
module Fuzzers
|
11
|
+
class TAOX11NewDeleteChecker
|
12
|
+
include Fuzz::Fzzr
|
13
|
+
def initialize
|
14
|
+
@fuzz_id = :check_new_delete
|
15
|
+
@description = 'checks against the use of new and/or delete in test code'
|
16
|
+
@errormsg = 'detected use of new and/or delete'
|
17
|
+
end
|
18
|
+
|
19
|
+
OBJECT_EXTS = ['h', 'hxx', 'hpp', 'c', 'cc', 'cxx', 'cpp', 'H', 'C']
|
20
|
+
|
21
|
+
def applies_to?(object)
|
22
|
+
Fuzz::FileObject === object &&
|
23
|
+
OBJECT_EXTS.include?(object.ext) &&
|
24
|
+
!is_excluded?(object)
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(object, apply_fix)
|
28
|
+
object.iterate(fuzz_id) do |lnptr|
|
29
|
+
if lnptr.text =~ /(^|\s+)(new|delete)(\s+|$)/
|
30
|
+
lnptr.mark_error
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Fuzz.register_fzzr(TAOX11NewDeleteChecker.new)
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# -------------------------------------------------------------------
|
3
|
+
# check_printf_keyword.rb - TAOX11 printf checker
|
4
|
+
#
|
5
|
+
# Author: Johnny Willemsen
|
6
|
+
#
|
7
|
+
# Copyright (c) Remedy IT Expertise BV
|
8
|
+
# -------------------------------------------------------------------
|
9
|
+
|
10
|
+
module Fuzzers
|
11
|
+
class TAOX11PrintfChecker
|
12
|
+
include Fuzz::Fzzr
|
13
|
+
def initialize
|
14
|
+
@fuzz_id = :check_printf_keyword
|
15
|
+
@description = 'checks against the use of the printf keyword in test code'
|
16
|
+
@errormsg = 'detected use of printf'
|
17
|
+
end
|
18
|
+
|
19
|
+
OBJECT_EXTS = ['h', 'hxx', 'hpp', 'c', 'cc', 'cxx', 'cpp', 'H', 'C']
|
20
|
+
|
21
|
+
def applies_to?(object)
|
22
|
+
Fuzz::FileObject === object &&
|
23
|
+
OBJECT_EXTS.include?(object.ext) &&
|
24
|
+
!is_excluded?(object)
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(object, apply_fix)
|
28
|
+
object.iterate(fuzz_id) do |lnptr|
|
29
|
+
if lnptr.text =~ /(^|\s+|::)(printf)(\s+|$)/
|
30
|
+
lnptr.mark_error
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Fuzz.register_fzzr(TAOX11PrintfChecker.new)
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# -------------------------------------------------------------------
|
3
|
+
# check_taox11_namespace.rb - TAOX11 namespace checker
|
4
|
+
#
|
5
|
+
# Author: Martin Corino
|
6
|
+
#
|
7
|
+
# Copyright (c) Remedy IT Expertise BV
|
8
|
+
# -------------------------------------------------------------------
|
9
|
+
|
10
|
+
module Fuzzers
|
11
|
+
class TAOX11NamespaceChecker
|
12
|
+
include Fuzz::Fzzr
|
13
|
+
def initialize
|
14
|
+
@fuzz_id = :check_taox11_namespace
|
15
|
+
@description = 'checks against the use of the TAOX11_NAMESPACE macro in user/test code'
|
16
|
+
@errormsg = 'detected use TAOX11_xxx namespace macro'
|
17
|
+
end
|
18
|
+
|
19
|
+
OBJECT_EXTS = ['h', 'hxx', 'hpp', 'c', 'cc', 'cxx', 'cpp', 'H', 'C']
|
20
|
+
|
21
|
+
def applies_to?(object)
|
22
|
+
Fuzz::FileObject === object &&
|
23
|
+
OBJECT_EXTS.include?(object.ext) &&
|
24
|
+
!is_excluded?(object)
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(object, apply_fix)
|
28
|
+
object.iterate(fuzz_id) do |lnptr|
|
29
|
+
if lnptr.text =~ /(TAOX11_NAMESPACE|TAOX11_CORBA|TAOX11_PORTABLE_SERVER)::/ ||
|
30
|
+
lnptr.text =~ /namespace\s+(TAOX11_NAMESPACE|TAOX11_CORBA|TAOX11_PORTABLE_SERVER)/
|
31
|
+
lnptr.mark_error
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Fuzz.register_fzzr(TAOX11NamespaceChecker.new)
|
38
|
+
end
|
data/lib/fuzz/console.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#--------------------------------------------------------------------
|
2
|
+
# @file console.rb
|
3
|
+
# @author Martin Corino
|
4
|
+
#
|
5
|
+
# @brief Fuzz console wrapper
|
6
|
+
#
|
7
|
+
# @copyright Copyright (c) Remedy IT Expertise BV
|
8
|
+
#--------------------------------------------------------------------
|
9
|
+
require 'fuzz/screen'
|
10
|
+
|
11
|
+
module Fuzz
|
12
|
+
|
13
|
+
module Console
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def screen
|
17
|
+
@screen ||= Screen.new(Fuzz.options[:output] || $stdout, $stdin)
|
18
|
+
end
|
19
|
+
include Screen::ColorizeMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.print(*args)
|
23
|
+
screen.print(*args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.println(*args)
|
27
|
+
screen.println(*args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.error_print(*args)
|
31
|
+
screen.error_print(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.error_println(*args)
|
35
|
+
screen.error_println(*args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.colorizer_include
|
39
|
+
Screen::ColorizeMethods
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.display_break
|
43
|
+
println("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.display_hline(len = nil)
|
47
|
+
println("#{'-' * (len || [80, (screen.output_cols / 5 * 4)].min)}\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
end # Console
|
51
|
+
|
52
|
+
end # Fuzz
|
data/lib/fuzz/fuzz.rb
ADDED
@@ -0,0 +1,402 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# -------------------------------------------------------------------
|
3
|
+
# fuzz.rb - TAOX11 fuzz checker
|
4
|
+
#
|
5
|
+
# Author: Martin Corino
|
6
|
+
#
|
7
|
+
# Copyright (c) Remedy IT Expertise BV
|
8
|
+
# -------------------------------------------------------------------
|
9
|
+
|
10
|
+
require 'optparse'
|
11
|
+
require 'tempfile'
|
12
|
+
require 'fileutils'
|
13
|
+
require 'yaml'
|
14
|
+
require 'fuzz/log'
|
15
|
+
require 'fuzz/system'
|
16
|
+
require 'fuzz/options'
|
17
|
+
require 'fuzz/fzzr'
|
18
|
+
|
19
|
+
module Fuzz
|
20
|
+
VERSION_MAJOR,
|
21
|
+
VERSION_MINOR,
|
22
|
+
VERSION_RELEASE = VERSION.split('.')
|
23
|
+
COPYRIGHT = "Copyright (c) 2012-#{Time.now.year} Remedy IT Expertise BV, The Netherlands".freeze
|
24
|
+
|
25
|
+
def self.root_path
|
26
|
+
f = File.expand_path(__FILE__)
|
27
|
+
f = File.expand_path(File.readlink(f)) if File.symlink?(f)
|
28
|
+
File.dirname(f)
|
29
|
+
end
|
30
|
+
|
31
|
+
FUZZ_ROOT = self.root_path
|
32
|
+
|
33
|
+
class << self
|
34
|
+
|
35
|
+
include LogMethods
|
36
|
+
include Sys::SysMethods
|
37
|
+
|
38
|
+
def reporter
|
39
|
+
@reporter ||= Fuzz::Reporter.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_reporter(rep)
|
43
|
+
@reporter = rep
|
44
|
+
end
|
45
|
+
alias :reporter= :set_reporter
|
46
|
+
|
47
|
+
def options
|
48
|
+
Fuzz::OPTIONS
|
49
|
+
end
|
50
|
+
|
51
|
+
def reset
|
52
|
+
options.reset
|
53
|
+
end
|
54
|
+
|
55
|
+
def load_config
|
56
|
+
options.load_config
|
57
|
+
end
|
58
|
+
|
59
|
+
def includes
|
60
|
+
unless @include_re
|
61
|
+
@include_re = []
|
62
|
+
# @include_re << "\\.(#{Fuzz::FileObject.extensions.join('|')})$"
|
63
|
+
# @include_re << "#{Fuzz::FileObject.filenames.join('|')}$"
|
64
|
+
@include_re << "\\.(#{options.config[:exts].join('|')})$"
|
65
|
+
@include_re << "#{options.config[:filenames].join('|')}$"
|
66
|
+
end
|
67
|
+
@include_re
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# fuzzer registration
|
72
|
+
#
|
73
|
+
|
74
|
+
def fuzzers
|
75
|
+
@fuzzers ||= {}
|
76
|
+
end
|
77
|
+
|
78
|
+
def register_fzzr(fzzr)
|
79
|
+
raise RuntimeError, "Duplicate fuzzer registration: #{fzzr.fuzz_id}" if fuzzers.has_key?(fzzr.fuzz_id)
|
80
|
+
fuzzers[fzzr.fuzz_id] = fzzr
|
81
|
+
fzzr.setup(options.optparser) if options.optparser && fzzr.respond_to?(:setup) && fzzr_included?(fzzr)
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_fzzr(id)
|
85
|
+
fuzzers[id]
|
86
|
+
end
|
87
|
+
|
88
|
+
def fzzr_excluded?(fzzr)
|
89
|
+
options.config[:fzzr_excludes].include?(fzzr.fuzz_id.to_sym)
|
90
|
+
end
|
91
|
+
|
92
|
+
def fzzr_included?(fzzr)
|
93
|
+
!fzzr_excluded?(fzzr)
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# load fuzzers
|
98
|
+
#
|
99
|
+
def load_fuzzers
|
100
|
+
# standard fuzzers included in Gem
|
101
|
+
unless loaded_fzzr_paths.include?(_p = File.join(FUZZ_ROOT, 'fuzzers'))
|
102
|
+
Dir.glob(File.join(_p, '*.rb')).each do |fnm|
|
103
|
+
require fnm
|
104
|
+
end
|
105
|
+
loaded_fzzr_paths << _p
|
106
|
+
end
|
107
|
+
# configured fuzzers
|
108
|
+
options.config[:fzzr_paths].each do |fzzrpath|
|
109
|
+
unless loaded_fzzr_paths.include?(_p = File.expand_path(fzzrpath))
|
110
|
+
Dir.glob(File.join(_p, '*.rb')).each do |fnm|
|
111
|
+
require fnm
|
112
|
+
end
|
113
|
+
loaded_fzzr_paths << _p
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def loaded_fzzr_paths
|
121
|
+
@loaded_fuzzr_paths ||= []
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
## Backwards compatibility
|
127
|
+
def self.log_verbose(msg)
|
128
|
+
log_info(msg) if verbose?
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Option methods
|
133
|
+
#
|
134
|
+
|
135
|
+
def self.verbosity
|
136
|
+
options.verbose
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.apply_fix?
|
140
|
+
options.apply_fix || false
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.follow_symlink?
|
144
|
+
options.config[:follow_symlink] || false
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.excludes
|
148
|
+
options.config[:excludes] || []
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.excluded?(object)
|
152
|
+
excludes.any? { |excl| (object.fullpath =~ /#{excl}/) }
|
153
|
+
end
|
154
|
+
|
155
|
+
#
|
156
|
+
# parse commandline arguments
|
157
|
+
#
|
158
|
+
def self.init_optparser
|
159
|
+
script_name = File.basename($0)
|
160
|
+
if not script_name =~ /fuzz/
|
161
|
+
script_name = "ruby "+$0
|
162
|
+
end
|
163
|
+
|
164
|
+
options.optparser = opts = OptionParser.new
|
165
|
+
opts.banner = "Usage: #{script_name} [options] [glob [glob]]\n\n"
|
166
|
+
opts.separator "\n--- [General options] ---\n\n"
|
167
|
+
opts.on('-t', '--filetype', '=EXT', String,
|
168
|
+
'Defines an alternative filetype to search and scan. Can be specified multiple times.',
|
169
|
+
"Default: #{Fuzz::FileObject.extensions.join('|')}") { |v|
|
170
|
+
(options.user_config[:exts] ||= []) << v
|
171
|
+
}
|
172
|
+
opts.on('-f', '--file', '=NAME', String,
|
173
|
+
'Defines an alternative filename to search and scan. Can be specified multiple times.',
|
174
|
+
"Default: #{Fuzz::FileObject.filenames.join('|')}") { |v|
|
175
|
+
(options.user_config[:filenames] ||= []) << v
|
176
|
+
}
|
177
|
+
opts.on('-a', '--add-files',
|
178
|
+
'Add custom filenames and/or filetype extensions to default list instead of replacing defaults.',
|
179
|
+
'Default: false') { |v|
|
180
|
+
options.user_config[:add_files] = true
|
181
|
+
}
|
182
|
+
opts.on('-S', '--no-symlinks',
|
183
|
+
'Do not follow symlinks.',
|
184
|
+
'Default: follow symlinks') { |v|
|
185
|
+
options.user_config[:follow_symlink] = false
|
186
|
+
}
|
187
|
+
opts.on('-P', '--fzzr-path', '=PATH',
|
188
|
+
'Adds search path for Fuzzers.',
|
189
|
+
"Default: loaded from ~/#{FUZZRC} and/or ./#{FUZZRC}") { |v|
|
190
|
+
(options.user_config[:fzzr_paths] ||= []) << v.to_s
|
191
|
+
}
|
192
|
+
opts.on('-B', '--blacklist', '=FZZRID',
|
193
|
+
'Adds Fuzzer ID to list of fuzzers to exclude from Fuzz check.',
|
194
|
+
'Default: none') { |v|
|
195
|
+
(options.user_config[:fzzr_excludes] ||= []) << v.to_sym
|
196
|
+
}
|
197
|
+
opts.on('-X', '--exclude', '=MASK',
|
198
|
+
'Adds path mask (regular expression) to list to exclude from Fuzz check.',
|
199
|
+
'Default: none') { |v|
|
200
|
+
(options.user_config[:excludes] ||= []) << v
|
201
|
+
}
|
202
|
+
opts.on('-c', '--config', '=FUZZRC',
|
203
|
+
'Load config from FUZZRC file.',
|
204
|
+
"Default: ~/#{FUZZRC} and/or ./#{FUZZRC}") { |v|
|
205
|
+
options.add_config(v)
|
206
|
+
}
|
207
|
+
opts.on('--write-config', '=[FUZZRC]',
|
208
|
+
'Write config to file and exit.',
|
209
|
+
"Default: ./#{FUZZRC}") { |v|
|
210
|
+
options.user_config.save(String === v ? v : FUZZRC)
|
211
|
+
exit
|
212
|
+
}
|
213
|
+
opts.on('--show-config',
|
214
|
+
'Display config settings and exit.') { |v|
|
215
|
+
options.load_config
|
216
|
+
puts YAML.dump(options.config.__send__ :table)
|
217
|
+
exit
|
218
|
+
}
|
219
|
+
|
220
|
+
opts.separator ''
|
221
|
+
opts.on('-o', '--output', '=FILE', String,
|
222
|
+
'Specifies filename to write Fuzz messages to.',
|
223
|
+
'Default: stderr') { |v|
|
224
|
+
options.output = v
|
225
|
+
}
|
226
|
+
opts.on('-p', '--apply-fix',
|
227
|
+
'Apply fixes (if any) for Fuzz errors.',
|
228
|
+
'Default: false') { |v|
|
229
|
+
options.apply_fix = true
|
230
|
+
}
|
231
|
+
opts.on('-n', '--no-recurse',
|
232
|
+
'Prevents directory recursion in file selection.',
|
233
|
+
'Default: recurse') { |v|
|
234
|
+
options.recurse = false
|
235
|
+
}
|
236
|
+
opts.on('-v', '--verbose',
|
237
|
+
'Run with increased verbosity level. Repeat to increase more.',
|
238
|
+
'Default: 1') { |v| options.verbose += 1 }
|
239
|
+
|
240
|
+
opts.separator ''
|
241
|
+
opts.on('-L', '--list',
|
242
|
+
'List available Fuzzers and exit.') {
|
243
|
+
options.load_config
|
244
|
+
load_fuzzers
|
245
|
+
puts "TAOX11 fuzz checker #{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_RELEASE}"
|
246
|
+
puts COPYRIGHT
|
247
|
+
puts('%-30s %s' % %w{Fuzzer Description})
|
248
|
+
puts(('-' * 30)+' '+('-' * 48))
|
249
|
+
fuzzers.values.each { |fzzr| puts('%-30s %s' % [fzzr.fuzz_id, fzzr.description]) }
|
250
|
+
puts
|
251
|
+
exit
|
252
|
+
}
|
253
|
+
|
254
|
+
opts.separator ""
|
255
|
+
opts.on('-V', '--version',
|
256
|
+
'Show version information and exit.') {
|
257
|
+
puts "TAOX11 fuzz checker #{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_RELEASE}"
|
258
|
+
puts COPYRIGHT
|
259
|
+
exit
|
260
|
+
}
|
261
|
+
opts.on('-h', '--help',
|
262
|
+
'Show this help message.') {
|
263
|
+
options.load_config
|
264
|
+
load_fuzzers
|
265
|
+
puts opts;
|
266
|
+
puts;
|
267
|
+
exit
|
268
|
+
}
|
269
|
+
|
270
|
+
opts.separator "\n--- [Fuzzer options] ---\n\n"
|
271
|
+
end
|
272
|
+
|
273
|
+
def self.parse_args(argv)
|
274
|
+
options.optparser.parse!(argv)
|
275
|
+
end
|
276
|
+
|
277
|
+
def self.select_fzzrs(object)
|
278
|
+
fuzzers.values.collect { |fzzr| (fzzr_included?(fzzr) && fzzr.applies_to?(object)) ? fzzr : nil }.compact
|
279
|
+
end
|
280
|
+
|
281
|
+
def self.update_file_object(fo)
|
282
|
+
if File.writable?(fo.fullpath)
|
283
|
+
log_verbose(%Q{Updating #{fo}...})
|
284
|
+
ftmp = Tempfile.new(fo.name)
|
285
|
+
log_verbose(%Q{+ Writing temp file #{ftmp.path}...})
|
286
|
+
fo.lines.each { |ln| ftmp.print ln }
|
287
|
+
ftmp.close(false) # close but do NOT unlink
|
288
|
+
log_verbose(%Q{+ Replacing #{fo} with #{ftmp.path}})
|
289
|
+
# create temporary backup
|
290
|
+
ftmp2 = Tempfile.new(fo.name)
|
291
|
+
ftmp2_name = ftmp2.path.dup
|
292
|
+
ftmp2.close(true)
|
293
|
+
mv(fo.fullpath, ftmp2_name)
|
294
|
+
# replace original
|
295
|
+
begin
|
296
|
+
mv(ftmp.path, fo.fullpath)
|
297
|
+
# preserve file mode
|
298
|
+
chmod(File.lstat(ftmp2_name).mode, fo.fullpath)
|
299
|
+
rescue
|
300
|
+
log_error(%Q{FAILED updating #{fo}: #{$!}})
|
301
|
+
# restore backup
|
302
|
+
mv(ftmp2_name, fo.fullpath)
|
303
|
+
raise
|
304
|
+
end
|
305
|
+
# remove backup
|
306
|
+
File.unlink(ftmp2_name)
|
307
|
+
log_verbose(%Q{Finished updating #{fo}.})
|
308
|
+
return true
|
309
|
+
else
|
310
|
+
log_error(%Q{NO_ACCESS - cannot update #{fo}})
|
311
|
+
return false
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def self.handle_object(object)
|
316
|
+
log_verbose(%Q{Handling #{object}})
|
317
|
+
fzzrs = select_fzzrs(object)
|
318
|
+
no_fixes_allowed = false
|
319
|
+
rc = fzzrs.inject(true) do |result, fzzr|
|
320
|
+
log_verbose(%Q{+ Running fuzzer #{fzzr.fuzz_id}})
|
321
|
+
begin
|
322
|
+
if fzzr.run(object, options.apply_fix)
|
323
|
+
result
|
324
|
+
else
|
325
|
+
log_verbose(%Q{+ Error from fuzzer #{fzzr.fuzz_id}})
|
326
|
+
false
|
327
|
+
end
|
328
|
+
rescue
|
329
|
+
log_error(%Q{EXCEPTION CAUGHT running fuzzer #{fzzr.fuzz_id} on #{object} - #{$!}\n#{$!.backtrace.join("\n")}})
|
330
|
+
no_fixes_allowed = true
|
331
|
+
break ## immediately stop handling this object, rc will remain false
|
332
|
+
end
|
333
|
+
end
|
334
|
+
unless no_fixes_allowed
|
335
|
+
if Fuzz.apply_fix? && object.changed?
|
336
|
+
rc = update_file_object(object) && rc
|
337
|
+
end
|
338
|
+
end
|
339
|
+
rc ? true : false
|
340
|
+
end
|
341
|
+
|
342
|
+
def self.iterate_paths(paths)
|
343
|
+
paths.inject(true) do |result, path|
|
344
|
+
if File.readable?(path) && (!File.symlink?(path) || follow_symlink?)
|
345
|
+
if File.directory?(path)
|
346
|
+
rc = handle_object(dirobj = Fuzz::DirObject.new(path))
|
347
|
+
log_verbose(%Q{Iterating #{path}})
|
348
|
+
if options.recurse && !excluded?(dirobj)
|
349
|
+
rc = iterate_paths(Dir.glob(File.join(path, '*'))) && rc
|
350
|
+
end
|
351
|
+
rc
|
352
|
+
elsif File.file?(path)
|
353
|
+
handle_object(Fuzz::FileObject.new(path))
|
354
|
+
else
|
355
|
+
true
|
356
|
+
end
|
357
|
+
else
|
358
|
+
log_warning(File.readable?(path) ? %Q{Cannot read #{path}} : %Q{Cannot follow symlink #{}path})
|
359
|
+
false
|
360
|
+
end && result
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def self.run_fzzrs(argv)
|
365
|
+
options.config[:exts].concat(Fuzz::FileObject.extensions) if options.config[:exts].empty? || options.config[:add_files]
|
366
|
+
options.config[:filenames].concat(Fuzz::FileObject.filenames) if options.config[:filenames].empty? || options.config[:add_files]
|
367
|
+
|
368
|
+
options.config[:exts].uniq!
|
369
|
+
options.config[:filenames].uniq!
|
370
|
+
|
371
|
+
f_close_output = false
|
372
|
+
if String === options.output
|
373
|
+
options.output = File.open(options.output, 'w')
|
374
|
+
f_close_output = true
|
375
|
+
end
|
376
|
+
begin
|
377
|
+
# determin files/paths to test
|
378
|
+
paths = argv.collect { |a| Dir.glob(a) }.flatten.uniq
|
379
|
+
paths = Dir.glob('*') if paths.empty?
|
380
|
+
# scan all determined objects
|
381
|
+
return iterate_paths(paths)
|
382
|
+
ensure
|
383
|
+
options.output.close if f_close_output
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def self.run
|
388
|
+
init_optparser
|
389
|
+
|
390
|
+
# parse arguments
|
391
|
+
parse_args(ARGV)
|
392
|
+
|
393
|
+
# load config (if any)
|
394
|
+
options.load_config
|
395
|
+
|
396
|
+
# load fuzzers
|
397
|
+
load_fuzzers
|
398
|
+
|
399
|
+
run_fzzrs(ARGV)
|
400
|
+
end
|
401
|
+
|
402
|
+
end
|