mcpField
C
cargo-fuzz

cargo-fuzz

github.com/trailofbitsテスト・品質7.9k5.4k 回インストール今日更新
リポジトリ

cargo-fuzz について

cargo-fuzzは、Cargoを使うRustプロジェクト向けのlibFuzzerベースのファジング用CLIです。必要なビルドフラグを設定し、サニタイザー連携やカバレッジ確認も行えます。

主な機能

  1. 01libFuzzerによるファジング
  2. 02Cargoコマンドでのターゲット初期化
  3. 03AddressSanitizer連携
  4. 04arbitraryによる構造化入力
  5. 05カバレッジデータとレポートの生成

活用シーン

  1. 01Rustライブラリの任意入力処理のテスト
  2. 02パーサーなど入力処理コードのファジング
  3. 03クラッシュケースの再実行とカバレッジ確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/trailofbits/skills --skill cargo-fuzz

インストール後、Claude Code で/cargo-fuzzを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yamlassets/trail-of-bits-mark.svg

詳細

cargo-fuzz

cargo-fuzz は、Cargo を使用する Rust プロジェクトのファジングにおけるデファクトスタンダードです。バックエンドとして libFuzzer を使用し、AddressSanitizer などのサニタイザーのサポートを含め、Rust プロジェクトに関連するコンパイルフラグを自動的に有効にする便利な Cargo サブコマンドを提供します。

使用する場面

cargo-fuzz は現在、Cargo を使用する Rust プロジェクト向けの主要かつ最も成熟したファジングソリューションです。

ファザー最適な用途複雑さ
cargo-fuzzCargo ベースの Rust プロジェクト、すばやいセットアップ低
AFL++マルチコアファジング、Cargo 以外のプロジェクト中
LibAFLカスタムファザー、研究、高度なユースケース高

次のような場合は cargo-fuzz を選んでください:

  • プロジェクトで Cargo を使用している(必須)
  • 最小限の設定で簡単かつすばやくセットアップしたい
  • サニタイザーの統合サポートが必要
  • unsafe ブロックの有無を問わず、Rust コードをファジングする

クイックスタート

#![no_main]

use libfuzzer_sys::fuzz_target;

fn harness(data: &[u8]) {
    your_project::check_buf(data);
}

fuzz_target!(|data: &[u8]| {
    harness(data);
});

初期化して実行します:

cargo fuzz init
# Edit fuzz/fuzz_targets/fuzz_target_1.rs with your harness
cargo +nightly fuzz run fuzz_target_1

インストール

cargo-fuzz は nightly でのみ利用できる機能を使用するため、Rust の nightly ツールチェーンが必要です。

前提条件
  • rustup 経由でインストールした Rust と Cargo
  • nightly ツールチェーン
Linux/macOS
# Install nightly toolchain
rustup install nightly

# Install cargo-fuzz
cargo install cargo-fuzz
検証
cargo +nightly --version
cargo fuzz --version

ハーネスの作成

プロジェクト構成

cargo-fuzz は、コードがライブラリクレートとして構成されている場合に最も効果を発揮します。バイナリプロジェクトの場合は、main.rs を次のように分割します:

src/main.rs  # Entry point (main function)
src/lib.rs   # Code to fuzz (public functions)
Cargo.toml

ファジングを初期化します:

cargo fuzz init

次のものが作成されます:

fuzz/
├── Cargo.toml
└── fuzz_targets/
    └── fuzz_target_1.rs
ハーネスの構造
#![no_main]

use libfuzzer_sys::fuzz_target;

fn harness(data: &[u8]) {
    // 1. Validate input size if needed
    if data.is_empty() {
        return;
    }

    // 2. Call target function with fuzz data
    your_project::target_function(data);
}

fuzz_target!(|data: &[u8]| {
    harness(data);
});
ハーネスのルール
推奨事項避けること
コードをライブラリクレートとして構成するすべてを main.rs に置く
fuzz_target! マクロを使用するカスタムの main 関数を書く
Result::Err を適切に処理する想定されるエラーでパニックする
ハーネスの決定性を保つ乱数生成器を使用する

関連項目: ハーネス作成の手法と、arbitrary クレートを使った構造を考慮するファジングについて詳しくは、 fuzz-harness-writing 技術スキルを参照してください。

構造を考慮するファジング

cargo-fuzz は、構造を考慮するファジングのために arbitrary クレートと統合されています:

// In your library crate
use arbitrary::Arbitrary;

