Fil-C: Garbage In, Memory Safety Out

Lobsters Hottest Tools

Summary

Fil-C is a fully memory-safe implementation of C/C++. It bundles pointer values with boundary information using invisicaps at the LLVM IR stage, achieving high compatibility with a performance penalty of about 4x.

<p><a href="https://lobste.rs/s/badu44/fil_c_garbage_memory_safety_out">Comments</a></p>
Original Article
View Cached Full Text

Cached at: 07/24/26, 04:59 AM

### TL;DR Fil-C is a fully memory-safe C/C++ implementation that bundles pointer values with boundary information using invisicaps, and intercepts pointer operations at the LLVM IR stage. This ensures that even if a compiled program has out-of-bounds or use-after-free errors, attackers cannot gain control over the entire memory. Performance is roughly 4× slower on average, about 6× slower for SQLite, but compatibility is very high—about half of C/C++ software packages compile and run without modification. ## What is memory safety? Define a memory-safe programming language: Memory logic errors do not give an attacker control over the entire memory. In non-memory-safe languages (such as traditional C/C++, which the speaker calls "YOLO C"), attackers can use array out-of-bounds access, type confusion, and other techniques to write arbitrary addresses into pointers, thereby accessing or tampering with any memory location. Even though modern operating systems deploy mitigations such as ASLR, NX bit, CFI, and pointer authentication, attackers can still bypass these defenses through ROP chains or overwriting critical data (e.g., command buffers), or even use "weird execution" to stitch together arbitrary operations from the program's instruction sequence. Therefore, the core goal is to prevent attackers from gaining "unrestricted memory access"; out-of-bounds access should only access the wrong index, and use-after-free should only cause a program crash. ## Shortcomings of prior work Since the 1990s, people have tried to make C memory-safe, but most approaches have not succeeded: - **Safe C**: Does not support the full C language, does not support C++, does not support threads. - **Sanitizers**: Do not provide memory safety by themselves (they check access to freed regions but do not prevent access to live objects). - **MTE/PA**: Probabilistic defenses; attackers have about a 1/5 chance of bypassing them. - **CHERI**: Depends on special hardware that is not available for purchase, and general-purpose hardware has long maintained a performance lead. ## Fil-C's design goals and scope The speaker defined the scope of the problem from a management perspective, abandoning unnecessary goals: - **No binary compatibility**: Cannot be mixed with objects not compiled with Fil-C. - **Initially not focused on speed**: The first version was 200× slower; now the median is about 4× slower, about 6× slower for SQLite, and even faster than Rust on Blake 3 (thanks to better SIMD support). - **Core goals**: Memory safety + high compatibility (about half of software packages require zero changes). ## Key trick: Leveraging the regularity of LLVM IR + invisicaps The speaker discovered that just after Clang generates LLVM IR but before optimization, the way pointer values are used is very regular: - Fields declared as pointers or references in source code correspond to the `ptr` type in LLVM IR; non-pointer fields correspond to integers or other types. - Therefore, all pointer operations can be identified at the LLVM IR stage, and each pointer can be instrumented with **invisicaps**. How invisicaps work: - Each pointer in the data flow is represented by two parts: - `int val`: the integer value of the pointer (visible and manipulable by the user). - Lower bound: invisible to the user, flowing with the pointer, stored in local data flow (registers). - Through the lower bound, a capability header can be found, which contains an upper bound and an ox word. - The lower and upper bounds of any allocated capability can never surround a "red"-marked region, so the user cannot modify the bounds. - When a pointer is stored in memory, the ox word points to an auxiliary allocation that holds the lower bounds of every pointer in that memory. This way, all pointer operations carry boundary information that cannot be tampered with, achieving memory safety. ## Compiler and runtime Fil-C is based on modifications to Clang/LLVM, inserting invisicaps at the LLVM IR stage. The runtime manages the capability headers, auxiliary allocations, etc. The speaker promised to demonstrate a real-world example (not elaborated in the transcript) but emphasized that performance is sufficient for everyday use. ## Summary Fil-C is a personal project that currently only supports Linux x86-64, but it has very high compatibility and acceptable performance overhead. It is a practical stepping stone toward memory-safe C/C++. **Source**: https://www.youtube.com/watch?v=5F-2Y1LPRek

Similar Articles

InvisiCaps: The Fil-C Capability Model

Lobsters Hottest

Describes Fil-C's InvisiCaps capability model for ensuring memory safety in C and C++ by tracking pointer permissions, while aiming for fanatical compatibility and reasonable performance.

Memory Safe Inline Assembly

Hacker News Top

Fil-C introduces memory-safe inline assembly, ensuring that programmer errors result in panics or traps rather than miscompilation.

The Fil-C Optimized Calling Convention

Hacker News Top

The Fil-C optimized calling convention ensures memory safety for C programs even under adversarial misuse, while maintaining efficiency by omitting safety checks in the common case. It explains the generic and register-passing optimizations that handle type violations via panics or well-defined behavior.

Practical Memory Safety

Lobsters Hottest

The article discusses the recent proposal for memory safety in Zig via Fil-C, compares Fil-C's definition of memory safety with Rust's, and argues that memory safety is a spectrum with practical definitions, using a concrete example where Fil-C is still unsafe.