fold/docs/internal/binary-fuzz-corpus.md
trvon ffc7917957
feat: symbolic IR, swift backend, binary-to-fuzz pipeline, SARIF fixes
- Rust IR encoder (encodeRustIr): walks HIR expr trees, fires SafetyObserver hooks
- Swift SIL frontend (fold-swift): swiftc -emit-sil parser, demangling, NDJSON output
- SwiftBackend: --mode swift CLI routing, shells out to fold-swift
- Binary-to-fuzz: Mach-O export discovery, ARM64 ABI param-count inference, dlopen harness generation
- Language-agnostic IR: json_keys canonical constants, Call/Member/ArraySubscript/Cast/HeapNew nodes
- Dogfood fixes: SARIF kind field, cross-detector dedup, harness_file in predictions, Swift stoi safety
- Corpuses: swift-sil-z3-corpus.md, binary-fuzz-corpus.md
- AGENTS.md: cross-language wire format rule
2026-05-27 15:29:14 -04:00

137 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Binary-to-Fuzz Pipeline Corpus
> Generated 2026-05-27. Reference for Mach-O binary → ABI inference → harness → fuzz.
## ARM64 Mach-O ABI (Apple Platforms)
Source: Apple "ARM64 Function Calling Conventions"
### Register Assignment
| Register | Role |
|----------|------|
| x0–x7 | Integer/pointer arguments 0–7 |
| d0–d7 | Floating-point arguments 0–7 |
| x8 | Indirect result location |
| x9–x15 | Temporary (caller-saved) |
| x16–x17 | Intra-procedure-call scratch |
| x18 | Platform register |
| x19–x28 | Callee-saved |
| x29 (fp) | Frame pointer |
| x30 (lr) | Link register (return address) |
| sp | Stack pointer |
### Parameter Count Inference Heuristic
For each exported function, r2 disassembles the first basic block. Count distinct
register **reads** (not writes) among x0–x7 BEFORE the first call/branch. This
estimates the parameter count.
```
Example: function reads x0, x1, x2 → 3 parameters
function reads x0 only → 1 parameter
function writes to x0, reads nothing → 0 parameters
```
Limitations:
- Variadic functions are not detected
- Struct-by-value arguments (passed via x8 indirect + x0 pointer) may be miscounted
- Functions that stash args to callee-saved regs before use may be undercounted
- Heuristic only — not a formal ABI analysis
### Mach-O Structure
| Section | Contents |
|---------|----------|
| `__TEXT,__text` | Executable code |
| `__TEXT,__cstring` | C string literals |
| `__DATA,__data` | Initialized data |
| `__DATA,__bss` | Zero-initialized data |
| `__LINKEDIT` | Export trie, symbol table, string table |
| `__TEXT,__swift5_*` | Swift metadata sections |
## r2 Binary Analysis Commands (fold usage)
| r2 Command | Output | fold Use |
|------------|--------|----------|
| `aflj` | Function list JSON | Discover functions for fuzz targets |
| `isj` | Symbol table JSON | Resolve function names, classify exports |
| `iEj` | Exports JSON | Identify dlopen-able symbols |
| `izzj` | String catalog JSON | Existing binary security detector path |
| `pdbj @ addr` | Basic block disassembly JSON | ABI parameter-count inference |
| `afij @ addr` | Function info JSON | Function boundaries, call graph |
## dlopen Harness Pattern
Source: rev.ng blog, AFL++ binary-only fuzzing docs
```c
// Auto-generated by fold binary-fuzz-prep
// Target: /path/to/library.node or Mach-O binary
#include <dlfcn.h>
#include <stdint.h>
#include <stddef.h>
// Resolved function pointers
typedef void (*target_fn_t)(uint64_t, uint64_t, uint64_t);
static target_fn_t target_fn = NULL;
// One-time library load
__attribute__((constructor))
static void load_library(void) {
void* handle = dlopen("TARGET_PATH", RTLD_NOW);
if (handle) {
target_fn = (target_fn_t)dlsym(handle, "TARGET_SYMBOL");
}
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (!target_fn || size < 24) return 0; // 3 × uint64_t
uint64_t arg0, arg1, arg2;
memcpy(&arg0, data + 0, 8);
memcpy(&arg1, data + 8, 8);
memcpy(&arg2, data + 16, 8);
target_fn(arg0, arg1, arg2);
return 0;
}
```
Compile:
```bash
clang++ -fsanitize=fuzzer,address -g -O1 harness.cc -o harness.fuzz
```
## Prior Art
| Source | Relevance |
|--------|-----------|
| rev.ng blog "Fuzzing binaries with libFuzzer" | dlopen + harness pattern for Mach-O/ELF |
| arXiv 2306.15596 "Automated Fuzzing Harness Generation" | API fuzzing harness synthesis |
| AFL++ binary-only docs | dlopen-based library fuzzing with persistent mode |
| Romain Thomas "Fuzzing Windows ARM64" | ARM64 binary fuzzing with QBDI |
| JMPscare (BAR 2021) | Introspection for binary-only fuzzing |
| "Binary-level directed fuzzing" (ANSSI thesis) | Directed fuzzing of closed-source binaries |
## Integration Architecture
```
Mach-O binary → r2 aflj → function list
↓
r2 pdbj @ addr → param count (ABI inference)
↓
harness_emitter → dlopen C harness
↓
clang++ -fsanitize=fuzzer,address → harness.fuzz
↓
libFuzzer + ASan → crash artifacts
↓
ASan parser → ConcreteWitness findings
```
## References
- Apple ARM64 ABI: `https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms`
- rev.ng binary fuzzing: `https://rev.ng/blog/fuzzing-binaries`
- AFL++ binary-only: `https://aflplus.plus/docs/fuzzing_binary-only_targets/`
- arXiv 2306.15596: Automated Fuzzing Harness Generation for Library APIs
- r2 book: `https://book.rada.re/`