Author Topic: A (runtime) memory-safe C, Fil-C  (Read 4728 times)

0 Members and 3 Guests are viewing this topic.

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
A (runtime) memory-safe C, Fil-C
« on: November 05, 2025, 10:02:35 pm »
I know the person behind this project was hired at Apple to work on the JS garbage collector, a great working experience which I am sure inspired his C compiler
See here  :D :D :D

Ok, it's not memory safety at compile time (like Rust?), but it's a step head with C.


The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6456
  • Country: nz
Re: A (runtime) memory-safe C, Fil-C
« Reply #1 on: November 06, 2025, 01:16:56 am »
I've been wondering when this will get discussed here :-)  I've been playing with it for a few weeks.

In many cases, running Fil-C with -O1 gives very comparable performance to using GCC with -O0. E.g. on my primes benchmark on my i9 laptop:

     1964ms gcc primes.c -o primes -O
     3723ms fil-c primes.c -o primes -O
     3753ms gcc primes.c -o primes
    16334ms fil-c primes.c -o primes

Getting full (runtime) memory safety from unmodified C/C++ code -- at a really pretty low speed penalty -- is a pretty nice option to have, and a great alternative to the huge labour of a complete rewrite.

He's found a heck of a lot of serious packages work with zero modifications. And a lot more with very minor ones which I think could be described as fixing latent bugs.

2:1 slowdown on primes is actually getting towards the common worst case. Looking at his chart of slowdowns on thousands of different programs 4:1 is getting rather outlier and there is a huge cluster between 1:1 and 1.5:1.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: A (runtime) memory-safe C, Fil-C
« Reply #2 on: November 22, 2025, 01:19:19 pm »
I expected more interest in this topic...  :-//
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline 5U4GB

  • Super Contributor
  • ***
  • Posts: 1738
  • Country: au
Re: A (runtime) memory-safe C, Fil-C
« Reply #3 on: November 23, 2025, 09:13:40 am »
I think the problem is that for code that's engineered to be as safe as possible (e.g. MISRA) you're not getting much extra safety in exchange for using an experimental compiler.  OTOH for something that's traditionally been unsafe, say a web browser, you probably want to compile with all the optimisation you can get because those things are slow and bloated enough as it is.  So that leaves it as a cool proof-of-concept but a bit difficult to justify fitting into a real-world deployment.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6456
  • Country: nz
Re: A (runtime) memory-safe C, Fil-C
« Reply #4 on: November 23, 2025, 10:06:34 am »
you're not getting much extra safety in exchange for using an experimental compiler

It's Clang/LLVM, with just a little extra code added around pointer dereferences.
 

Offline 5U4GB

  • Super Contributor
  • ***
  • Posts: 1738
  • Country: au
Re: A (runtime) memory-safe C, Fil-C
« Reply #5 on: November 23, 2025, 10:29:53 am »
you're not getting much extra safety in exchange for using an experimental compiler

It's Clang/LLVM, with just a little extra code added around pointer dereferences.

Sure, but it's not mainstreamed into LLVM which means there's a risk development may stop at some point.  I have a machine with around half a dozen obsolete versions of LLVM installed that are (or at least were) needed to work with various safety/security tools whose development stopped at that version.  For example STACK needs LLVM 3.4 to work.  This has made me a bit gun-shy around such tools.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 6456
  • Country: nz
Re: A (runtime) memory-safe C, Fil-C
« Reply #6 on: November 23, 2025, 11:27:50 am »
you're not getting much extra safety in exchange for using an experimental compiler

It's Clang/LLVM, with just a little extra code added around pointer dereferences.

Sure, but it's not mainstreamed into LLVM which means there's a risk development may stop at some point.  I have a machine with around half a dozen obsolete versions of LLVM installed that are (or at least were) needed to work with various safety/security tools whose development stopped at that version.  For example STACK needs LLVM 3.4 to work.  This has made me a bit gun-shy around such tools.

It doesn't change the language. The absolutely worst thing that can happen is you go back to compiling with gcc or clang.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17788
  • Country: fr
Re: A (runtime) memory-safe C, Fil-C
« Reply #7 on: November 23, 2025, 04:30:04 pm »
you're not getting much extra safety in exchange for using an experimental compiler

It's Clang/LLVM, with just a little extra code added around pointer dereferences.

