If you actually care about memory safety—which you should, as the CVE list shows—then why not use an actual memory-safe language?
If you actually care about memory safety—which you should, as the CVE list shows—then why not use an actual memory-safe language?
> If you actually care about memory safety ... then why not use an actual memory-safe language?
Many teams are stuck with established codebases that they can't afford to re-write entirely from scratch.
I think the proposal in the article is an interesting point on a continuum of mitigations for C, spanning from the really weak and/or hacky (but cheap/easy) all the way up to safe systems languages like Rust and Ivory. Other points on this continuum include Cyclone [1], SAFECode [2], and the fat pointer approach in Cello [3].
[1] http://cyclone.thelanguage.org/
Automatic translation (assistance) from native C to SaferCPlusPlus is being worked on. And if you'll permit me to gripe a little here - you might think it's a reasonable undertaking, until you start contemplating code like this:
int **var1 = (int **)malloc(20);
var1[2] = (int *)malloc(10);
int *var2 = var1[2] + 4;
var2--;
free(var2 - 3);
free(var1);
:)[1] https://github.com/google/sanitizers
[2] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus
You don't have to. Most alternative can call compiled C libraries. Rust can.
Perhaps there's a place in this world for both approaches?
Take in account how many can't even consider the possibility that a full OS can (and have be made before) safer, have GC, is NOT C, is NOT EVEN ALIKE C, etc.
C, C++, Unix are the biggest roadblock in the progres of computing. Or more exactly, the users, that prefer patch-along and commit million of dollars in wasted effort than in build (or rediscover) better ways.
This is alike climate change resistance. Why go solar, if carbon is better and well understood? Instead, push ahead and waste money fixing symptoms instead of causes.
And "causes" is a word that here mean, C, C++, Unix, etc...
There are legitimate use cases for C. If you're writing low-level, bare-metal programs then there is no other portable programming language that offers better semantics. C programmers often laud that language because they can easily reason what the output of the compiler will be. That is an extremely important and rare property for a portable programming language.
But hey, don't listen to me, listen to an actual experienced C programmer: https://youtu.be/MShbP3OpASA?t=20m45s
They certainly do, and in doing so, conveniently forget all the instances of their compilers surprisingly deleting invalid code as optimization because it inadvertently depended upon undefined behaviour.
Of course something must be use to fill the niche C have. But is clear that exist a huge resistance to fill it with something better, to the point that anything is almost dismissed and the only "valid" answer is continue with C (or C++, or Unix, or Old-School Terminals).
Probably you have see
https://www.destroyallsoftware.com/talks/a-whole-new-world
Is not hard to imagine that better/improved tools must have arise in all this decades. In contrast, we (as community) are stuck in more or less the same things and maybe even devolving in some areas.
Because it's not as mature, and doesn't support as many platforms. Those things are very important to me, and there is no steel thread for them.
I imagine that in twenty years, it could be worth talking about rust as an alternative, but rust is only two years "stable", and it's unclear what the language, the tooling and the libraries are going to look like in that time.
Meanwhile, I have software I wrote 20 years ago in C that still runs, correctly, and on the Internet, generating income, and a big part of the reason why is that C was already more than twenty years old at that point.
But WHY in 20? With this thinking NEVER WILL BE IMPROVED THE SITUATION!
And I don't mean you, I mean the whole industry.
Obviously stability and compatibility is important, but is not this almost like the COBOL problem? Nobody try to move out from COBOL because "maybe in the far future a solution will emerge" and the the future get here, and we are decades LATE?
And RUST is not the only viable alternative. Ada, Pascal, Oberon, Modula (to name the family of languages I know more, but is likely some lisp and others exist too) where already there (decades ago) without break too much from the C mindset (and go crazy with monads and stuff like that).
So, because look like without {} a system language have not chance in hell, take oberon and put the C syntax? And them we are not waiting 20 years in the future for it.
But this will fail, for the same reasons that renuevable energy will fail against carbon:
The community will not accept the costs in the short-term, not matter how much things could improve later...
P.D: And what if a "rust-alike" lang but trans-piling to C, like with Nim?
Or even better:
C2 (C with improvements and eliminating as much baggage as possible) trans-piling to C. Eventually this will allow to bootstrap and still keep a way to old code bases...
C has all these. Only C/C++ and Ada have these.
People who say "C is not a safe language" may not be aware, but most of the worlds safety critical code is written in C or ancient C++. Most aerospace, military and medical applications are written either in C/C++ or Ada. Ada would be much safer than C, but it has been abandoned for C/C++ because language of choice is not that important.
If the culture and tooling to write safe code is not there, changing language is not going to help. It's currently easier to write safe code in C than it's to write safe code in your favorite 'memory safe' language like Rust.
Analysis tools for C exceed anything you can have in Rust or Go compiler in scope and features.
Having external tools to track out of bonds errors, use after free, double free, free bad pointers, implicit conversions and UB, errors that don't happen in another languages is band aid.
Other languages just don't need them thanks to being designed with safety first.
Other languages are not used for writing safety critical code. Language features are not even close being enough for that.
No need to defensively boast if you realize that you are wrong.
The band-aids called MISRA-C, Frama-C, High Integrity C++ and DOD certifications are a mechanism to force Ada safe like semantics in C and C++, while paying lower salaries, instead of hiring Ada devs.
F-35 proves how good they work out in large scale projects.
These tools exist since 1979, it hasn't changed anything.
C doesn't deserve a place on any security conscious developer toolbox.
Really? I had a look at the code and I would agree with the basic idea of eliminating errno and always using the return value.
> If you actually care about memory safety—which you should, as the CVE list shows—then why not use an actual memory-safe language?
Following the logic here, you seem to be implying that no-one except the irresponsible should use C.
There are some platforms (such as embedded systems) where C really is the only choice. But if you do have a choice? Then I don't think using C is a good idea.
I'm not sure if "irresponsible" is the right word, though. I think developers underestimate the risks of C's unsafety and/or overestimate their ability to properly deal with it. Hanlon's razor[0] applies.
Much of the software that we all currently rely on is in C, for example all of the common operating systems are in C, and the reliability of these operating systems shows very clearly that C is nowhere near as inherently dangerous as you claim it to be.
That's never true. You can always use a higher-level, safer language that can compile to C. The result is C code but you never write it & avoid its pitfalls. Ivory language in Haskell, Ada-to-C, and Modula-2-to-C come to mind. Alternatively, you can use something even more primitive in a C subset or native assembly that it compiles to. OcaPIC or JavaCard come to mind. Astrobe Oberon is another for safe, low-level coding but not sure how its compiler works.
"This boot-loader, unfortunately, did not support loading any kernel images larger than 4 megabytes. This turned into a problem very quickly as it turns out that rustc is far less adept than gcc at creating succinct output. In fact, I was hitting this problem so early I was barely able to make a “Hello World” before having to stop working on rust code. Fixing this problem required rewriting most of the early boot code, all of which was x86 assembly ..."
This seems highly likely, yes.
C was a good language at the time. It's still probably a very good teaching language for systems programming. But it's a bad language for anyone who wants to write software that needs to be used responsibly. It predates the entire idea that some people on the network might be hostile. It predates the knowledge that buffer overflows might be used for malice. It predates about 40 years of programming language research and security research, some of which has even shown results.
C also predates computers of modern speed; it was written at a time when interpreted languages were mostly unthinkable for serious software. There's no reason that, say, the manpage rendering tools (the most recent thing I had half a mind of exposing to the network) would be written in C today, but it was presumably the best tool for the job at the time.
It is no criticism of C to say that it has served us well but it is a bad choice for new software for clear and objective reasons.
There were already powerful computers than the PDP-11, with more saner languages.
Someone called Kristaps Dzonsons wrote a manual page renderer and a cgi/fastcgi library in C quite recently.
Although Rust shows a lot of promise, Ada has a proven track record of use in safety critical applications such as avionics and railways.
So you can make the C safe or get rid of it. However much work you want to put in.
Five years from now? Probably a number of them. You've been able to write in Go with no standard library for years. There's a project to avoid it in Rust. There are lots of active kernel development projects. Do you want your software to continue to be written in C with a kernel and standard library in safe languages?
And why does it matter to you to avoid improving your code until it's possible to run on an all-safe stack? It is as if it is 1990, and you are asking, why should I license my code as free software? How much can I run on a free C library and a free kernel?
C only became relevant outside UNIX around the late 90's.
MS-DOS was written in Assembly, just like any application where performance mattered.
CRUD applications were mostly written in an xBase dialect, with Clipper being the prominent one.
Turbo Pascal, Turbo C, Turbo C++, Turbo Basic, Quick Basic, Quick C, Quick Pascal.... All of them had plenty of users.
I own MS-DOS system programming books, with examples in Assembly, Pascal, Basic and C for both Microsoft and Borland variants.
Those languages were the "Unity" of the 80 and 90's.
Real games were 100% Assembly.
This only started to change with the adoption of Watcom C, as it could generate relatively good code and use a DOS 32 bit Extender.
There is a good reason why Visual Basic is still alive.
More like "most C implementations do not offer memory safety by default". This is unrelated to the language per se, it's like for example calling Scheme unsafe because an implementation could have set-cdr! on '() write on random memory. It can be applied to any language.
(1) Once you have a formally defined semantics, undefined behavior is no big deal, because you have the tools to prove its absence in whatever program you're writing.
It what ways is it unsafe? Thinking about the examples you'll cite, can the programmer introduce checks and safety nets to overcome them? For example, you'll no doubt mention buffer overflows, but can these be protected against?
The simplest example here is the one the Safe C Library is about: it's very hard in C to talk about memory buffers that know their own capacity. C wants you to think about pointers, often with implicit lengths (memcpy takes a single size parameter, strcpy takes none, tmpname takes none, etc.). You can write a library where you pass lengths alongside every pointer. But you've got to keep track of two variables for what should conceptually be a single variable.
Now, one approach is to make a struct buffer {char *ptr; size_t len;}. But then you run into C's problem that it has no encapsulation or operator overloading. You can't index into a buffer; you can call a function that checks the length, or you can just do the tempting thing of ->ptr[i], which you'll get wrong at some point. The compiler won't help you notice that you got it wrong.
And even if you do that, the C standard library is full of the unsafe approach to pointers. If you scrupulously avoid all functions that use unsafe pointers, you've also got to avoid the C standard library as well as almost all third-party libraries. This is not what most people think of when they think of using C.
C++ (and especially C++11 with good discipline) is a very good step forward in the direction of making C more safe, in no small part because C++ has its own standard library and the entire ecosystem tends to use that standard library. Due to the desire to be backwards-compatible with C, C++ retains a lot of unsafety, but it makes safer paradigms possible. If you're not bound to backwards-compatibility, though, there's probably no reason to voluntarily take the burden of dealing with the things that are unsafe in C.
A "fat" pointer. That's essentially what the Cello project does [1]. The author has pulled together some crazy hacks to make this approach accessible in C. Including, apparently his own version of many standard library routines. Crazy, but very interesting. Discussed on HN yesterday/today: https://news.ycombinator.com/item?id=14091630
However, there also are plenty of cars that safe drivers will refuse to drive. You don't need crumple zones, safety belts, etc. in a car you will never drive.
There are no unsafe nuclear launch buttons, only unsafe nuclear launch button pushers.
Hmm, maybe some buttons should be harder to push...
I would like to apply the same principle to the language I program computers in. Make it the computer's job to minimize mistakes - it might not be perfect, but it's definitely better than I am!
And who develop the languages? Coders.
Ergo, exist unsafe languages.