RefinedC: Automating Foundational Verification of C Code with Refined Ownership
plv.mpi-sws.org
plv.mpi-sws.org
If you want something you can use with C code today, that has had many applications and integrates a little better IMO, then see Frama-C, the open source platform for extensible C verification:
One of the reasons C likely continues to play a large role in systems programming, despite regularly highlighted defects by researchers, is because new language designers have largely given up on concept of header files and forward declaration.
When a standards organization wants to work with hardware vendors to define a cross-platform interface in terms of human readable symbols rather than explicit values, with the possibility of many competing private translations, C is a natural choice because header files provide a necessary bridge or abstraction.
It would be interesting if a 'Better C' language was also a 'Better H' language and provided a literate interface declaration formats without macros or inline functions. Eliminating support for macros and inline functions from headers, and making inlinability a private implementation detail, should not theoretically prevent future compilers from inlining implementation code from multiple sources into a single unit as a performance optimization.
Instead it ties down C's popularity to the language's ability to separate interface from implementation via header files, and claims no other language can achieve that.
It also overlooks the downsides of header files (like unnecessary recompilation).
* Interop with every language.
* Existing codebases.
* Years of virtual platform excusivity in embedded systems, and OS.
* Momentum (people like to get into things that are popular).Reusable code. Your library written in C++ can't be called as easily from Python, PHP, Perl, C, Pascal, Rust, Go or any of the other languages people like to use.
Just do a search for uses of libffi and you'll get a pretty good idea why C is still more popular than C++.
Obviously you can make it work, and it probably makes a lot of sense for larger libraries where the advantages of working with C++ really pull their weight, but regardless, FFI is still one of the (admittedly fewer and fewer) niches where C shines.
Yes, you need to provide the C-like interface on the API boundary, but internally you can just use normal C++ for everything else. Sure, that C-like interface will not be as nice and comfortable as it would have been with C++ interface, but then again, neither it would be if you used C instead of C++.
> FFI is still one of the (admittedly fewer and fewer) niches where C shines.
No, it’s C linkage that shines, and C++ can use C linkage just fine.
And ensure that you catch every exception and turn it into an error code?
Edit: I suppose JavaScript + WebIDL would fit? Although nobody uses them, except browsers themselves.
This also makes its formal verification (SPARK dialect) nice because you can add pre and post-conditions to the interface without cluttering up the code body.
Ocaml's .mli files?
It reminds me of Google’s closure compiler-annotated JavaScript, where the ES4 type system was encoded in comments around the code. That was pretty frustrating to use, and switching to TypeScript where the types are actually part of the language was a significant improvement.
I suppose the benefit here is that you can annotate existing C code without re-writing it in a new language. Although I didn’t read enough to find out how well the refinement language can describe existing C coding patterns, which may not be provably safe. Similar to how type-safe JavaScript has to eschew certain control flows and meta programming, or null-safe Java has to conform to a certain style of programming to satisfy the null ness checker.
I salute the idea of fixing C shortcomings instead of starting over from scratch (Rust, Zig), but clearly this mix of large functional annotations on top of procedural code adds some burden and inelegance.
The automated formal code proving will appeal security researchers, but I doubt most developers will want to go through that.
As a developer, I would rather use checked-C since it's only a thin overlay requiring little syntactic sugar on top of C99. https://github.com/microsoft/checkedc
However, unlike RefinedC, it requires a new compiler and headers...
It focuses on bounds checking (that is a hard enough problem) and does not handle use after free for now.
[[rc::constraints("{s = {[n]} ⊎ tail}", "{∀ k, k ∈ tail → n ≤ k}")]]
APL meets GCC inline assembly syntax. A dream come true.At this point I wonder if it would be much more trouble to just port the code to Rust.
Still, if this is meant to be used by C coders it might be worth stooping to our level, many of us won't be comfortable with this mathematical notation. I know I'm not, and I know I'm not the most mathematically illiterate in general.
The thing is, experts struggle to verify C. This is an aid to experts so that C can be verified at all. Ease of use comes after that.
This looks interesting and offloading the actual proving to coq is a great idea. That allows them to not have to spend the time writing, verifying, and convincing others that their prover is correct.
A sibling commented that the annotations look complex, but what's being described is complex. Even if this were made a core part of a language, much of that complexity probably couldn't be elided.
[1]: https://page.mi.fu-berlin.de/prechelt/sw/crefine.3.0.tar.gz
Link with more info: http://plv.mpi-sws.org/rustbelt/