That's still in "experimental" stage and you don't know what this extra code could introduce in terms of bugs. Judging from a few of the reported issues ( https://github.com/pizlonator/fil-c/issues ), it looks far from being production-ready.

I personally agree with 5U4GB, I wouldn't trade a robust and standard compiler for something experimental. Unless, of course, for experimental use. No problem with that.

The performance hit seems pretty severe too, as expected. Yes, you said that it's probably not in real-life cases, but do we know? Are there actual benchmarks on real code? I suspect that it probably has a significant impact on compression and decompression code, which is ubiquitous.

I think (again my take here) that it may be more interesting as a test tool than as a "production" compiler. See what it's able to catch if anything, and fix code accordingly. There are actually tons of tools, both static and dynamic, that can do this, and I'm always surprised seeing how very few people use them.

Now, we know rewriting software has a high cost and almost invariably introduces a whole series of new bugs, so keeping code as is and using a different compiler producing "safer" executables looks like a reasonable idea. But it has been tried before and has never caught on, so, we'll see (I wouldn't bet a dollar on Fil-C, but that's just my opinion at the moment).

One thing that should IMO be integrated into compilers for ANY language is to force developers to add input validation of every single function (with a possibiity to escape that for specific performance reasons with extra keywords, making it annoying enough not to be "default"). Of course, that's a different approach, not a "drop-in" replacement: that would require writing better code and re-writing existing code that doesn't comply. The lack of input validation accounts for a gigantic proportion of bugs in general and security-related bugs in particular. I don't even quite remember the last time when I saw a security report that wasn't linked to a lack of input validation.
 
The following users thanked this post: 5U4GB

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 11216
  • Country: fi
Re: A (runtime) memory-safe C, Fil-C
« Reply #8 on: November 23, 2025, 06:18:28 pm »
One thing that should IMO be integrated into compilers for ANY language is to force developers to add input validation of every single function (with a possibiity to escape that for specific performance reasons with extra keywords, making it annoying enough not to be "default"). Of course, that's a different approach, not a "drop-in" replacement: that would require writing better code and re-writing existing code that doesn't comply. The lack of input validation accounts for a gigantic proportion of bugs in general and security-related bugs in particular. I don't even quite remember the last time when I saw a security report that wasn't linked to a lack of input validation.

Yes. Input validation related bugs are common because input validation is a lot of work - and not just implementation work or boilerplate, but actual design work. People are lazy so they don't do it. Since early 1990's language designers have been promising languages that somehow make this easier and automatic, and result is that input validation is still not being done - because it cannot be automated. Yet people want to believe that stuff like exceptions or memory safety somehow even relates to input validation (which it doesn't), or even worse, believe it solves input validation somehow so that they don't have to think about it.

Result is that programs still
A) do wrong things (logically), which can be serious, including security issues
B) crash, which is also serious, downtime can be costly.

All that is needed is designing in proper input validation. Which takes time and effort, but can't be avoided. Main purpose is to prevent logical misbehavior and crashes. As a side effect, those nasty memory corruption bugs people like to talk about also basically just vanish.
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 4841
  • Country: us
Re: A (runtime) memory-safe C, Fil-C
« Reply #9 on: November 23, 2025, 09:18:28 pm »
To me the big obstacle here is (aside from the experimental nature) is the lack of compatibility with anything else.   It's an ABI breaking change that can't really interoperate with anything else. 

That, plus the performance hit I guess would make it a hard sell for many applications.  While the most attractive applications are likely either using development techniques that reduce the impact or are better served by using other languages.

One are where something like this could be useful is fuzz testing.  This looks much faster than UBSAN and valgrind, and catches more errors than valgrind.  So if you have a particular module you want to extensively fuzz test you could use this compiler.
 

Offline Marco

  • Super Contributor
  • ***
  • Posts: 7749
  • Country: nl
Re: A (runtime) memory-safe C, Fil-C
« Reply #10 on: November 24, 2025, 02:11:51 am »
Yes. Input validation related bugs are common because input validation is a lot of work
Design by contract and not using text based API's get you most of the way there. Text based API's being broken by design is one of the least recognised major sources of exploits.

SQL is wrong, shell is wrong, html is wrong, printf is wrong, etc. Passing them strings from untrusted sources is too failure prone for humans to handle.

