Crash Triage
Relevant source files
The following files were used as context for generating this wiki page: - [src/afl-fuzz-bitmap.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c) - [src/afl-tmin.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-tmin.c) - [src/afl-fuzz-init.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-init.c) - [afl-cmin.bash](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/afl-cmin.bash) - [utils/mutation_chain/mutation_chain.py](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/utils/mutation_chain/mutation_chain.py) - [custom_mutators/libfuzzer/FuzzerDriver.cpp](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/custom_mutators/libfuzzer/FuzzerDriver.cpp) - [src/afl-analyze.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-analyze.c) - [src/afl-fuzz.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz.c)Crash triage in AFL++ is the systematic process of identifying, classifying, saving, and analyzing inputs that cause a target program to crash or hang. This process is crucial for making fuzzing results actionable. It involves not only the core fuzzer's ability to detect and save unique crashes but also a suite of external tools designed to minimize and analyze these findings. The primary goal is to provide developers with the smallest, most understandable test cases to reproduce and debug the discovered vulnerabilities.
The main fuzzer, afl-fuzz, automatically saves crashing inputs to the crashes/ directory and hanging inputs to the hangs/ directory within the specified output folder. After a fuzzing session, developers can use tools like afl-tmin and afl-cmin to further refine these results.
Crash and Hang Detection
The core of crash detection resides within the afl-fuzz main loop. The function save_if_interesting is responsible for evaluating the outcome of each execution and deciding whether to save the input.
Sources: src/afl-fuzz-bitmap.c:836-1309, src/afl-fuzz.c
Execution Outcome Classification
After an input is executed in the target, afl-fuzz receives a fault status. The primary statuses relevant to triage are:
FSRV_RUN_OK: The program executed normally.FSRV_RUN_TMOUT: The program exceeded the execution timeout.FSRV_RUN_CRASH: The program terminated due to a signal (e.g., SIGSEGV, SIGABRT).
The save_if_interesting function uses this fault status to determine the subsequent course of action. If the execution is normal (FSRV_RUN_OK), it checks for new code coverage. If a crash or timeout occurs, it proceeds to the uniqueness check and saving process.
Sources: src/afl-fuzz-bitmap.c:836-840, src/afl-fuzz-bitmap.c:1082-1084, src/afl-fuzz-bitmap.c:1168-1170
Saving Process
The following diagram illustrates the high-level logic of the save_if_interesting function when handling potential crashes and new coverage.
This diagram shows the decision flow for saving interesting inputs, including new coverage, crashes, and hangs.
Sources: src/afl-fuzz-bitmap.c:836-1309
Crash Uniqueness and Classification
To avoid saving thousands of redundant crash files, AFL++ employs a uniqueness check. A crash or hang is considered "unique" if it triggers an execution path not seen in previous crashes or hangs of the same type.
Sources: src/afl-fuzz-bitmap.c:1089-1097, src/afl-fuzz-bitmap.c:1176-1184
Uniqueness Check Workflow
- Simplify Trace: For a crash or hang, the execution trace (bitmap) is first simplified. The
simplify_tracefunction is called, which converts the hit counts for each edge into a binary state (hit or not hit), effectively ignoring how many times an edge was traversed. - Check Against Virgin Map: The simplified trace is then compared against a dedicated "virgin" bitmap for that fault type (
virgin_crashfor crashes,virgin_tmoutfor hangs). has_new_bits: Thehas_new_bitsfunction performs this comparison. If the input's trace contains any bit (edge) not present in the virgin map, it is considered unique.- Update Virgin Map: If the crash is unique, the new bits from its trace are added to the corresponding virgin map, so subsequent crashes with the same path will not be considered unique.
This process is illustrated below:
This diagram outlines how AFL++ determines if a crash or hang is unique before saving.
Sources: src/afl-fuzz-bitmap.c:45-51, src/afl-fuzz-bitmap.c:1093-1095, src/afl-fuzz-bitmap.c:1178-1180
Crash File Naming Convention
Saved crash and hang files are given descriptive names that encode information about their origin and the circumstances of their discovery. This is handled by the describe_op function.
Sources: src/afl-fuzz-bitmap.c:482-581
A typical crash filename looks like this: id:000000,sig:06,src:000005,op:havoc,rep:8. The components are detailed in the table below.
| Component | Description | Source |
|---|---|---|
id | A sequential identifier for the saved crash or hang. | src/afl-fuzz-bitmap.c:1232 |
sig | The signal number that caused the crash (e.g., 06 for SIGABRT, 11 for SIGSEGV). | src/afl-fuzz-bitmap.c:1233 |
src | The ID of the parent queue item that was mutated to produce this crash. If it was a splice, it will be in the format src:xxxxxx+yyyyyy. If it was synced from another fuzzer, it will be sync:fuzzer_name,src:xxxxxx. | src/afl-fuzz-bitmap.c:510-520 |
time | The wall-clock time in milliseconds since the fuzzer started when this crash was found. | src/afl-fuzz-bitmap.c:522-524 |
execs | The total number of executions performed by the fuzzer when this crash was found. | src/afl-fuzz-bitmap.c:522-524 |
op | The mutation operator that was being applied. Examples: havoc, splice, flip1. | src/afl-fuzz-bitmap.c:556-557 |
pos | The byte offset within the input file where the mutation was applied. | src/afl-fuzz-bitmap.c:559-561 |
val | The value used in an arithmetic or interesting value mutation. | src/afl-fuzz-bitmap.c:563-567 |
rep | The repetition count for stacked mutations like havoc. | src/afl-fuzz-bitmap.c:571-572 |
+cov | Indicates that this input also discovered new edge coverage. | src/afl-fuzz-bitmap.c:577 |
+tout | Indicates the input originally timed out but was saved for other reasons (e.g., it crashed on a re-run with a longer timeout). | src/afl-fuzz-bitmap.c:575 |
+san | Indicates the crash was found by a sanitizer build and did not increase coverage. | src/afl-fuzz-bitmap.c:579 |
The environment variable AFL_SHA1_FILENAMES can be set to use the SHA1 hash of the file content as the filename instead.
Sources: src/afl-fuzz-bitmap.c:1229-1243
Post-Fuzzing Analysis Tools
AFL++ includes several command-line utilities to help analyze and minimize crash data after a fuzzing session.
afl-tmin: Test Case Minimization
afl-tmin is a tool that takes a single crashing input file and attempts to reduce its size as much as possible while still causing the same crash or producing the same instrumentation output.
Sources: src/afl-tmin.c
The minimization process in afl-tmin occurs in several stages:
- Block Normalization: Attempts to replace blocks of data with a neutral character (e.g., '0') to see if the content matters.
- Block Deletion: Iteratively removes blocks of decreasing size from the input file.
- Alphabet Minimization: Tries to replace unique bytes with a common byte ('0') to reduce the set of characters needed to trigger the bug.
- Character Minimization: A final pass that attempts to replace individual non-essential bytes with '0'.
This diagram shows the multi-stage minimization process of afl-tmin.
Sources: src/afl-tmin.c:502-748
afl-cmin: Corpus Minimization
afl-cmin.bash is a script used to find the smallest subset of files from a larger corpus (e.g., the queue/ directory) that collectively trigger all unique execution paths observed in the original set. It is useful for creating a minimal seed corpus for a new fuzzing session or for reducing a large queue for easier analysis.
Sources: afl-cmin.bash
The script operates as follows:
- Collect Traces: It runs
afl-showmapon every file in the input directory to generate a trace file containing the hit tuples. - Sort Tuples: It aggregates all tuples from all traces and sorts them by frequency to identify unique tuples.
- Find Best Candidates: For each unique tuple, it identifies the smallest input file that triggers it.
- Write Output: It copies the selected minimal set of files to the output directory.
Sources: afl-cmin.bash:204-325
mutation_chain.py: Mutation History Analysis
This Python script helps in understanding the lineage of a crash. By parsing the src: and sync: fields in filenames, it can recursively trace a crash file back to its original seed in the queue, showing the complete mutation history. This is invaluable for debugging how a simple input evolved into a complex crashing one.
Sources: utils/mutation_chain/mutation_chain.py
LibFuzzer-style Crash Minimization
The LibFuzzer custom mutator compatibility layer includes its own crash minimization and cleansing logic, which can be invoked with command-line flags.
-minimize_crash=1: This flag initiates a crash minimization loop. It repeatedly runs the fuzzer on a crashing input, attempting to find a smaller version that produces the same crash signature (dedup token).-cleanse_crash=1: This attempts to replace bytes in a crashing input with "clean" values (space or0xFF) to simplify the input without losing the crash.
Sources: custom_mutators/libfuzzer/FuzzerDriver.cpp:388-508, custom_mutators/libfuzzer/FuzzerDriver.cpp:341-386
Informational Files
To aid developers, AFL++ automatically generates a README.txt file in the crashes/ directory upon finding the first unique crash.
Sources: src/afl-fuzz-bitmap.c:586-634
This file contains:
- The exact command line used to start the fuzzing session.
- The memory limit (
-m) that was set. - A strong recommendation to use
afl-tminto minimize the test case before analysis.
Example content of crashes/README.txt:
Command line used to find this crash:
./afl-fuzz -i in -o out -- ./test_program
If you can't reproduce a bug outside of afl-fuzz, be sure to set the same
memory limit. The limit used for this fuzzing session was 50 MB.
Need a tool to minimize test cases before investigating the crashes or sending
them to a vendor? Check out the afl-tmin that comes with the fuzzer!
Sources: src/afl-fuzz-bitmap.c:610-630
Conclusion
The crash triage ecosystem in AFL++ is a comprehensive set of features and tools designed to streamline the process of handling and analyzing fuzzing-induced failures. From intelligent, coverage-based uniqueness checks in afl-fuzz to powerful post-processing utilities like afl-tmin and afl-cmin, the system ensures that developers receive concise, relevant, and actionable data to effectively find and fix bugs.json {"thought": "I need to create a technical wiki page about \"Crash Triage\" for the AFLplusplus project.\n\nHere's my plan:\n1. **Start with the `<details>` block.** I'll list the two provided files (`utils/crash_triage/triage_crashes.sh` and `src/afl-analyze.c`) and then find at least three more relevant files from the provided context to meet the minimum of five.\n * `src/afl-fuzz-bitmap.c`: This file contains `save_if_interesting`, `write_crash_readme`, and logic for handling crashes and hangs. This is highly relevant.\n * `src/afl-fuzz-init.c`: This file has `perform_dry_run` which handles initial seed crashes, and `handle_existing_out_dir` which deals with backing up old crash directories. This is also very relevant.\n * `src/afl-tmin.c`: This is the test case minimizer, a key tool for crash triage. It's explicitly mentioned in the `write_crash_readme` function.\n * `afl-cmin.bash`: This is the corpus minimizer, which is also part of the triage/analysis process.\n * `utils/mutation_chain/mutation_chain.py`: This tool is specifically for analyzing the history of a crash file, which is a form of triage.\n * `src/afl-fuzz.c`: The main entry point, which orchestrates the whole process, including calling `save_if_interesting`.\n * `custom_mutators/libfuzzer/FuzzerDriver.cpp`: Contains crash minimization logic (`MinimizeCrashInput`, `CleanseCrashInput`). This is relevant to the broader concept of crash analysis.\n\n I'll select a good set of 5+ files from this list. My final list will be:\n * `src/afl-fuzz-bitmap.c` (core crash saving logic)\n * `src/afl-fuzz-init.c` (initial crash handling, README creation)\n * `src/afl-tmin.c` (test case minimization tool)\n * `afl-cmin.bash` (corpus minimization tool)\n * `utils/mutation_chain/mutation_chain.py` (mutation history analysis)\n * `src/afl-analyze.c` (file analysis tool, though less about triage)\n * `custom_mutators/libfuzzer/FuzzerDriver.cpp` (LibFuzzer-style crash minimization)\n\n2. **H1 Heading:** `# Crash Triage`.\n\n3. **Introduction:** I'll explain that crash triage in AFL++ is the process of identifying, saving, classifying, and analyzing crashing inputs discovered during a fuzzing session. I'll mention that it involves several components, from the core fuzzer's crash detection to standalone tools for minimization and analysis. I'll reference the `crashes/` and `hangs/` directories.\n\n4. **Detailed Sections:** I'll structure the page into logical parts.\n\n * **## Crash and Hang Detection:**\n * Explain how `afl-fuzz` identifies and saves interesting inputs, particularly crashes and hangs, using the `save_if_interesting` function in `src/afl-fuzz-bitmap.c`.\n * Describe the `fault` parameter and how it distinguishes between normal execution, timeouts (`FSRV_RUN_TMOUT`), and crashes (`FSRV_RUN_CRASH`).\n * Mention the `crashes/` and `hangs/` directories where findings are stored.\n * Create a flowchart for `save_if_interesting`.\n\n * **## Crash Uniqueness and Classification:**\n * Explain how AFL++ determines if a crash is \"unique\" before saving it.\n * Detail the use of `virgin_crash` and `virgin_tmout` bitmaps.\n * The `simplify_trace` function is called to ignore hit counts, focusing only on new path coverage for uniqueness.\n * The `has_new_bits` function is used to check against the respective virgin bitmap.\n * I'll add a Mermaid diagram illustrating this uniqueness check.\n\n * **## Crash File Naming Convention:**\n * Describe the structure of the filenames for crashes and hangs.\n * Use `describe_op` from `src/afl-fuzz-bitmap.c` to explain the components: `id`, `sig`, `src`, `op`, `time`, `execs`, etc.\n * Provide a table summarizing the filename components and their meaning.\n * Mention the `AFL_SHA1_FILENAMES` environment variable as an alternative.\n\n * **## Post-Fuzzing Analysis Tools:**\n * This section will cover the tools used after a crash is found.\n\n * **### `afl-tmin`: Test Case Minimization**\n * Explain the purpose of `afl-tmin` based on `src/afl-tmin.c`: to reduce a crashing test case to the smallest possible size while still causing the crash.\n * Describe its operation: block deletion, symbol minimization, and character minimization.\n * Mention its modes: crash mode, instrumented mode, and hang mode.\n * Create a flowchart for the `minimize` function in `afl-tmin.c`.\n\n * **### `afl-cmin`: Corpus Minimization**\n * Explain `afl-cmin.bash`'s role: to find the smallest subset of files that trigger the full range of instrumentation seen in a larger corpus.\n * Mention it's useful for screening large seed corpora or minimizing the fuzzer-generated queue.\n * Briefly describe its process: collecting traces with `afl-showmap`, sorting tuples, and selecting the best candidates.\n * Create a flowchart for the `afl-cmin.bash` script's logic.\n\n * **### `mutation_chain.py`: Mutation History Analysis**\n * Explain the purpose of `utils/mutation_chain/mutation_chain.py`: to recursively compute the chain of queue items that led to a crash file.\n * This helps understand the path from an initial seed to the final crash.\n * Mention how it parses `src:` and `sync:` fields in filenames.\n\n * **### LibFuzzer-style Crash Minimization**\n * Based on `custom_mutators/libfuzzer/FuzzerDriver.cpp`, describe the `-minimize_crash` and `-cleanse_crash` features.\n * `MinimizeCrashInput`: Iteratively tries to reduce the input size.\n * `CleanseCrashInput`: Tries to replace bytes with \"clean\" values (like spaces) while preserving the crash.\n\n * **## Informational Files:**\n * Describe the `crashes/README.txt` file generated by `write_crash_readme` in `src/afl-fuzz-bitmap.c`.\n * Mention the information it contains: command line, memory limit, and a suggestion to use `afl-tmin`.\n\n5. **Mermaid Diagrams:** I will create several diagrams as planned above:\n * A flowchart for the `save_if_interesting` logic.\n * A flowchart for the crash uniqueness check.\n * A flowchart for the `afl-tmin` minimization process.\n * A flowchart for the `afl-cmin.bash` logic.\n\n6. **Tables:** I'll create a table for the crash filename components.\n\n7. **Code Snippets:** I might include a snippet of the `describe_op` function or the `crashes/README.txt` content.\n\n8. **Source Citations:** I will diligently add citations for every piece of information, referencing the files and line numbers.\n\n9. **Conclusion:** I'll summarize the importance of the crash triage process in making fuzzing results actionable and understandable for developers.\n\nI will now start writing the content, following this structure.<details>\n<summary>Relevant source files</summary>\nThe following files were used as context for generating this wiki page:\n- [src/afl-fuzz-bitmap.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c)\n- [src/afl-tmin.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-tmin.c)\n- [src/afl-fuzz-init.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-init.c)\n- [afl-cmin.bash](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/afl-cmin.bash)\n- [utils/mutation_chain/mutation_chain.py](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/utils/mutation_chain/mutation_chain.py)\n- [custom_mutators/libfuzzer/FuzzerDriver.cpp](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/custom_mutators/libfuzzer/FuzzerDriver.cpp)\n- [src/afl-analyze.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-analyze.c)\n- [src/afl-fuzz.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz.c)\n</details>\n\n# Crash Triage\n\nCrash triage in AFL++ is the systematic process of identifying, classifying, saving, and analyzing inputs that cause a target program to crash or hang. This process is crucial for making fuzzing results actionable. It involves not only the core fuzzer's ability to detect and save unique crashes but also a suite of external tools designed to minimize and analyze these findings. The primary goal is to provide developers with the smallest, most understandable test cases to reproduce and debug the discovered vulnerabilities.\n\nThe main fuzzer, `afl-fuzz`, automatically saves crashing inputs to the `crashes/` directory and hanging inputs to the `hangs/` directory within the specified output folder. After a fuzzing session, developers can use tools like `afl-tmin` and `afl-cmin` to further refine these results.\n\n## Crash and Hang Detection\n\nThe core of crash detection resides within the `afl-fuzz` main loop. The function `save_if_interesting` is responsible for evaluating the outcome of each execution and deciding whether to save the input.\n\n*Sources: [src/afl-fuzz-bitmap.c:836-1309](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L836-L1309), [src/afl-fuzz.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz.c)*\n\n### Execution Outcome Classification\n\nAfter an input is executed in the target, `afl-fuzz` receives a fault status. The primary statuses relevant to triage are:\n* `FSRV_RUN_OK`: The program executed normally.\n* `FSRV_RUN_TMOUT`: The program exceeded the execution timeout.\n* `FSRV_RUN_CRASH`: The program terminated due to a signal (e.g., SIGSEGV, SIGABRT).\n\nThe `save_if_interesting` function uses this fault status to determine the subsequent course of action. If the execution is normal (`FSRV_RUN_OK`), it checks for new code coverage. If a crash or timeout occurs, it proceeds to the uniqueness check and saving process.\n\n*Sources: [src/afl-fuzz-bitmap.c:836-840](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L836-L840), [src/afl-fuzz-bitmap.c:1082-1084](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1082-L1084), [src/afl-fuzz-bitmap.c:1168-1170](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1168-L1170)*\n\n### Saving Process\n\nThe following diagram illustrates the high-level logic of the `save_if_interesting` function when handling potential crashes and new coverage.\n\nmermaid\nflowchart TD\n A[Execution Finished] --> B{Fault Status?};\n B -- FSRV_RUN_OK --> C{New Coverage?};\n B -- FSRV_RUN_CRASH --> E[Check Crash Uniqueness];\n B -- FSRV_RUN_TMOUT --> F[Check Hang Uniqueness];\n C -- Yes --> D[Save to 'queue/'];\n C -- No --> X[Discard Input];\n E -- Unique --> G[Save to 'crashes/'];\n E -- Not Unique --> X;\n F -- Unique --> H[Re-run with longer timeout];\n F -- Not Unique --> X;\n H -- Still a Timeout --> I[Save to 'hangs/'];\n H -- Now a Crash --> G;\n H -- Now OK --> X;\n\n*This diagram shows the decision flow for saving interesting inputs, including new coverage, crashes, and hangs.*\n*Sources: [src/afl-fuzz-bitmap.c:836-1309](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L836-L1309)*\n\n## Crash Uniqueness and Classification\n\nTo avoid saving thousands of redundant crash files, AFL++ employs a uniqueness check. A crash or hang is considered \"unique\" if it triggers an execution path not seen in previous crashes or hangs of the same type.\n\n*Sources: [src/afl-fuzz-bitmap.c:1089-1097](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1089-L1097), [src/afl-fuzz-bitmap.c:1176-1184](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1176-L1184)*\n\n### Uniqueness Check Workflow\n\n1. **Simplify Trace**: For a crash or hang, the execution trace (bitmap) is first simplified. The `simplify_trace` function is called, which converts the hit counts for each edge into a binary state (hit or not hit), effectively ignoring how many times an edge was traversed.\n2. **Check Against Virgin Map**: The simplified trace is then compared against a dedicated \"virgin\" bitmap for that fault type (`virgin_crash` for crashes, `virgin_tmout` for hangs).\n3. **`has_new_bits`**: The `has_new_bits` function performs this comparison. If the input's trace contains any bit (edge) not present in the virgin map, it is considered unique.\n4. **Update Virgin Map**: If the crash is unique, the new bits from its trace are added to the corresponding virgin map, so subsequent crashes with the same path will not be considered unique.\n\nThis process is illustrated below:\n\nmermaid\nflowchart TD\n A[Crash or Hang Occurs] --> B[Get Execution Trace];\n B --> C[simplify_trace(trace)];\n C --> D{Fault Type?};\n D -- Crash --> E[has_new_bits(simplified_trace, virgin_crash)];\n D -- Hang --> F[has_new_bits(simplified_trace, virgin_tmout)];\n E -- Returns True --> G[Save Crash & Update virgin_crash];\n F -- Returns True --> H[Save Hang & Update virgin_tmout];\n E -- Returns False --> I[Discard as Duplicate];\n F -- Returns False --> I;\n\n*This diagram outlines how AFL++ determines if a crash or hang is unique before saving.*\n*Sources: [src/afl-fuzz-bitmap.c:45-51](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L45-L51), [src/afl-fuzz-bitmap.c:1093-1095](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1093-L1095), [src/afl-fuzz-bitmap.c:1178-1180](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1178-L1180)*\n\n## Crash File Naming Convention\n\nSaved crash and hang files are given descriptive names that encode information about their origin and the circumstances of their discovery. This is handled by the `describe_op` function.\n\n*Sources: [src/afl-fuzz-bitmap.c:482-581](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L482-L581)*\n\nA typical crash filename looks like this: `id:000000,sig:06,src:000005,op:havoc,rep:8`. The components are detailed in the table below.\n\n| Component | Description | Source |\n| :--- | :--- | :--- |\n| `id` | A sequential identifier for the saved crash or hang. | [src/afl-fuzz-bitmap.c:1232](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1232) |\n| `sig` | The signal number that caused the crash (e.g., `06` for SIGABRT, `11` for SIGSEGV). | [src/afl-fuzz-bitmap.c:1233](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1233) |\n| `src` | The ID of the parent queue item that was mutated to produce this crash. If it was a splice, it will be in the format `src:xxxxxx+yyyyyy`. If it was synced from another fuzzer, it will be `sync:fuzzer_name,src:xxxxxx`. | [src/afl-fuzz-bitmap.c:510-520](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L510-L520) |\n| `time` | The wall-clock time in milliseconds since the fuzzer started when this crash was found. | [src/afl-fuzz-bitmap.c:522-524](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L522-L524) |\n| `execs` | The total number of executions performed by the fuzzer when this crash was found. | [src/afl-fuzz-bitmap.c:522-524](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L522-L524) |\n| `op` | The mutation operator that was being applied. Examples: `havoc`, `splice`, `flip1`. | [src/afl-fuzz-bitmap.c:556-557](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L556-L557) |\n| `pos` | The byte offset within the input file where the mutation was applied. | [src/afl-fuzz-bitmap.c:559-561](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L559-L561) |\n| `val` | The value used in an arithmetic or interesting value mutation. | [src/afl-fuzz-bitmap.c:563-567](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L563-L567) |\n| `rep` | The repetition count for stacked mutations like havoc. | [src/afl-fuzz-bitmap.c:571-572](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L571-L572) |\n| `+cov` | Indicates that this input also discovered new edge coverage. | [src/afl-fuzz-bitmap.c:577](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L577) |\n| `+tout` | Indicates the input originally timed out but was saved for other reasons (e.g., it crashed on a re-run with a longer timeout). | [src/afl-fuzz-bitmap.c:575](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L575) |\n| `+san` | Indicates the crash was found by a sanitizer build and did not increase coverage. | [src/afl-fuzz-bitmap.c:579](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L579) |\n\nThe environment variable `AFL_SHA1_FILENAMES` can be set to use the SHA1 hash of the file content as the filename instead.\n\n*Sources: [src/afl-fuzz-bitmap.c:1229-1243](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L1229-L1243)*\n\n## Post-Fuzzing Analysis Tools\n\nAFL++ includes several command-line utilities to help analyze and minimize crash data after a fuzzing session.\n\n### `afl-tmin`: Test Case Minimization\n\n`afl-tmin` is a tool that takes a single crashing input file and attempts to reduce its size as much as possible while still causing the same crash or producing the same instrumentation output.\n\n*Sources: [src/afl-tmin.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-tmin.c)*\n\nThe minimization process in `afl-tmin` occurs in several stages:\n1. **Block Normalization**: Attempts to replace blocks of data with a neutral character (e.g., '0') to see if the content matters.\n2. **Block Deletion**: Iteratively removes blocks of decreasing size from the input file.\n3. **Alphabet Minimization**: Tries to replace unique bytes with a common byte ('0') to reduce the set of characters needed to trigger the bug.\n4. **Character Minimization**: A final pass that attempts to replace individual non-essential bytes with '0'.\n\nmermaid\nflowchart TD\n A[Start afl-tmin with input file] --> B[Dry Run: Confirm initial crash/path];\n B --> C[Stage 0: Block Normalization];\n C --> D[Stage 1: Block Deletion];\n D --> E{Block size > limit?};\n E -- Yes --> D;\n E -- No --> F[Stage 2: Alphabet Minimization];\n F --> G[Stage 3: Character Minimization];\n G --> H{Any changes in pass?};\n H -- Yes --> D;\n H -- No --> I[Write minimized output file];\n\n*This diagram shows the multi-stage minimization process of `afl-tmin`.*\n*Sources: [src/afl-tmin.c:502-748](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-tmin.c#L502-L748)*\n\n### `afl-cmin`: Corpus Minimization\n\n`afl-cmin.bash` is a script used to find the smallest subset of files from a larger corpus (e.g., the `queue/` directory) that collectively trigger all unique execution paths observed in the original set. It is useful for creating a minimal seed corpus for a new fuzzing session or for reducing a large queue for easier analysis.\n\n*Sources: [afl-cmin.bash](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/afl-cmin.bash)*\n\nThe script operates as follows:\n1. **Collect Traces**: It runs `afl-showmap` on every file in the input directory to generate a trace file containing the hit tuples.\n2. **Sort Tuples**: It aggregates all tuples from all traces and sorts them by frequency to identify unique tuples.\n3. **Find Best Candidates**: For each unique tuple, it identifies the smallest input file that triggers it.\n4. **Write Output**: It copies the selected minimal set of files to the output directory.\n\n*Sources: [afl-cmin.bash:204-325](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/afl-cmin.bash#L204-L325)*\n\n### `mutation_chain.py`: Mutation History Analysis\n\nThis Python script helps in understanding the lineage of a crash. By parsing the `src:` and `sync:` fields in filenames, it can recursively trace a crash file back to its original seed in the queue, showing the complete mutation history. This is invaluable for debugging how a simple input evolved into a complex crashing one.\n\n*Sources: [utils/mutation_chain/mutation_chain.py](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/utils/mutation_chain/mutation_chain.py)*\n\n### LibFuzzer-style Crash Minimization\n\nThe LibFuzzer custom mutator compatibility layer includes its own crash minimization and cleansing logic, which can be invoked with command-line flags.\n\n* `-minimize_crash=1`: This flag initiates a crash minimization loop. It repeatedly runs the fuzzer on a crashing input, attempting to find a smaller version that produces the same crash signature (dedup token).\n* `-cleanse_crash=1`: This attempts to replace bytes in a crashing input with \"clean\" values (space or `0xFF`) to simplify the input without losing the crash.\n\n*Sources: [custom_mutators/libfuzzer/FuzzerDriver.cpp:388-508](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/custom_mutators/libfuzzer/FuzzerDriver.cpp#L388-L508), [custom_mutators/libfuzzer/FuzzerDriver.cpp:341-386](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/custom_mutators/libfuzzer/FuzzerDriver.cpp#L341-L386)*\n\n## Informational Files\n\nTo aid developers, AFL++ automatically generates a `README.txt` file in the `crashes/` directory upon finding the first unique crash.\n\n*Sources: [src/afl-fuzz-bitmap.c:586-634](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz-bitmap.c#L586-L634)*\n\nThis file contains:\n* The exact command line used to start the fuzzing session.\n* The memory limit (`-m`) that was set.\n* A strong recommendation to use `afl-tmin` to minimize the test case before analysis.\n\nExample content of `crashes/README.txt`:\n\nCommand line used to find this crash:\n\n./afl-fuzz -i in -o out -- ./test_program\n\nIf you can't reproduce a bug outside of afl-fuzz, be sure to set the same\nmemory limit. The limit used for this fuzzing session was 50 MB.\n\nNeed a tool to minimize test cases before investigating the crashes or sending\nthem to a vendor? Check out the afl-tmin that comes with the fuzzer!\n```\nSources: src/afl-fuzz-bitmap.c:610-630\n\n## Conclusion\n\nThe crash triage ecosystem in AFL++ is a comprehensive set of features and tools designed to streamline the process of handling and analyzing fuzzing-induced failures. From intelligent, coverage-based uniqueness checks in afl-fuzz to powerful post-processing utilities like afl-tmin and afl-cmin, the system ensures that developers receive concise, relevant, and actionable data to effectively find and fix bugs."}