- Swift ABI: tagged pointers, garbage-input abort path, ObjC bridging - C++ fuzz: libFuzzer dlopen coverage limits, AFL++ QEMU mode, vtable seeding - Cross-language IR: CodeQL/Infer/Joern patterns, Swift SIL gaps in fold IR - MIR verification: Kani/Prusti/Creusot approaches, BorrowTracker wiring
49 lines
1.9 KiB
Markdown
49 lines
1.9 KiB
Markdown
# Swift ABI Research for Binary Fuzzing
|
|
|
|
> Generated 2026-05-28. Reference for Swift binary fuzzing.
|
|
|
|
## Calling Convention (ARM64)
|
|
|
|
- **x0**: self parameter (the object reference)
|
|
- **x1-x7**: additional arguments
|
|
- **x21**: error return register (for throwing functions)
|
|
- **x0** also used for return value
|
|
|
|
## Tagged Pointer Format
|
|
|
|
Swift uses tagged pointers on ARM64:
|
|
- **Small values** (integers, bools): stored inline in pointer bits
|
|
- **Small objects** (strings < 15 bytes): stored inline
|
|
- **Regular objects**: pointer to heap-allocated metadata
|
|
|
|
Bits 60-62 discriminate the tag:
|
|
- `0b000` = regular heap pointer
|
|
- `0b001` = small value
|
|
- `0b010` = small object
|
|
|
|
## Garbage Input Behavior
|
|
|
|
When the fuzzer passes random `uint64_t` as `self`:
|
|
1. Swift runtime attempts to dereference the "pointer" as type metadata
|
|
2. If the bit pattern doesn't match valid metadata → `swift_unexpectedError()`
|
|
3. This calls `abort()` — SIGABRT, not SIGSEGV
|
|
4. libFuzzer's default signal handler catches SIGABRT but the coverage counters show cov:2 because the abort happens before any real code executes
|
|
|
|
## Tooling
|
|
|
|
- `swift demangle`: demangles Swift symbol names
|
|
- Frida: can hook ObjC methods via `ObjC.classes.FuzzMeClass`
|
|
- `lldb -o "expr"`: expression evaluation against Swift objects
|
|
|
|
## IRGen Patterns
|
|
|
|
- Value witness tables: manage copy/destroy/assign for generic types
|
|
- Existential containers: type-erased protocol values
|
|
- SILGen: Swift AST → SIL lowering pass, then SIL → LLVM IR
|
|
|
|
## Implications for fold
|
|
|
|
1. **Swift-mangled symbols are unfuzzable via dlopen**: need ObjC bridging or Swift-source harness generation
|
|
2. **ObjC interop path works**: our `objc_msgSend` harness routes through the ObjC runtime which handles nil receivers gracefully
|
|
3. **C-ABI exports work**: `@_cdecl` functions are safe dlopen targets
|
|
4. **Future**: Swift-source harness generation with `swiftc -emit-library` could construct valid objects
|