#[derive(Debug, Arbitrary)]
pub struct Name {
    data: String
}
// In your fuzz target
#![no_main]
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: your_project::Name| {
    data.check_buf();
});

ライブラリの Cargo.toml に追加します:

[dependencies]
arbitrary = { version = "1", features = ["derive"] }

ファジングキャンペーンの実行

基本的な実行
cargo +nightly fuzz run fuzz_target_1
サニタイザーを使用しない場合(安全な Rust)

プロジェクトで unsafe Rust を使用していない場合は、サニタイザーを無効にするとパフォーマンスが 2 倍になります:

cargo +nightly fuzz run --sanitizer none fuzz_target_1

プロジェクトで unsafe コードが使用されているか確認します:

cargo install cargo-geiger
cargo geiger
テストケースの再実行
# Run a specific test case (e.g., a crash)
cargo +nightly fuzz run fuzz_target_1 fuzz/artifacts/fuzz_target_1/crash-<hash>

# Run all corpus entries without fuzzing
cargo +nightly fuzz run fuzz_target_1 fuzz/corpus/fuzz_target_1 -- -runs=0
辞書の使用
cargo +nightly fuzz run fuzz_target_1 -- -dict=./dict.dict
出力の読み方
出力意味
NEWカバレッジを向上させる新しい入力を検出
pulse定期的なステータス更新
INITEDファザーの初期化に成功
スタックトレース付きのクラッシュバグを検出。fuzz/artifacts/ に保存

コーパスの場所:fuzz/corpus/fuzz_target_1/ クラッシュの場所:fuzz/artifacts/fuzz_target_1/

サニタイザーの統合

AddressSanitizer(ASan)

ASan はデフォルトで有効になっており、メモリエラーを検出します:

cargo +nightly fuzz run fuzz_target_1
サニタイザーの無効化

純粋な安全な Rust(コードまたは依存関係に unsafe ブロックがない場合)では:

cargo +nightly fuzz run --sanitizer none fuzz_target_1

パフォーマンスへの影響: ASan によりオーバーヘッドが約 2 倍になります。安全な Rust では、ファジング速度を向上させるために無効にしてください。

unsafe コードの確認
cargo install cargo-geiger
cargo geiger

関連項目: サニタイザーの設定、フラグ、トラブルシューティングについて詳しくは、 address-sanitizer 技術スキルを参照してください。

カバレッジ分析

cargo-fuzz は Rust のカバレッジツールと統合されており、ファジングの有効性を分析できます。

前提条件
rustup toolchain install nightly --component llvm-tools-preview
cargo install cargo-binutils
cargo install rustfilt
カバレッジレポートの生成
# Generate coverage data from corpus
cargo +nightly fuzz coverage fuzz_target_1

カバレッジ生成スクリプトを作成します:

