Minimize Reproducer
Workflow
1. Identify the Failure Signature
Before minimizing, understand exactly what "reproduction" looks like.
- Exact Command: e.g., `out/x64.release/d8 --fuzzing poc.js`
- Failure Type: Crash (segfault, abort), Assertion failure, Sandbox
violation, or Incorrect output.
- Stability Check: Initially check how stable the reproduction is. If it's
flaky, you'll need to run it multiple times at every step. Use the bundled
`repro_check.sh` script.
2. Command-Line Flag Minimization
Find the minimal set of V8 flags required to reproduce the issue.
- Batch Removal: Start by removing larger batches of flags (e.g., all flags
starting with `--no-` or all optimization flags).
- One-by-One: Progressively remove individual flags until only the essential
ones remain.
- Common Critical Flags: Pay attention to flags like `--sandbox-fuzzing`,
`--memory-corruption-via-watchpoints`, or `--turbofan`, as these often
control the underlying feature being tested.
- Validation: Test reproduction after every step. If it stops failing,
restore the last flag removed.
3. File Minimization (The Iterative Phase)
Reduce the input JavaScript file systematically. Always work on a copy (e.g.,
`poc-copy.js`) and maintain a `poc-min.js` as your "best known" version.
- Remove Large Blocks: Start by removing entire functions, classes, or large
blocks of code (e.g., fuzzer boilerplate, unused libraries).
- Binary Search: If a large block is present, try removing half. If it still
fails, that half was unnecessary.
- Remove Individual Lines: Once large blocks are gone, try removing
individual lines.
- Inline Functions: If a function is called only once, inline its content
and remove the definition.
- Simplify Wrappers: Remove `try-catch` blocks but retain the code inside
the `try` block.
- Stabilize with Loops: If a reproduction is flaky (e.g., it only fails 10%
of the time), add a loop around the triggering logic to increase the failure
probability to 100%.
4. Wasm Minimization
WebAssembly reproductions often start as opaque Uint8Array blobs. Converting
these to readable WasmModuleBuilder JS is critical for understanding and
minimizing the logic.
- Convert Early with
wami: Use the wami tool to automatically generate
WasmModuleBuilder code from a Wasm binary. This is much less error-prone
than manual conversion.
- Command:
out/x64.release/wami --mjsunit input.wasm > poc.js
- Handle
WasmModuleBuilder Specifics:
- Recursive Types: Be careful with recursive type definitions; ensure they
are correctly indexed.
- Reference Types: When specifying indices for heap types (e.g., in
struct.get), use wasmRefNullType(typeIndex) or similar helpers where the
builder expects a type object rather than a raw integer.
- Signature Validation: After conversion, verify that the module still
reproduces the original issue.
WasmModuleBuilder might require minor
manual adjustments if the original binary had subtle validation errors.
5. Special API Handling (e.g., Sandbox API)
- Offset Alignment: Some APIs (like
Sandbox.markForCorruptionOnAccess)
require specific alignments (e.g., tagged-size-aligned offsets like 8, 12, or
16).
- Object Context: Ensure the object being manipulated (e.g., a String) is
large enough for the offset being targeted. Use
%DebugPrint(obj) with
--allow-natives-syntax to inspect the internal structure.
6. Clean and Polish
- Rename Variables: Obfuscated names like
__v_0 should be renamed to
something descriptive like str or targetObj.
- Readability > Size: A 20-line file that is easy to understand is better
than a 10-line file that is completely cryptic.
- Self-Contained: Ensure the final
poc-min.js is completely self-contained
and does not rely on external fuzzer libraries unless strictly necessary.
Guidelines
- Work on a copy: Never modify the original reproduction file directly.
- Validate EVERY change: A single character change can stop a bug from
reproducing. Always verify.
- Keep a "Best Version": Always update your `-min.js` file as soon as you
find a smaller working version. This allows you to easily backtrack if a more
aggressive minimization fails.
1---2name: minimize-reproducer3description: Use this when you need to minimize a complex or bloated JavaScript test case (e.g., from a fuzzer or external report) into a minimal, readable reproduction for debugging V8 issues.4---56# Minimize Reproducer78## Workflow910### 1. Identify the Failure Signature1112Before minimizing, understand exactly what "reproduction" looks like.1314- **Exact Command:** e.g., \`out/x64.release/d8 --fuzzing poc.js\`15- **Failure Type:** Crash (segfault, abort), Assertion failure, Sandbox16 violation, or Incorrect output.17- **Stability Check:** Initially check how stable the reproduction is. If it's18 flaky, you'll need to run it multiple times at every step. Use the bundled19 \`repro_check.sh\` script.2021### 2. Command-Line Flag Minimization2223Find the minimal set of V8 flags required to reproduce the issue.2425- **Batch Removal:** Start by removing larger batches of flags (e.g., all flags26 starting with \`--no-\` or all optimization flags).27- **One-by-One:** Progressively remove individual flags until only the essential28 ones remain.29- **Common Critical Flags:** Pay attention to flags like \`--sandbox-fuzzing\`,30 \`--memory-corruption-via-watchpoints\`, or \`--turbofan\`, as these often31 control the underlying feature being tested.32- **Validation:** Test reproduction after every step. If it stops failing,33 restore the last flag removed.3435### 3. File Minimization (The Iterative Phase)3637Reduce the input JavaScript file systematically. Always work on a copy (e.g.,38\`poc-copy.js\`) and maintain a \`poc-min.js\` as your "best known" version.3940- **Remove Large Blocks:** Start by removing entire functions, classes, or large41 blocks of code (e.g., fuzzer boilerplate, unused libraries).42- **Binary Search:** If a large block is present, try removing half. If it still43 fails, that half was unnecessary.44- **Remove Individual Lines:** Once large blocks are gone, try removing45 individual lines.46- **Inline Functions:** If a function is called only once, inline its content47 and remove the definition.48- **Simplify Wrappers:** Remove \`try-catch\` blocks but retain the code inside49 the \`try\` block.50- **Stabilize with Loops:** If a reproduction is flaky (e.g., it only fails 10%51 of the time), add a loop around the triggering logic to increase the failure52 probability to 100%.5354### 4. Wasm Minimization5556WebAssembly reproductions often start as opaque `Uint8Array` blobs. Converting57these to readable `WasmModuleBuilder` JS is critical for understanding and58minimizing the logic.5960- **Convert Early with `wami`:** Use the `wami` tool to automatically generate61 `WasmModuleBuilder` code from a Wasm binary. This is much less error-prone62 than manual conversion.63 - **Command:** `out/x64.release/wami --mjsunit input.wasm > poc.js`64- **Handle `WasmModuleBuilder` Specifics:**65 - **Recursive Types:** Be careful with recursive type definitions; ensure they66 are correctly indexed.67 - **Reference Types:** When specifying indices for heap types (e.g., in68 `struct.get`), use `wasmRefNullType(typeIndex)` or similar helpers where the69 builder expects a type object rather than a raw integer.70 - **Signature Validation:** After conversion, verify that the module still71 reproduces the original issue. `WasmModuleBuilder` might require minor72 manual adjustments if the original binary had subtle validation errors.7374### 5. Special API Handling (e.g., Sandbox API)7576- **Offset Alignment:** Some APIs (like `Sandbox.markForCorruptionOnAccess`)77 require specific alignments (e.g., tagged-size-aligned offsets like 8, 12, or78 16).79- **Object Context:** Ensure the object being manipulated (e.g., a String) is80 large enough for the offset being targeted. Use `%DebugPrint(obj)` with81 `--allow-natives-syntax` to inspect the internal structure.8283### 6. Clean and Polish8485- **Rename Variables:** Obfuscated names like `__v_0` should be renamed to86 something descriptive like `str` or `targetObj`.87- **Readability > Size:** A 20-line file that is easy to understand is better88 than a 10-line file that is completely cryptic.89- **Self-Contained:** Ensure the final `poc-min.js` is completely self-contained90 and does not rely on external fuzzer libraries unless strictly necessary.9192## Guidelines9394- **Work on a copy:** Never modify the original reproduction file directly.95- **Validate EVERY change:** A single character change can stop a bug from96 reproducing. Always verify.97- **Keep a "Best Version":** Always update your \`-min.js\` file as soon as you98 find a smaller working version. This allows you to easily backtrack if a more99 aggressive minimization fails.