Ruzzy

Seamlessly automate and integrate Ruzzy into your existing workflows

Ruzzy is a community skill for fuzz testing Ruby C extensions using the Ruzzy fuzzing framework, covering harness creation, coverage-guided fuzzing, crash analysis, bug reproduction, and integration with continuous testing workflows.

What Is This?

Overview

Ruzzy provides tools for fuzz testing Ruby C extensions to discover memory safety bugs and crashes. It covers harness creation that writes fuzzing targets wrapping Ruby C extension functions with appropriate input generation, coverage-guided fuzzing that uses code coverage feedback to explore execution paths through the C extension code, crash analysis that captures and categorizes crashes by type including buffer overflows, null dereferences, and memory corruption, bug reproduction that minimizes crashing inputs to the smallest test case that triggers the bug, and integration with continuous testing that runs fuzz campaigns as part of CI pipelines. The skill helps Ruby developers find C extension bugs.

Who Should Use This

This skill serves Ruby gem maintainers with C extensions that process untrusted input, security researchers auditing Ruby native code for vulnerabilities, and teams building Ruby applications that depend on C extension gems.

Why Use It?

Problems It Solves

Ruby C extensions bypass Ruby's memory safety and can introduce buffer overflows and use-after-free vulnerabilities. Traditional unit tests cannot explore the vast input space needed to trigger edge-case crashes in C code. Manually constructing test inputs that trigger specific C extension code paths is impractical. Identifying the root cause of a crash requires minimizing the input and analyzing the execution trace.

Core Highlights

Harness builder creates fuzzing targets for Ruby C extension functions. Coverage engine guides input generation toward unexplored code paths. Crash analyzer categorizes and deduplicates discovered crashes. Input minimizer reduces crashing inputs to minimal reproduction cases.

How to Use It?

Basic Usage

require 'ruzzy'

Ruzzy.fuzz do |data|
  begin
    MyParser.parse(
      data)
  rescue StandardError
    # Expected errors
    # are ignored
  end
end

Ruzzy.fuzz(
  max_len: 1024,
  timeout: 300,
  corpus_dir:
    './corpus'
) do |data|
  begin
    result =
      NativeLib.process(
        data)
    # Check invariants
    raise 'bad output' if
      result.nil? &&
      data.length > 0
  rescue ArgumentError
    # Expected rejection
  end
end

Real-World Examples

require 'ruzzy'

class FuzzRunner
  def initialize(
    target:,
    corpus:,
    duration: 600
  )
    @target = target
    @corpus = corpus
    @duration = duration
    @crashes = []
  end

  def run
    Ruzzy.fuzz(
      corpus_dir: @corpus,
      timeout: @duration,
      crash_dir:
        './crashes'
    ) do |data|
      begin
        @target.call(data)
      rescue StandardError
        nil
      end
    end
  end

  def report
    crashes = Dir.glob(
      './crashes/*')
    {
      total: crashes.length,
      files: crashes.map {
        |f| File.basename(f)
      }
    }
  end
end

runner = FuzzRunner.new(
  target: method(
    :parse_input),
  corpus: './seeds',
  duration: 300)
runner.run
puts runner.report
  .inspect

Advanced Tips

Seed the corpus directory with valid input samples to help the fuzzer reach deeper code paths faster. Add assertions inside fuzz harnesses to detect logic bugs in addition to memory safety issues. Run fuzzing campaigns for extended periods since some bugs require millions of iterations to discover.

When to Use It?

Use Cases

Fuzz test a Ruby gem's C extension parser to find buffer overflow vulnerabilities. Run coverage-guided fuzzing in CI to catch regressions in native code. Minimize a crashing input to create a reproducible test case for bug reporting.

Related Topics

Ruzzy, fuzz testing, Ruby, C extensions, security testing, coverage-guided fuzzing, and vulnerability discovery.

Important Notes

Requirements

Ruby environment with the Ruzzy gem installed for fuzz testing. C compiler toolchain for building instrumented C extensions. Seed corpus with representative input samples for effective fuzzing coverage.

Usage Recommendations

Do: rescue expected Ruby exceptions in fuzz harnesses to focus on unexpected crashes from C code. Start with small maximum input lengths and increase gradually to explore deeper code paths. Save and version control the corpus to build coverage over time.

Don't: ignore crashes that appear intermittent since they may indicate real memory corruption. Run fuzzing with production credentials or against live services. Assume that passing a short fuzz run means the code is bug-free since longer runs may discover additional issues.

Limitations

Fuzzing effectiveness depends on corpus quality and the diversity of seed inputs provided. Some code paths may require structured input that random mutation alone cannot produce efficiently. Memory safety bugs in C extensions may be environment-specific and not reproducible across all platforms.