cat <<'EOF' > ./generate_html
#!/bin/sh
if [ $# -lt 1 ]; then
    echo "Error: Name of fuzz target is required."
    echo "Usage: $0 fuzz_target [sources...]"
    exit 1
fi
FUZZ_TARGET="$1"
shift
SRC_FILTER="$@"
TARGET=$(rustc -vV | sed -n 's|host: ||p')
cargo +nightly cov -- show -Xdemangler=rustfilt \
  "target/$TARGET/coverage/$TARGET/release/$FUZZ_TARGET" \
  -instr-profile="fuzz/coverage/$FUZZ_TARGET/coverage.profdata"  \
  -show-line-counts-or-regions -show-instantiations  \
  -format=html -o fuzz_html/ $SRC_FILTER
EOF
chmod +x ./generate_html

HTML レポートを生成します:

./generate_html fuzz_target_1 src/lib.rs

HTML レポートの保存先:fuzz_html/

関連項目: カバレッジ分析の手法と体系的なカバレッジ改善について詳しくは、 coverage-analysis 技術スキルを参照してください。

高度な使い方

ヒントとコツ
ヒント役立つ理由
シードコーパスから始める初期のカバレッジ検出を大幅に高速化できます
安全な Rust では --sanitizer none を使うパフォーマンスが 2 倍向上します
カバレッジを定期的に確認するハーネスまたはシードコーパスの不足箇所を特定できます
パーサーには辞書を使うマジック値のチェックを乗り越えるのに役立ちます
コードをライブラリとして構成するcargo-fuzz との統合に必要です
libFuzzer のオプション

-- の後にオプションを libFuzzer に渡します。

# See all options
cargo +nightly fuzz run fuzz_target_1 -- -help=1

# Set timeout per run
cargo +nightly fuzz run fuzz_target_1 -- -timeout=10

# Use dictionary
cargo +nightly fuzz run fuzz_target_1 -- -dict=dict.dict

# Limit maximum input size
cargo +nightly fuzz run fuzz_target_1 -- -max_len=1024
マルチコアファジング
# Experimental forking support (not recommended)
cargo +nightly fuzz run --jobs 1 fuzz_target_1

注:マルチコアファジング機能は実験的であり、推奨されません。並列ファジングには、複数のインスタンスを手動で実行するか、AFL++ の使用を検討してください。

実例

例:ogg クレート

ogg クレート は、Ogg メディアコンテナーファイルを解析します。信頼できないデータを処理するパーサーは、ファジングの優れた対象です。

# Clone and initialize
git clone https://github.com/RustAudio/ogg.git
cd ogg/
cargo fuzz init

ハーネスは fuzz/fuzz_targets/fuzz_target_1.rs にあります。

#![no_main]

use ogg::{PacketReader, PacketWriter};
use ogg::writing::PacketWriteEndInfo;
use std::io::Cursor;
use libfuzzer_sys::fuzz_target;

fn harness(data: &[u8]) {
    let mut pck_rdr = PacketReader::new(Cursor::new(data.to_vec()));
    pck_rdr.delete_unread_packets();

    let output = Vec::new();
    let mut pck_wtr = PacketWriter::new(Cursor::new(output));

    if let Ok(_) = pck_rdr.read_packet() {
        if let Ok(r) = pck_rdr.read_packet() {
            match r {
                Some(pck) => {
                    let inf = if pck.last_in_stream() {
                        PacketWriteEndInfo::EndStream
                    } else if pck.last_in_page() {
                        PacketWriteEndInfo::EndPage
                    } else {
                        PacketWriteEndInfo::NormalPacket
                    };
                    let stream_serial = pck.stream_serial();
                    let absgp_page = pck.absgp_page();
                    let _ = pck_wtr.write_packet(
                        pck.data, stream_serial, inf, absgp_page
                    );
                }
                None => return,
            }
        }
    }
}

fuzz_target!(|data: &[u8]| {
    harness(data);
});

コーパスにシードを追加します。

mkdir fuzz/corpus/fuzz_target_1/
curl -o fuzz/corpus/fuzz_target_1/320x240.ogg \
  https://commons.wikimedia.org/wiki/File:320x240.ogg

実行します。

cargo +nightly fuzz run fuzz_target_1

カバレッジを分析します。

cargo +nightly fuzz coverage fuzz_target_1
./generate_html fuzz_target_1 src/lib.rs

トラブルシューティング

問題原因解決策
「requires nightly」エラーstable ツールチェーンを使用しているcargo +nightly fuzz を使います
ファジングのパフォーマンスが低い安全な Rust で ASan が有効になっている--sanitizer none フラグを追加します
「cannot find binary」ライブラリクレートがないコードを main.rs から lib.rs に移動します
サニタイザーのコンパイルに関する問題nightly のバージョンが不適切別の nightly を試します:rustup install nightly-2024-01-01
カバレッジが低いシードコーパスがないサンプル入力を fuzz/corpus/fuzz_target_1/ に追加します
マジック値が見つからない辞書がないマジック値を含む辞書ファイルを作成します

関連スキル

技法スキル
スキル用途
fuzz-harness-writingarbitrary クレートを使った構造を考慮したファジング
address-sanitizerASan の出力と設定を理解する
coverage-analysisファジングの有効性を測定し、改善する
fuzzing-corpusシードコーパスの構築と管理
fuzzing-dictionariesフォーマットを考慮したファジング用の辞書を作成する
関連ファザー
スキル検討する場面
libfuzzer同様のワークフローで C/C++ コードをファジングする
aflppマルチコアファジング、または Cargo を使わない Rust プロジェクト
libafl高度なファジング研究、またはカスタムファザーの開発

リソース

Rust Fuzz Book - cargo-fuzz cargo-fuzz のインストール、使用方法、高度な機能を網羅した公式ドキュメントです。

arbitrary クレートのドキュメント Rust の型を自動導出して、構造を考慮したファジングを行うためのガイドです。

cargo-fuzz GitHub リポジトリ cargo-fuzz のソースコード、課題トラッカー、サンプルを確認できます。

コメント