Module: Ruzzy

Defined in:
lib/ruzzy.rb,
lib/ruzzy/fuzzed_data_provider.rb

Overview

A coverage-guided fuzzer for pure Ruby code and Ruby C extensions

Defined Under Namespace

Classes: FuzzedDataProvider

Constant Summary collapse

DEFAULT_ARGS =
[$PROGRAM_NAME] + ARGV
EXT_PATH =
Pathname.new(__FILE__).parent.parent / 'ext' / 'cruzzy'
ASAN_PATH =
(EXT_PATH / 'asan_with_fuzzer.so').to_s
UBSAN_PATH =
(EXT_PATH / 'ubsan_with_fuzzer.so').to_s

Class Method Summary collapse

Class Method Details

.dummyObject



28
29
30
31
32
33
34
35
# File 'lib/ruzzy.rb', line 28

def dummy
  # Load the instrumented shared object before calling fuzz so its coverage
  # maps are registered before LLVMFuzzerRunDriver starts. Some fuzzer
  # runtimes (e.g. LibAFL) require coverage maps to exist upfront.
  require 'dummy/dummy'

  fuzz(->(data) { dummy_test_one_input(data) })
end

.dummy_test_one_input(data) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/ruzzy.rb', line 19

def dummy_test_one_input(data)
  # This 'require' depends on LD_PRELOAD, so it's placed inside the function
  # scope. This allows us to access EXT_PATH for LD_PRELOAD and not have a
  # circular dependency.
  require 'dummy/dummy'

  c_dummy_test_one_input(data)
end

.fuzz(test_one_input, args = DEFAULT_ARGS) ⇒ Object



15
16
17
# File 'lib/ruzzy.rb', line 15

def fuzz(test_one_input, args = DEFAULT_ARGS)
  c_fuzz(test_one_input, args)
end

.trace(harness_script) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ruzzy.rb', line 37

def trace(harness_script)
  harness_path = Pathname.new(harness_script)

  # Mimic require_relative. If harness script is provided as an absolute path,
  # then use that. If not, then assume the script is in the same directory as
  # as the tracer script, i.e. the caller.
  if !harness_path.absolute?
    caller_path = Pathname.new(caller_locations.first.path)
    harness_path = (caller_path.parent / harness_path).realpath
  end

  c_trace(harness_path.to_s)
end