https://cs.ru.nl/E.Poll/papers/strings2018.pdf
Quote
Since early 1990's language designers have been promising languages that somehow make this easier and automatic, and result is that input validation is still not being done - because it cannot be automated.
A couple huge exploits in VPN software in recent years were caused by a web monkey being just too plain lazy to use prepared statements (some might say the problem was the lack of input sanitation, but that's confusing the symptom with the disease). The automation was there, the willingness of management to tell them to always do it the annoying way was not.
Quote
All that is needed is designing in proper input validation. Which takes time and effort, but can't be avoided. Main purpose is to prevent logical misbehavior and crashes. As a side effect, those nasty memory corruption bugs people like to talk about also basically just vanish.
The get good method. Doing that consistently is of course for lesser mortals who mistakes, if you're really good you can only do it where necessary.
« Last Edit: November 24, 2025, 02:17:09 am by Marco »
 
The following users thanked this post: Siwastaja

Offline 5U4GB

  • Super Contributor
  • ***
  • Posts: 1738
  • Country: au
Re: A (runtime) memory-safe C, Fil-C
« Reply #11 on: November 24, 2025, 02:52:00 am »
One thing that should IMO be integrated into compilers for ANY language is to force developers to add input validation of every single function (with a possibiity to escape that for specific performance reasons with extra keywords, making it annoying enough not to be "default").

There have been attempts in the past to create tools that do taint-tracing, so the tool will tell you where potentially attacker-controlled data will end up.  They've been distributed as patches to a particular compiler version (see my previous post about needing to maintain ancient compiler builds) with academic-quality code (works on all three test cases presented in the paper, with the authors mostly being able to understand the diagnostic output if they squint at it just right), so enough to get the conference paper published and that's it.  Development then stopped once the paper was published.

It's a pity because every now and then you see tools pop up that go beyond the standard static source code analysis or dynamic checking (valgrind, fuzzers), but they never get past the proof-of-concept stage.
 

Offline 5U4GB

  • Super Contributor
  • ***
  • Posts: 1738
  • Country: au
Re: A (runtime) memory-safe C, Fil-C
« Reply #12 on: November 24, 2025, 02:54:24 am »
One are where something like this could be useful is fuzz testing.  This looks much faster than UBSAN and valgrind, and catches more errors than valgrind.  So if you have a particular module you want to extensively fuzz test you could use this compiler.

+1, it'd be cool to see it integrated into AFL or similar.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: A (runtime) memory-safe C, Fil-C
« Reply #13 on: November 24, 2025, 01:20:26 pm »
It's Clang/LLVM, with just a little extra code added around pointer dereferences.
[...]
It doesn't change the language. The absolutely worst thing that can happen is you go back to compiling with gcc or clang.

In fact, and as it doesn't change the C language it can be used to cook a whole GNU/Linux stage4: experimental, but usable  :D

Comparing this compiler with my toy "myC" , well... at least the "Fil-C" compiler is based on a tested framework, while mine is written from scratch from the lexer up, and doesn't require completely rewriting your sources to comply with a more rigid syntax.

myC accepts nothing more than a subset of C/89, which must be strictly MISRA-C/95, with some modifications -> It cannot be used to "cook" any gnu/linux rootfs, as each source must be modified first.

At runtime, thanks to fact that types are monads, the compiler then adds checks not only on the valid range of a pointer, but also on the range of any type -> excellent way to catch bugs!

It makes the binary code 4 times heavier (worse than gcc -o0) and 5 times slower (but better than any instrumentation code). But that's not a problem, since its job is to help squash bugs.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Marco

  • Super Contributor
  • ***
  • Posts: 7749
  • Country: nl
Re: A (runtime) memory-safe C, Fil-C
« Reply #14 on: November 24, 2025, 02:33:11 pm »
I expected more interest in this topic...  :-//

It's not a system programming language any more, it's cute but has little use case. For anything old suddenly introducing GC/RC is mostly unacceptable, for anything new it's competing with Go and C# ... and going to lose.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 17788
  • Country: fr
Re: A (runtime) memory-safe C, Fil-C
« Reply #15 on: November 24, 2025, 04:04:44 pm »
Yes. Input validation related bugs are common because input validation is a lot of work
Design by contract and not using text based API's get you most of the way there.

Design by contract is a good thing that unfortunately got too little traction. Of course, it's in Ada and was in Eiffel before that. I don't think Rust has this as a core feature? (Unless I missed it.) Just saw some people came up with "crates" to emulate contracts, which looks kind of like a band-aid.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: A (runtime) memory-safe C, Fil-C
« Reply #16 on: November 24, 2025, 04:22:01 pm »
I expected more interest in this topic...  :-//

It's not a system programming language any more, it's cute but has little use case. For anything old suddenly introducing GC/RC is mostly unacceptable, for anything new it's competing with Go and C# ... and going to lose.

In my opinion, Fil-C has all the potential to compete with Rust.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Marco

  • Super Contributor
  • ***
  • Posts: 7749
  • Country: nl
Re: A (runtime) memory-safe C, Fil-C
« Reply #17 on: November 24, 2025, 04:32:29 pm »
Rust appeals to language nerds and is a system programming language (ie. not dependent on GC/RC). Neither is true for Fil-C.

Swift embedded is a bigger competitor, with non copyables and borrow checking.
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 4841
  • Country: us
Re: A (runtime) memory-safe C, Fil-C
« Reply #18 on: November 24, 2025, 04:37:00 pm »
One thing that should IMO be integrated into compilers for ANY language is to force developers to add input validation of every single function (with a possibiity to escape that for specific performance reasons with extra keywords, making it annoying enough not to be "default").

I don't know what that would even look like.  The problem with input validation is that valid input is if you are lucky in the intent of the developer, but let's be honest the biggest bugs come when the developer is mistaken about what constitutes valid input.  Invalid input handling is even harder than validation itself.

It's obviously important an a lot of tools have been developed to help with it.  I just don't know how you make it a generic compiler check and still be useful.  One of the main goals of OOP,  especially as implemented in say C++ is that after construction an object is supposed to be valid, and and stay valid for the lifetime of the object.  Of course valid as "internally consistent" is not the same thing  as "usable for my current purpose" and even then, maintaining useful meanings of valid is not always possible.  At least you can often use it to force error handling when trying to manipulate an invalid object.

Languages with Error/Maybe return types can force you to explicitly check if a return object exists and prevent accessing it if it's not valid but they can't force you to do something sensible if it's not.

Languages with memory safety features can prevent you from accessing an invalid pointer or out of bounds access.  But again there are lots of other ways input can be invalid that cant be detected.

C++ tried to implement one of the more powerful input validation systems in the form of contracts, which give explicit syntax for pre- and post- condition checks, but I'm not sure how useful it really is going to be.  I somehow doubt that if you made a rule "every c++ function must specify at least one pre-condition that references each input value" that it would meaningfully improve things beyond what other languages get by default.
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 4841
  • Country: us
Re: A (runtime) memory-safe C, Fil-C
« Reply #19 on: November 24, 2025, 04:55:34 pm »
In my opinion, Fil-C has all the potential to compete with Rust.

Why?  How?  The overhead is much worse than rust, and the guarantees are basically the same.  The major difference is that fil-c does runtime checking which obviates the need for "unsafe" overrides but defers detecting detectable errors.

If they can make fil-C play nicely with other languages (it's totally unclear to me if that's possible) the it could be a nice way to check existing code, but if you want that kind of protection I don't know why you wouldn't use a language that does so with less overhead and earlier detection of errors.

IMHO, the languages that have a much better approach than rust are chandlar caruth's Carbon and herb sutters cpp2.  These languages preserve extremely high levels of compatibility with unchanged C/C++ code, and heavily leverage existing developer knowledge while letting you develop new code that easily uses the "best practices" that we have learned over the last 30 years.  They both avoid my main complaint about rust that its developers think they need to reinvent absolutely everything.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: A (runtime) memory-safe C, Fil-C
« Reply #20 on: November 24, 2025, 06:48:17 pm »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline 5U4GB

  • Super Contributor
  • ***
  • Posts: 1738
  • Country: au
Re: A (runtime) memory-safe C, Fil-C
« Reply #21 on: November 24, 2025, 10:40:54 pm »
Speaking of Carbon and many similar ideas, it's like roleplaying games in the 1980s, almost everyone who played them at some point thought "you know, this system has a number of problems, I bet I could do a better one!", after which they'd spend anything from a few weeks through to months and occasionally even erratic effort over years futzing around with their new improved universal system that got more and more complex as it progressed (or failed to) until eventually enthusiasm waned and it fell by the wayside.  My nephew goes out RPG'ing every week or two and do you know what he plays?  D&D, the Dartmouth BASIC of RPGs.  I don't know how he'd even find anyone playing the fancier systems, and none of the revolutionary we-can-do-it-better-ourselves ones have survived.
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: A (runtime) memory-safe C, Fil-C
« Reply #22 on: November 25, 2025, 03:27:59 pm »
In my opinion, Fil-C has all the potential to compete with Rust.

Why?  How?  The overhead is much worse than rust, and the guarantees are basically the same.  The major difference is that fil-c does runtime checking which obviates the need for "unsafe" overrides but defers detecting detectable errors.

If they can make fil-C play nicely with other languages (it's totally unclear to me if that's possible) the it could be a nice way to check existing code, but if you want that kind of protection I don't know why you wouldn't use a language that does so with less overhead and earlier detection of errors.

IMHO, the languages that have a much better approach than rust are chandlar caruth's Carbon and herb sutters cpp2.  These languages preserve extremely high levels of compatibility with unchanged C/C++ code, and heavily leverage existing developer knowledge while letting you develop new code that easily uses the "best practices" that we have learned over the last 30 years.  They both avoid my main complaint about rust that its developers think they need to reinvent absolutely everything.

Makese no sense.
Fil_C is "C", and it's an attempt to improve C and does not need to play anything with "other languages".
In my opinion, the overhead is not that worse than Rust
The Fil_C also implements a garbage collector.
This may be a problem for things like "Kernels" and "embedded stuff".
But you can disable it.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 5098
  • Country: gb
Re: A (runtime) memory-safe C, Fil-C
« Reply #23 on: November 25, 2025, 03:36:01 pm »
Speaking of Carbon and many similar ideas, it's like roleplaying games in the 1980s, almost everyone who played them at some point thought "you know, this system has a number of problems, I bet I could do a better one!", after which they'd spend anything from a few weeks through to months and occasionally even erratic effort over years futzing around with their new improved universal system that got more and more complex as it progressed (or failed to) until eventually enthusiasm waned and it fell by the wayside.  My nephew goes out RPG'ing every week or two and do you know what he plays?  D&D, the Dartmouth BASIC of RPGs.  I don't know how he'd even find anyone playing the fancier systems, and none of the revolutionary we-can-do-it-better-ourselves ones have survived.

well ... improving C@KISS(1) is no easy feat; every branch of development could contribute something, or contribute nothing at all.

(1) and there's always the risk of betraying the initial "KISS philosophy" ...
and generating very complicated things
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 4841
  • Country: us
Re: A (runtime) memory-safe C, Fil-C
« Reply #24 on: November 25, 2025, 07:36:55 pm »
Makese no sense.
Fil_C is "C", and it's an attempt to improve C and does not need to play anything with "other languages".

Maybe in your world.  In the real world C is used to build libraries called from other languages, and has to call external code as well.   Fil-C implements some of those for you such a system calls, and does provide a foreign function interface that can be used for some purposes (they suggest constant time crypto primatives) but it comes with a bunch of warnings. 

Quote
In my opinion, the overhead is not that worse than Rust

That's not an opinion it's an incorrect fact.  If you need the memory integrity guarantees of Fil-C, you care about performance, and you are writing new code I can't imagine choosing Fil-C over rust for technical rather than political reasons.  The big advantage Fil-C has is the ability to keep using existing battle tested code with a tolerable overhead.


Quote
The Fil_C also implements a garbage collector.
This may be a problem for things like "Kernels" and "embedded stuff".
But you can disable it.

The GC is fine, but as it stands Fil-C can't be used for embedded development and I doubt will be adapted to do so.  First off, right now it only supports 64 bit platforms with a full hosted libc.  Looking over the implementation, it looks like it could be adapted to 32 bit, and maybe with a free standing implementation, but it relies on malloc pretty heavily.

As it stands it would need a way to run unsafe code in an operating system or embedded platform in order to do hardware access.  That could obviously be added to the runtime in the same way that the runtime currently provides a syscall wrapper but that would require a major change to embedded software that currently assumes it can just cast a hard coded integer to a pointer and start poking hardware registers.

Memory overhead would be a big issue on embedded platforms as well.  Every data structure that exists in memory (including on the stack, but excluding purely local variables) that ever contains a pointer ends up with a dynamically allocated shadow object of equal size that contains the capability information.  Note that this means that a 1024 byte stuct with a single pointer has an entire 1024 byte shadow object.  Those objects are lazily allocated with malloc, and while you could statically allocate them, then a great many more objects would have that overhead.  I'm pretty sure this would be a complete non starter for most freestanding embedded applications.

Finally, if you are already required to confirm to something like MISRA, the benefits of the memory protection afforded by either Rust or Fil-C are not that big.  Especially Fil-C with it's focus on runtime checking is really targeting applications where runtime panics are considered acceptable.  The real focus is providing protection from security vulnerabilities caused by memory corruption, not ensuring correct opeation.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->