ruzzy 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0abba0ffb63d4c50fbbb33fb3624299f8421293a02d65e199525c75b4dbd5f46
4
- data.tar.gz: 4787489da1373bb820cd66d62a913a4c9c33c49bda68f251dae25745ccac3679
3
+ metadata.gz: 64fa385ff3dca5a231ebc02511f7240143838b4cf4314a8ced35a57127ac2dc2
4
+ data.tar.gz: 1cd94db1a0b30debdc03caddf39394b3759b11f85d0b2ef78037e5769b0761ed
5
5
  SHA512:
6
- metadata.gz: c029eca231fbeb0d8b19b469a6cb2de99117a939e35c9f42622f803d06a0b4ad85ceacc25dff1bba9e56b1179358ec8fff054a35d894faa11398727891697216
7
- data.tar.gz: cb761ff27a1fa8d462295d9022d03490338d2608d94cddc8454fb2919fd308e8ee7ea18b4735e601574ca1366de266607c2966be18e27af21ab1c3e243f60237
6
+ metadata.gz: ed77800fbbe359a7b2be3e215b00d052b2bf8f1038da0e2ad88c6a8ea9d66bcf2d875ed5658592262ef35a18a23c4b1f5fcc9d44e7f669fc81817310dda96122
7
+ data.tar.gz: 80ef311558dd4c4aa88697014e08a6b06a164d182a16d5c4718ce9355bc6b2f82c52bce11d3eaa1d1071df2a900eef9ef46148013ad7099ed1fbf07df173b6c3
data/ext/cruzzy/cruzzy.c CHANGED
@@ -194,11 +194,11 @@ static void event_hook_branch(VALUE counter_hash, rb_trace_arg_t *tracearg) {
194
194
 
195
195
  static void enable_branch_coverage_hooks()
196
196
  {
197
- // Call Coverage.setup(branches: true) to activate branch coverage hooks.
197
+ // Call Coverage.start(branches: true) to activate branch coverage hooks.
198
198
  // Branch coverage hooks will not be activated without this call despite
199
199
  // adding the event hooks. I suspect rb_set_coverages must be called
200
200
  // first, which initializes some global state that we do not have direct
201
- // access to. Calling setup initializes coverage state here:
201
+ // access to. Calling start initializes coverage state here:
202
202
  // https://github.com/ruby/ruby/blob/v3_3_0/ext/coverage/coverage.c#L112-L120
203
203
  // If rb_set_coverages is not called, then rb_get_coverages returns a NULL
204
204
  // pointer, which appears to effectively disable coverage collection here:
@@ -207,10 +207,10 @@ static void enable_branch_coverage_hooks()
207
207
  VALUE coverage_mod = rb_const_get(rb_cObject, rb_intern("Coverage"));
208
208
  VALUE hash_arg = rb_hash_new();
209
209
  rb_hash_aset(hash_arg, ID2SYM(rb_intern("branches")), Qtrue);
210
- rb_funcall(coverage_mod, rb_intern("setup"), 1, hash_arg);
210
+ rb_funcall(coverage_mod, rb_intern("start"), 1, hash_arg);
211
211
  }
212
212
 
213
- static VALUE c_trace_branch(VALUE self)
213
+ static VALUE c_trace(VALUE self, VALUE harness_path)
214
214
  {
215
215
  VALUE counter_hash = rb_hash_new();
216
216
 
@@ -230,7 +230,7 @@ static VALUE c_trace_branch(VALUE self)
230
230
 
231
231
  enable_branch_coverage_hooks();
232
232
 
233
- return Qnil;
233
+ return rb_require(StringValueCStr(harness_path));
234
234
  }
235
235
 
236
236
  void Init_cruzzy()
@@ -245,5 +245,5 @@ void Init_cruzzy()
245
245
  rb_define_module_function(ruzzy, "c_libfuzzer_is_loaded", &c_libfuzzer_is_loaded, 0);
246
246
  rb_define_module_function(ruzzy, "c_trace_cmp8", &c_trace_cmp8, 2);
247
247
  rb_define_module_function(ruzzy, "c_trace_div8", &c_trace_div8, 1);
248
- rb_define_module_function(ruzzy, "c_trace_branch", &c_trace_branch, 0);
248
+ rb_define_module_function(ruzzy, "c_trace", &c_trace, 1);
249
249
  }
