Death To C

Jon Evans is the CTO of the engineering consultancy HappyFunCorp; the award-winning author of six novels, one graphic novel, and a book of travel writing; and TechCrunch's weekend columnist since 2010.

Ladies and gentlemen, the C programming language. It’s a classic. It is sleek, and spartan, and elegant. (Especially compared to its sequel, that bloated mess C++, which shares all the faults I’m about to describe.) It is blindingly, quicksilver fast, because it’s about as close to the bone of the machine as you can get. It is time-tested and ubiquitous. And it is terrifyingly dangerous.

But don’t take my word for it. Take the word of living legend John Carmack:

Found two pointer-to-out-of-scope-stack bugs today. I like tight native code, but C/C++ still makes me worry a lot.

If you write code in C, you have to be careful not to introduce subtle bugs that can turn into massive security holes — and as anyone who ever wrote software knows, you cannot be perfectly careful all of the time. (This is especially true in C; it’s so easy to write impenetrable, incomprehensible C that it has become a competitive sport.)

In principle, as software evolves and grows more mature, security exploits should grow ever more baroque, in the same way that plane crashes are getting weirder and weirder. We learn from previous crashes, and fix those problems, and “as the obvious fixes are found, we discover less and less likely ways that things can go wrong.”

And this is indeed the case for much of today’s software. Look at a few prominent recent exploit discoveries. A side-channel attack to read L3 caches via Javascript. The mindboggling “Rowhammer” attack, which relies on the fact that

As DRAM manufacturing scales down chip features to smaller physical dimensions, to fit more memory capacity onto a chip, it has become harder to prevent DRAM cells from interacting electrically with each other. As a result, accessing one location in memory can disturb neighbouring locations, causing charge to leak into or out of neighbouring cells. With enough accesses, this can change a cell’s value from 1 to 0 or vice versa.

and. astonishingly, turns that fact of hardware life into a totally viable attack vector.

But this is not the case for software written in C/C++. Buffer overflows and dangling pointers lead to catastrophic security holes, again and again and again, just like yesteryear, just like all the years of yore. We fail to learn. Heartbleed. GHOST. The Android 4.3 KeyStore. Etcetera, etcetera, etcetera.

C was and is magnificent, in its way. But we cannot afford its gargantuan, gaping security blind spots any more. It’s long past time to retire and replace it with another language.

The trouble is, most modern languages don’t even try to replace C. They’re vastly more abstract. They’re easier to read. They provide programming constructs which are enormously powerful if you’re dealing with vast quantities of data, or multiple concurrent threads and processes, or distributed systems. But they’re not good at the thing C does best: getting down to the bare metal and working at mach speed.

Historically, programming languages have had a tradeoff: you can have a language which is safe, but you give up control, or you can have a language with control, but it is unsafe. C++ falls into that latter category. More modern C++ is significantly more safe than it used to be, but there are fundamental aspects of C++ which make it impossible to ever be truly safe. Rust attempts to give you a language with 100% control, yet be absolutely safe.

So please, low-level programmers of the world, I beseech you (while, to be clear, also respecting you immensely): for your next project, try Rust rather than C/C++. There is no longer any good reason for today’s software to be as insecure as it is. Those old warhorses have served us well, but today they are cavalry in an era of tanks. Let us put them out to pasture and move on.