Fil-C: Implementing Memory Safety for C Programs
Fil-C: Implementing Memory Safety for C Programs
Fil-C is a memory-safe implementation of C that aims to eliminate common memory-safety vulnerabilities by enforcing safety constraints at runtime. Unlike languages designed for compile-time safety, Fil-C focuses on transforming "garbage" (unsafe C code) into memory-safe execution.
Dynamic Runtime Enforcement vs. Compile-Time Safety
Fil-C enforces memory safety dynamically at runtime rather than detecting bugs at compile-time. This means that while a program with memory errors may compile successfully, it will error out the moment an invalid memory access is attempted during execution.
This architectural choice creates a fundamental difference between Fil-C and languages like Rust. While Rust uses a borrow checker to reject large classes of memory-safety bugs before the code ever runs, Fil-C allows the code to run until a safety violation occurs. As noted by community observers:
So apparently Fil-C enforces memory safety dynamically at run-time, rather than detecting these bugs at compile-time. A new language designed around memory safety, such as Rust, can reject large and important classes of memory-safety bugs at compile-time.
System Call Safety and Libc Integration
Fil-C achieves system-level safety through a custom libc implementation. The project claims that all syscalls are safe because they are handled by this custom library. However, critics point out that this custom libc eventually calls out to the system libc, where the underlying system calls remain inherently unsafe.
This has led to comparisons with Rust's approach to system calls. In Rust, making a raw syscall is considered unsafe, but using the Rust standard library provides a safe abstraction over those calls. Fil-C's approach of using a custom standard library to wrap unsafe operations is functionally similar to how safe Rust interacts with the system.
Technical Capabilities and Ecosystem
Fil-C has expanded its technical scope through several specialized implementations and ports. The project has demonstrated the ability to handle complex low-level operations while maintaining safety guards:
- Inline Assembly: Fil-C includes an inline assembly sanitizer to ensure that assembly blocks do not violate memory safety.
- Calling Conventions: The project has developed an optimized calling convention specifically for Fil-C.
- Context Switching: Fil-C has explored memory-safe context switching.
- Library Ports: Several critical libraries, including
freetype,fontconfig,harfbuzz, andgraphite, have been ported to Fil-C.
Performance and Resource Trade-offs
Implementing dynamic memory safety for a language as permissive as C involves significant overhead. Some critics argue that the "worse is better" philosophy is applied here, suggesting that the safety gains come at the cost of substantial performance degradation and increased memory consumption. Specifically, some users have suggested that the tool may make code significantly slower and more memory-intensive to achieve its safety guarantees.
Comparison with Hardware-Based Integrity
Fil-C is a software-based approach to memory integrity. It differs from hardware-level solutions, such as Apple's Memory Integrity Enforcement, which rely on specific CPU features to enforce safety. Fil-C's safety is achieved through software instrumentation and runtime checks, making it portable across hardware that does not have specialized memory-integrity instructions.