@@ -64,6 +64,7 @@ def merge_sanitizer_libfuzzer_lib(sanitizer_lib, fuzzer_no_main_lib, merged_outp
64
64
  '-Wl,--no-whole-archive',
65
65
  '-lpthread',
66
66
  '-ldl',
67
+ '-lstdc++',
67
68
  '-shared',
68
69
  '-o',
69
70
  merged_output
@@ -137,4 +138,6 @@ merge_sanitizer_libfuzzer_lib(
137
138
  # For more information, see https://github.com/ruby/ruby/blob/master/lib/mkmf.rb.
138
139
  $LOCAL_LIBS = fuzzer_no_main_lib
139
140
 
141
+ $LIBS << ' -lstdc++'
142
+
140
143
  create_makefile('cruzzy/cruzzy')
data/ext/dummy/dummy.c CHANGED
@@ -6,17 +6,18 @@
6
6
  // https://llvm.org/docs/LibFuzzer.html#toy-example
7
7
  static int _c_dummy_test_one_input(const uint8_t *data, size_t size)
8
8
  {
9
- char test[] = {'a', 'b', 'c'};
9
+ volatile char boom = 'x';
10
10
 
11
- if (size > 0 && data[0] == 'H') {
12
- if (size > 1 && data[1] == 'I') {
13
- // This code exists specifically to test the driver and ensure
14
- // libFuzzer is functioning as expected, so we can safely ignore
15
- // the warning.
16
- #pragma clang diagnostic push
17
- #pragma clang diagnostic ignored "-Warray-bounds"
18
- test[1024] = 'd';
19
- #pragma clang diagnostic pop
11
+ if (size == 2) {
12
+ if (data[0] == 'H') {
13
+ if (data[1] == 'I') {
14
+ // Intentional heap-use-after-free for testing purposes
15
+ char * volatile ptr = malloc(128);
16
+ ptr[0] = 'x';
17
+ free(ptr);
18
+ boom = ptr[0];
19
+ (void) boom;
20
+ }
20
21
  }
21
22
  }
22
23
 
data/lib/ruzzy.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'pathname'
4
4
 
5
- # A Ruby C extension fuzzer
5
+ # A coverage-guided fuzzer for pure Ruby code and Ruby C extensions
6
6
  module Ruzzy
7
7
  require 'cruzzy/cruzzy'
8
8
 
@@ -15,10 +15,6 @@ module Ruzzy
15
15
  c_fuzz(test_one_input, args)
16
16
  end
17
17
 
18
- def dummy
19
- fuzz(->(data) { Ruzzy.dummy_test_one_input(data) })
20
- end
21
-
22
18
  def dummy_test_one_input(data)
23
19
  # This 'require' depends on LD_PRELOAD, so it's placed inside the function
24
20
  # scope. This allows us to access EXT_PATH for LD_PRELOAD and not have a
@@ -28,9 +24,28 @@ module Ruzzy
28
24
  c_dummy_test_one_input(data)
29
25
  end
30
26
 
27
+ def dummy
28
+ fuzz(->(data) { dummy_test_one_input(data) })
29
+ end
30
+
31
+ def trace(harness_script)
32
+ harness_path = Pathname.new(harness_script)
33
+
34
+ # Mimic require_relative. If harness script is provided as an absolute path,
35
+ # then use that. If not, then assume the script is in the same directory as
36
+ # as the tracer script, i.e. the caller.
37
+ if !harness_path.absolute?
38
+ caller_path = Pathname.new(caller_locations.first.path)
39
+ harness_path = (caller_path.parent / harness_path).realpath
40
+ end
41
+
42
+ c_trace(harness_path.to_s)
43
+ end
44
+
31
45
  module_function :fuzz
32
- module_function :dummy
33
46
  module_function :dummy_test_one_input
47
+ module_function :dummy
48
+ module_function :trace
34
49
  end
35
50
 
36
51
  # Hook Integer operations for tracing in SantizerCoverage
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruzzy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trail of Bits
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-13 00:00:00.000000000 Z
11
+ date: 2024-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -101,5 +101,5 @@ requirements: []
101
101
  rubygems_version: 3.5.3
102
102
  signing_key:
103
103
  specification_version: 4
104
- summary: A Ruby C extension fuzzer
104
+ summary: A coverage-guided fuzzer for pure Ruby code and Ruby C extensions
105
105
  test_files: []