A simplified model of Fil-C shows how memory safety might be grafted onto C

What is Fil-C and why care?
It has been reported that Fil‑C pitches itself as a memory‑safe implementation of C/C++. That’s a bold claim in a world still haunted by use‑after‑free, buffer overruns and the occasional heartbleed. The original, production‑level Fil‑C allegedly performs a compiler pass that rewrites LLVM IR, but a recent simplified model — described in a blog post linked from Lobsters — demonstrates the core idea by rewriting C/C++ source instead. Easier to read, easier to grok.
How the simplified model works
The trick is surprisingly straightforward: every local pointer variable gets an accompanying AllocationRecord that tracks the allocation’s visible bytes, invisible bytes, and length. Simple pointer assignments are duplicated for the record pointer (p1 = p2 becomes p1 = p2; p1ar = p2ar). malloc is replaced by filc_malloc, which actually performs three allocations: an AllocationRecord, visible_bytes, and an invisible_bytes area that holds parallel records for heap‑stored pointers. Dereferences are guarded with bounds checks that use the AllocationRecord, and when a pointer value is itself loaded from the heap the model reads the accompanying AllocationRecord from invisible_bytes. It’s elegant in its bluntness.
Why this matters (and what’s left)
The emotional pivot here is obvious: the moment pointers travel from stack to heap, safety either breaks or must be enforced. Fil‑C’s model enforces it by carrying metadata alongside data — an approach familiar to sandboxing and fat‑pointer schemes, and a conceptual cousin to how Rust changed expectations about safe memory. Practical questions remain: performance cost, compatibility with raw casts, and how well the LLVM‑level implementation preserves semantics. But for anyone baffled by the full system, the simplified source‑rewrite model is a tidy bridge: understand this, and the compiler‑level machinery becomes a smaller leap.
Sources: corsix.org, Lobsters
Comments