libfuzzer について
libFuzzer スキルは、ClangでC/C++プロジェクトをテストする開発者向けに、LLVMのプロセス内カバレッジガイド型ファザーを解説します。ハーネス、ビルド、コーパス管理、実行、カバレッジ分析を扱います。
主な機能
- 01LLVMFuzzerTestOneInputハーネスの作成
- 02Clangとサニタイザーによるビルド
- 03コーパスの作成と最小化
- 04辞書、入力長、タイムアウトの設定
- 05マルチコア実行とカバレッジ分析
活用シーン
- 01C/C++パーサーのファジング
- 02AddressSanitizerによるメモリエラー検査
- 03クラッシュの再現とテストコーパスの縮小
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trailofbits/ skills --skill libfuzzerインストール後、Claude Code で/libfuzzerを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlassets/trail-of-bits-mark.svg
詳細
libFuzzer
libFuzzer は LLVM プロジェクトの一部である、プロセス内で動作するカバレッジガイド型ファザーです。シンプルで LLVM ツールチェーンとの統合性に優れているため、C/C++ プロジェクトのファジングを始める際に推奨されます。libFuzzer は 2022 年後半以降、メンテナンスのみのモードになっていますが、代替ツールよりもインストールや使用が簡単で、幅広くサポートされており、今後も当面はメンテナンスが続けられる見込みです。
使用する場面
| ファザー | 最適な用途 | 複雑さ |
|---|---|---|
| libFuzzer | 素早いセットアップ、単一プロジェクトのファジング | 低 |
| AFL++ | マルチコアファジング、多様なミューテーション | 中 |
| LibAFL | カスタムファザー、研究プロジェクト | 高 |
| Honggfuzz | ハードウェアベースのカバレッジ | 中 |
libFuzzer を選ぶ場合:
- C/C++ コードをシンプルかつ素早くセットアップする必要がある
- プロジェクトのコンパイルに Clang を使用している
- まずはシングルコアのファジングで十分である
- 後で AFL++ に移行する選択肢がある(ハーネスに互換性があります)
注: libFuzzer 用に記述したファジングハーネスは AFL++ と互換性があるため、より優れたマルチコアサポートなどの高度な機能が必要になった場合も簡単に移行できます。
クイックスタート
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Validate input if needed
if (size < 1) return 0;
// Call your target function with fuzzer-provided data
my_target_function(data, size);
return 0;
}
コンパイルして実行します:
clang++ -fsanitize=fuzzer,address -g -O2 harness.cc target.cc -o fuzz
mkdir corpus/
./fuzz corpus/
インストール
前提条件
- LLVM/Clang コンパイラー(libFuzzer を含む)
- カバレッジ分析用の LLVM ツール(任意)
Linux(Ubuntu/Debian)
apt install clang llvm
最新の LLVM バージョンを使用する場合:
# Add LLVM repository from apt.llvm.org
# Then install specific version, e.g.:
apt install clang-18 llvm-18
macOS
# Using Homebrew
brew install llvm
# Or using Nix
nix-env -i clang
Windows
Visual Studio を通じて Clang をインストールします。セットアップ手順については、Microsoft のドキュメントを参照してください。
推奨: 可能であれば、ローカルの x86_64 VM でファジングを行うか、DigitalOcean、AWS、または Hetzner で VM を借りてください。Linux は libFuzzer のサポートが最も優れています。
確認
clang++ --version
# Should show LLVM version information
ハーネスの作成
ハーネスの構造
ハーネスはファザーのエントリーポイントです。libFuzzer は、異なる入力を使って LLVMFuzzerTestOneInput 関数を繰り返し呼び出します。
#include <stdint.h>
#include <stddef.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 1. Optional: Validate input size
if (size < MIN_REQUIRED_SIZE) {
return 0; // Reject inputs that are too small
}
// 2. Optional: Convert raw bytes to structured data
// Example: Parse two integers from byte array
if (size >= 2 * sizeof(uint32_t)) {
uint32_t a = *(uint32_t*)(data);
uint32_t b = *(uint32_t*)(data + sizeof(uint32_t));
my_function(a, b);
}
// 3. Call target function
target_function(data, size);
// 4. Always return 0 (non-zero reserved for future use)
return 0;
}
ハーネスのルール
| 実施すること | 避けること |
|---|---|
| あらゆる種類の入力(空、大きい、不正な形式)を処理する | exit() を呼び出す(ファジングプロセスが停止します) |
| 戻る前にすべてのスレッドを結合する | スレッドを実行したままにする |
| ハーネスを高速かつシンプルに保つ | 過剰なログ出力や複雑さを加える |
| 決定性を保つ | 乱数生成器を使う、または /dev/random を読み取る |
| 実行のたびにグローバル状態をリセットする | 以前の実行の状態に依存する |
| 対象を絞り、焦点を明確にする | 無関係なデータ形式(PNG + TCP)を 1 つのハーネスに混在させる |
理由:
- 速度が重要です: コアごとに毎秒 100~1000 回の実行を目指します
- 再現性: ファジングの完了後もクラッシュを再現できる必要があります
- 分離: 各実行は独立している必要があります
複雑な入力に FuzzedDataProvider を使用する
複雑な入力(文字列、複数のパラメーター)には、FuzzedDataProvider ヘルパーを使用します:
#include <stdint.h>
#include <stddef.h>
#include "FuzzedDataProvider.h" // From LLVM project
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
// Extract structured data
size_t allocation_size = fuzzed_data.ConsumeIntegral<size_t>();
std::vector<char> str1 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
std::vector<char> str2 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
// Call target with extracted data
char* result = concat(&str1[0], str1.size(), &str2[0], str2.size(), allocation_size);
if (result != NULL) {
free(result);
}
return 0;
}
LLVM リポジトリから FuzzedDataProvider.h をダウンロードしてください。
インターリーブファジング
関連する複数の関数をテストするには、単一のハーネスを使用します:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < 1 + 2 * sizeof(int32_t)) {
return 0;
}
uint8_t mode = data[0];
int32_t numbers[2];
memcpy(numbers, data + 1, 2 * sizeof(int32_t));
// Select function based on first byte
switch (mode % 4) {
case 0: add(numbers[0], numbers[1]); break;
case 1: subtract(numbers[0], numbers[1]); break;
case 2: multiply(numbers[0], numbers[1]); break;
case 3: divide(numbers[0], numbers[1]); break;
}
return 0;
}
関連項目: 詳細なハーネス作成手法、複雑な入力を処理するパターン、構造認識型ファジング、protobuf ベースのファジングについては、fuzz-harness-writing 技術スキルを参照してください。
コンパイル
基本的なコンパイル
重要なフラグは -fsanitize=fuzzer です。このフラグは次の処理を行います:
- libFuzzer ランタイムをリンクする(
main関数を提供) - カバレッジ追跡のために SanitizerCoverage インストルメンテーションを有効にする
memcmpなどの組み込み関数を無効にする
clang++ -fsanitize=fuzzer -g -O2 harness.cc target.cc -o fuzz
フラグの説明:
-fsanitize=fuzzer:libFuzzer を有効にする-g:デバッグシンボルを追加する(クラッシュ分析に役立ちます)-O2:本番環境レベルの最適化を行う(ファジングに推奨)-DNO_MAIN:コードにmain関数がある場合にマクロを定義する
サニタイザーを使用する場合
AddressSanitizer(推奨):
clang++ -fsanitize=fuzzer,address -g -O2 -U_FORTIFY_SOURCE harness.cc target.cc -o fuzz
複数のサニタイザー:
clang++ -fsanitize=fuzzer,address,undefined -g -O2 harness.cc target.cc -o fuzz
関連項目: サニタイザーの詳細な設定、一般的な問題、ASAN_OPTIONS フラグ、 高度なサニタイザーの使用方法については、address-sanitizer および undefined-behavior-sanitizer 技術スキルを参照してください。
ビルドフラグ
| フラグ | 目的 |
|---|---|
-fsanitize=fuzzer | libFuzzer のランタイムとインストルメンテーションを有効にします |
-fsanitize=address | AddressSanitizer(メモリエラー検出)を有効にします |
-fsanitize=undefined | UndefinedBehaviorSanitizer を有効にします |
-fsanitize=fuzzer-no-link | ファザーをリンクせずにインストルメントします(ライブラリ向け) |
-g | デバッグシンボルを含めます |
-O2 | 本番環境向けの最適化レベルです |
-U_FORTIFY_SOURCE | Fortify を無効にします(ASan と干渉する場合があります) |
静的ライブラリのビルド
静的ライブラリを生成するプロジェクトの場合:
- ファジングのインストルメンテーションを有効にしてライブラリをビルドします:
export CC=clang CFLAGS="-fsanitize=fuzzer-no-link -fsanitize=address"
export CXX=clang++ CXXFLAGS="$CFLAGS"
./configure --enable-shared=no
make
- 静的ライブラリをハーネスにリンクします:
clang++ -fsanitize=fuzzer -fsanitize=address harness.cc libmylib.a -o fuzz
CMake との統合
project(FuzzTarget)
cmake_minimum_required(VERSION 3.0)
add_executable(fuzz main.cc harness.cc)
target_compile_definitions(fuzz PRIVATE NO_MAIN=1)
target_compile_options(fuzz PRIVATE -g -O2 -fsanitize=fuzzer -fsanitize=address)
target_link_libraries(fuzz -fsanitize=fuzzer -fsanitize=address)
次のコマンドでビルドします:
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ .
cmake --build .
コーパスの管理
初期コーパスの作成
コーパス用のディレクトリを作成します(空の状態から始めてもかまいません):
mkdir corpus/
任意ですが、推奨されます: シード入力(有効なサンプルファイル)を用意します:
# For a PNG parser:
cp examples/*.png corpus/
# For a protocol parser:
cp test_packets/*.bin corpus/
シード入力の利点:
- ファザーがゼロから開始せずに済みます
- 有効なコードパスにより早く到達できます
- 有効性が大幅に向上します
コーパスの構造
コーパスディレクトリには、次のものが含まれます:
- 固有のコードパスを実行する入力ファイル
- 最小化されたバージョン(libFuzzer が自動的に最小化します)
- 内容のハッシュ値を名前として付けたファイル(例:
a9993e364706816aba3e25717850c26c9cd0d89d)
コーパスの最小化
libFuzzer はファジング中にコーパスのエントリを自動的に最小化します。明示的に最小化するには:
mkdir minimized_corpus/
./fuzz -merge=1 minimized_corpus/ corpus/
これにより、重複が除去され、最小化されたコーパスが minimized_corpus/ に作成されます。
関連項目: コーパスの作成方法、シードの選定、フォーマットごとのコーパス構築、 コーパスのメンテナンスについては、fuzzing-corpus 技術スキルを参照してください。
ファジングキャンペーンの実行
基本的な実行
./fuzz corpus/
クラッシュが見つかるか、停止する(Ctrl+C)まで実行されます。
推奨:クラッシュ後も続行する
./fuzz -fork=1 -ignore_crashes=1 corpus/
-fork および -ignore_crashes フラグ(実験的ですが広く使用されています)を使うと、クラッシュの検出後もファジングを続行できます。
よく使うオプション
入力サイズを制御する:
./fuzz -max_len=4000 corpus/
目安:現実的な最小入力の 2 倍のサイズです。
タイムアウトを設定する:
./fuzz -timeout=2 corpus/
2 秒を超えて実行されるテストケースを中止します。
辞書を使用する:
./fuzz -dict=./format.dict corpus/
stdout/stderr を閉じる(ファジングを高速化):
./fuzz -close_fd_mask=3 corpus/
すべてのオプションを表示する:
./fuzz -help=1
マルチコアファジング
方法 1:ジョブとワーカー(推奨):
./fuzz -jobs=4 -workers=4 -fork=1 -ignore_crashes=1 corpus/
-jobs=4:4 つのキャンペーンを順番に実行します-workers=4:4 つのプロセスでジョブを並列処理します- テストケースはジョブ間で共有されます
方法 2:Fork モード:
./fuzz -fork=4 -ignore_crashes=1 corpus/
注: 本格的なマルチコアファジングには、AFL++、Honggfuzz、または LibAFL への切り替えを検討してください。
テストケースの再実行
単一のクラッシュを再実行する:
./fuzz ./crash-a9993e364706816aba3e25717850c26c9cd0d89d
ファジングを行わずに、ディレクトリ内のすべての入力をテストする:
./fuzz -runs=0 corpus/
出力の読み方
ファジングの実行中には、次のような統計情報が表示されます:
INFO: Seed: 3517090860
INFO: Loaded 1 modules (9 inline 8-bit counters)
#2 INITED cov: 3 ft: 4 corp: 1/1b exec/s: 0 rss: 26Mb
#57 NEW cov: 4 ft: 5 corp: 2/4b lim: 4 exec/s: 0 rss: 26Mb
| 出力 | 意味 |
|---|---|
INITED | ファジングが初期化されました |
NEW | 新しいカバレッジが見つかり、コーパスに追加されました |
REDUCE | カバレッジを維持したまま入力が最小化されました |
cov: N | ヒットしたカバレッジエッジの数 |
corp: X/Yb | コーパスのサイズ:X 件、合計 Y バイト |
exec/s: N | 1 秒あたりの実行回数 |
rss: NMb | 常駐メモリの使用量 |
クラッシュ時:
==11672== ERROR: libFuzzer: deadly signal
artifact_prefix='./'; Test unit written to ./crash-a9993e364706816aba3e25717850c26c9cd0d89d
0x61,0x62,0x63,
abc
Base64: YWJj
クラッシュは ./crash-<hash> に保存され、入力は 16 進数、UTF-8、Base64 で表示されます。
再現性: -seed=<value> を使用すると、ファジングキャンペーンを再現できます(シングルコアのみ)。
ファジング辞書
辞書を使うと、入力形式に関するヒントを与えることで、ファザーが興味深い入力をより速く発見できるようになります。
辞書の形式
引用符で囲まれた文字列(1 行に 1 つ)を記述したテキストファイルを作成します:
# Lines starting with '#' are comments
# Magic bytes
magic="\x89PNG"
magic2="IEND"
# Keywords
"GET"
"POST"
"Content-Type"
# Hex sequences
delimiter="\xFF\xD8\xFF"
辞書の使用
./fuzz -dict=./format.dict corpus/
辞書の生成
ヘッダーファイルから:
grep -o '".*"' header.h > header.dict
man ページから:
man curl | grep -oP '^\s*(--|-)\K\S+' | sed 's/[,.]$//' | sed 's/^/"&/; s/$/&"/' | sort -u > man.dict
バイナリ文字列から:
strings ./binary | sed 's/^/"&/; s/$/&"/' > strings.dict
LLM の使用: ChatGPT などに、使用するフォーマット用の辞書の生成を依頼します(例:「JSON パーサー用の libFuzzer 辞書を生成してください」)。
関連項目: 高度な辞書生成、フォーマット固有の辞書、辞書の最適化戦略については、 fuzzing-dictionaries 技術スキルを参照してください。
カバレッジ分析
libFuzzer では基本的なカバレッジ統計(cov: N)が表示されますが、詳細なカバレッジ分析には追加のツールが必要です。
ソースベースのカバレッジ
1. カバレッジ計測を有効にして再コンパイルします:
clang++ -fsanitize=fuzzer -fprofile-instr-generate -fcoverage-mapping harness.cc target.cc -o fuzz
2. ファザーを実行してカバレッジを収集します:
LLVM_PROFILE_FILE="coverage-%p.profraw" ./fuzz -runs=10000 corpus/
3. カバレッジデータをマージします:
llvm-profdata merge -sparse coverage-*.profraw -o coverage.profdata
4. カバレッジレポートを生成します:
llvm-cov show ./fuzz -instr-profile=coverage.profdata
5. HTML レポートを生成します:
llvm-cov show ./fuzz -instr-profile=coverage.profdata -format=html > coverage.html
カバレッジの改善
ヒント:
- コーパスにより適切なシード入力を用意します
- フォーマットを考慮したファジングには辞書を使用します
- ハーネスが対象を適切に実行しているか確認します
- 複雑なフォーマットには構造を考慮したファジングを検討します
- より長い期間(数日/数週間)ファジングを実行します
関連項目: 詳細なカバレッジ分析手法、カバレッジの不足箇所の特定、 体系的なカバレッジ改善、ファザー間でのカバレッジ比較については、 coverage-analysis 技術スキルを参照してください。
サニタイザーとの統合
AddressSanitizer(ASan)
ASan は、バッファーオーバーフローや解放後使用バグなどのメモリエラーを検出します。ファジングでは強く推奨されます。
ASan を有効にする:
clang++ -fsanitize=fuzzer,address -g -O2 -U_FORTIFY_SOURCE harness.cc target.cc -o fuzz
ASan の出力例:
==1276163==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000c4ab1
WRITE of size 1 at 0x6020000c4ab1 thread T0
#0 0x55555568631a in check_buf(char*, unsigned long) main.cc:13:25
#1 0x5555556860bf in LLVMFuzzerTestOneInput harness.cc:7:3
環境変数を使用して ASan を設定する:
ASAN_OPTIONS=verbosity=1:abort_on_error=1 ./fuzz corpus/
重要なフラグ:
verbosity=1:ASan が有効であることを表示しますdetect_leaks=0:リーク検出を無効にします(リークは終了時に報告されます)abort_on_error=1:エラー発生時に_exit()ではなくabort()を呼び出します
欠点:
- 速度が 2~4 倍遅くなります
- 約 20TB の仮想メモリが必要です(メモリ制限を無効にします:
-rss_limit_mb=0) - Linux で最もよくサポートされています
関連項目: ASan の包括的な設定、よくある落とし穴、シンボル化、 他のサニタイザーとの併用については、address-sanitizer 技術スキルを参照してください。
UndefinedBehaviorSanitizer(UBSan)
UBSan は、整数オーバーフローやヌルポインターの参照解除などの未定義動作を検出します。
UBSan を有効にする:
clang++ -fsanitize=fuzzer,undefined -g -O2 harness.cc target.cc -o fuzz
ASan と併用する:
clang++ -fsanitize=fuzzer,address,undefined -g -O2 harness.cc target.cc -o fuzz
MemorySanitizer(MSan)
MSan は初期化されていないメモリの読み取りを検出します。使用するには、すべての依存関係を再ビルドする必要があるため、より複雑です。
clang++ -fsanitize=fuzzer,memory -g -O2 harness.cc target.cc -o fuzz
よくあるサニタイザーの問題
| 問題 | 解決策 |
|---|---|
| ASan によってファジングが遅くなりすぎる | 致命的ではないエラーには -fsanitize-recover=address を使用します |
| メモリ不足 | ASAN_OPTIONS=rss_limit_mb=0 または -rss_limit_mb=0 を設定します |
| スタックの枯渇 | スタックサイズを増やします:ASAN_OPTIONS=stack_size=8388608 |
_FORTIFY_SOURCE による誤検知 | -U_FORTIFY_SOURCE フラグを使用します |
| MSan が依存関係で問題を報告する | すべての依存関係を -fsanitize=memory を付けて再ビルドします |
実際の例
例 1:libpng のファジング
libpng は、PNG 画像の読み書きに広く使われているライブラリです。バグはセキュリティ上の問題につながる可能性があります。
1. ソースコードを取得します:
curl -L -O https://downloads.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
tar xf libpng-1.6.37.tar.xz
cd libpng-1.6.37/
2. 依存関係をインストールします:
apt install zlib1g-dev
3. ファジング計測を有効にしてコンパイルします:
export CC=clang CFLAGS="-fsanitize=fuzzer-no-link -fsanitize=address"
export CXX=clang++ CXXFLAGS="$CFLAGS"
./configure --enable-shared=no
make
4. ハーネスを取得します(または独自に作成します):
curl -O https://raw.githubusercontent.com/glennrp/libpng/f8e5fa92b0e37ab597616f554bee254157998227/contrib/oss-fuzz/libpng_read_fuzzer.cc
5. コーパスと辞書を準備します:
mkdir corpus/
curl -o corpus/input.png https://raw.githubusercontent.com/glennrp/libpng/acfd50ae0ba3198ad734e5d4dec2b05341e50924/contrib/pngsuite/iftp1n3p08.png
curl -O https://raw.githubusercontent.com/glennrp/libpng/2fff013a6935967960a5ae626fc21432807933dd/contrib/oss-fuzz/png.dict
6. ファザーをリンクしてコンパイルします:
clang++ -fsanitize=fuzzer -fsanitize=address libpng_read_fuzzer.cc .libs/libpng16.a -lz -o fuzz
7. ファジングを実行します:
./fuzz -close_fd_mask=3 -dict=./png.dict corpus/
例 2:単純な除算バグ
ゼロ除算バグを見つけるハーネス:
#include <stdint.h>
#include <stddef.h>
double divide(uint32_t numerator, uint32_t denominator) {
// Bug: No check if denominator is zero
return numerator / denominator;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if(size != 2 * sizeof(uint32_t)) {
return 0;
}
uint32_t numerator = *(uint32_t*)(data);
uint32_t denominator = *(uint32_t*)(data + sizeof(uint32_t));
divide(numerator, denominator);
return 0;
}
コンパイルしてファジングします:
clang++ -fsanitize=fuzzer harness.cc -o fuzz
./fuzz
ファザーはクラッシュを引き起こす入力をすぐに見つけます。
高度な使用方法
ヒントとコツ
| ヒント | メリット |
|---|---|
| まずシングルコアで始め、マルチコアでは AFL++ に切り替える | libFuzzer のハーネスは AFL++ でも動作します |
| 構造化された形式には辞書を使用する | バグの発見速度が 10~100 倍になります |
-close_fd_mask=3 でファイル記述子を閉じる | SUT が出力を書き込む場合、速度が向上します |
適切な -max_len を設定する | 巨大な入力に時間を浪費するのを防ぎます |
| 数分ではなく、数日から数週間実行する | カバレッジの停滞を打破するには時間がかかります |
| テストスイートのシードコーパスを使用する | 有効な入力からファジングを開始できます |
構造を考慮したファジング
複雑なプロトコルやファイル形式など、高度に構造化された入力には libprotobuf-mutator を使用します。
- Protocol Buffers を使用して入力構造を定義します
- libFuzzer が protobuf メッセージを変異させます(構造を保持した変異)
- ハーネスが protobuf をネイティブ形式に変換します
詳しくは、構造を考慮したファジングのドキュメントを参照してください。
カスタムミューテーター
libFuzzer では、特殊なファジング用にカスタムミューテーターを使用できます。
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
size_t MaxSize, unsigned int Seed) {
// Custom mutation logic
return new_size;
}
extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
const uint8_t *Data2, size_t Size2,
uint8_t *Out, size_t MaxOutSize,
unsigned int Seed) {
// Custom crossover logic
return new_size;
}
パフォーマンスの調整
| 設定 | 影響 |
|---|---|
-close_fd_mask=3 | stdout/stderr を閉じ、ファジングを高速化します |
-max_len=<reasonable_size> | 巨大な入力に時間を浪費するのを防ぎます |
-timeout=<seconds> | ハングを検出し、実行が停止するのを防ぎます |
| ベースライン測定では ASan を無効にする | 速度が 2~4 倍向上します(ただし、メモリエラーを見逃します) |
-jobs と -workers を使用する | マルチコアのサポートは限定的です |
| Linux で実行する | サポートとパフォーマンスが最も優れています |
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
| 数時間実行してもクラッシュが見つからない | コーパスの質が低い、カバレッジが低い | シード入力を追加し、辞書を使用して、ハーネスを確認します |
| 実行数/秒が非常に少ない(<100) | ターゲットが複雑すぎる、ログが過剰 | ターゲットを最適化し、-close_fd_mask=3 を使用して、ログを減らします |
| メモリ不足 | ASan の 20TB の仮想メモリ | -rss_limit_mb=0 を設定して RSS 制限を無効にします |
| 最初のクラッシュ後にファザーが停止する | デフォルトの動作 | -fork=1 -ignore_crashes=1 を使用して続行します |
| クラッシュを再現できない | ハーネス/ターゲットの非決定性 | 乱数の生成とグローバル状態を取り除きます |
-fsanitize=fuzzer でリンクエラーが発生する | libFuzzer ランタイムがない | Clang を使用していることを確認し、LLVM のインストールを確認します |
| GCC のプロジェクトを Clang でコンパイルできない | GCC 固有のコード | 代わりに gcc_plugin を使用する AFL++ に切り替えます |
| カバレッジが向上しない | コーパスの停滞 | より長く実行し、辞書を追加し、シードを改善して、カバレッジレポートを確認します |
| クラッシュするが ASan が反応しない | ASan なしではメモリエラーを検出できない | -fsanitize=address を指定して再コンパイルします |
関連スキル
技法スキル
| スキル | 用途 |
|---|---|
| fuzz-harness-writing | 効果的なハーネスの作成、構造を考慮したファジング、FuzzedDataProvider の使用に関する詳しいガイダンス |
| address-sanitizer | メモリエラー検出の設定、ASAN_OPTIONS、トラブルシューティング |
| undefined-behavior-sanitizer | ファジング中の未定義動作の検出 |
| coverage-analysis | ファジングの有効性を測定し、未テストのコードパスを特定する |
| fuzzing-corpus | シードコーパスの構築と管理、コーパスの最小化戦略 |
| fuzzing-dictionaries | バグをより速く発見するための、形式固有の辞書の作成 |
関連するファザー
| スキル | 検討するタイミング |
|---|---|
| aflpp | 本格的なマルチコアファジングが必要な場合、または libFuzzer のカバレッジが停滞した場合 |
| honggfuzz | Linux でハードウェアベースのカバレッジフィードバックを利用したい場合 |
| libafl | カスタムファザーを構築する場合、またはファジングの研究を行う場合 |
リソース
公式ドキュメント
- LLVM libFuzzer ドキュメント - 公式リファレンス
- Google による libFuzzer チュートリアル - ステップごとのガイド
- SanitizerCoverage - カバレッジ計測の詳細
高度なトピック
サンプルプロジェクト
- OSS-Fuzz - オープンソースプロジェクト向けの継続的なファジング(libFuzzer のサンプルが多数あります)
- AFL++ ディクショナリコレクション - 再利用可能なディクショナリ