It's not the language, it's the tools.
Add a static analyzer pass to each C/C++ compiler which is switched on by default. Add clang-address-sanitizer-style code when compiling in debug mode, and also offer runtime checks as option for release-compiled code. Both combined would have caught 99% of memory safety issues that pop up now and then.
If necessary extend the language with optional ownership keywords a'la Rust, and allow me to switch off features I don't require to reduce complexity.
Most important of all: provide options that I don't need to pay at runtime for memory safety with precious CPU cycles.
1) every language has hoops to jump through to make them safe (e.g. garbage collection does not protect you from memory leaks) [1]
2) every 4-5 years or so someone comes out with a programming language/system* [2] (rust, go at the moment) that fixes it all and "encourages good practices" - and then the good practices change (e.g. microservices are making their second round. They're good for sysadmins/sres and very bad for programmers (because you have to serialize/deserialize everything and changes to the system propagate into potentially dozens of separate programs - and God help you if they're maintained by different departments)). I wonder what's next ? Data-oriented programming is the perfect solution for the problems of microservices, so that could be next I guess.
* they may call it programming language, they may call it a system. Of course, it's always both.
[1] https://www.youtube.com/watch?v=ydWFpcoYraU [2] Forth, C, COBOL (/mainframes), Pascal, C++, Oberon vs Modula-2, dBase (and it's competitors), Object Pascal/VB (the built-in database approach), Perl, Java, .Net, and now here Go/Rust
There's always a trade-off between performance and security, but with better tooling support the price for secure code will be very low. Right now security is bad because we look at security as a feature. As something that is added to a project, instead of as something that guides the entire design.
Your suggestion that static analysis can fix this is wildly optimistic, because C/C++ code for a modern browser uses memory pools, pointer arithmetic, just-in-time compilation, and shared memory between object instances, threads and processes and so on. It's hugely complex, and correctness can't be verified with some sort of static analyzer or with added runtime checks.
Wrong. You can write perfectly safe code in C++. You seem to have this ridiculous idea that pointer arithmetic is mandatory on C++. "Pointer arithmetic" is not a feature of C++. It's a feature of how computers work. C++ allows you to do it if you want. Memory pools are not a C++ feature, memory pools are part of how a modern computer and OS works. You know, memory doesn't appear magically in your program.
> Rust forces programmers to indicate ownership and lifetime of memory
So like C++ with unique_ptr, shared_ptr, and RAII?
Also I wanted to say that some of you keep mixing C and C++, calling them "C/C++". They're two different languages.
You can't write safe code in any Turing complete language. That's the whole point of Turing completeness. The only reason why memory attacks are as common as they are is because C like languages are the most popular ones.
If we replaced everything written with C to a "safe" language like, I don't know Haskell?, we'd have just as many zero day exploits of the monads within programs.
Then you've picked the wrong profession. You write that like it was a fact, while it's obviously nothing more than a lack of skill (and maybe knowledge) on your side.
If I chose a language primarily because it's 'safe', that would mean that either I'm pretty bad at writing safe code, or that I'm just unnecessarily lazy.
This really cuts to the core of ideological differences between C/C++ and Rust camps. C/C++ programmers tell the compiler trust me, while Rust programmers say check me. I can't help but feel to a degree the Rust ideology is superior. To make by bias clear I work in C, and write in Rust in my spare time.
Safer systems programming languages were already available outside AT&T when C was born. Rust is just the latest addition to them.
The correctness invariants of complex C++ programs (such as browsers and JITs) cannot be 'discovered' by static analysis - they must be, at least in part, supplied by the programmer.
C and C++ were not designed to allow programmers to specify such invariants (and have them automatically checked). I am not convinced that introducing them can be done in a clean way.
In French, your first line would be, "Oh, hell no!"
It is used for that exact memory control and access that this article demonizes so that we can have efficient and thought out systems.
When those systems aren't well thought out or secure you have security issues. C/C++ lets you build a wobbly treehouse _and_ a secure fortress. It is up to the developer which one is made...
C and C++ are used due to UNIX becoming widespread, opening the door to those languages in the industry, and killing safer systems programming languages in the process.
The majority of security exploits in C and C++ aren't possible in Modula-2, Ada, Algol, just to cite a few examples.
To quote Hoare on his award's speech, The Emperor's Old Clothes:
"Many years later we asked our customers whether they wished us to provide an option to switch off these checks in the interests of efficiency on production runs. Unanimously, they urged us not to - they already knew how frequently subscript errors occur on production runs where failure to detect them could be disastrous. I note with fear and horror that even in 1980, language designers and users have not learned this lesson. In any respectable branch of engineering, failure to observe such elementary precautions would have long been against the law"
There are a few legendary developers in the world I would trust to write secure C/C++. Others may be able to do so, by luck.
Would I trust an organization of 2000 people all developing the same large code base? I know there are processes that can be adopted, such as using clever static analysis tools and rigorous review by security professionals.
But time and time again, the community says "Yay, we've invented X, this makes a huge class of security bugs obsolete". Then Y comes along and opens the playing field again. (e.g, X=Data execution prevention, Y=Return oriented programming).
This keeps happening. It takes some arrogance to believe that a safe large system can be built in an unsafe language, these days.
To be fair...
This issue exists with every other language as well. I would be very skeptical of any language claiming to be 100% secure.
The same is true of the developer argument. Cyclone, Rust, C#, Java... you name it... they are all capable of producing systems with security vulnerabilities owing to developer quality inconsistencies.
Java: https://www.exploit-db.com/exploits/36101/
.NET: https://www.exploit-db.com/exploits/35280/
Python: https://www.exploit-db.com/exploits/33251/
At least my code/data running in "the cloud" is safe:
http://www.jcomputers.us/vol9/jcp0904-30.pdf
https://www.cs.unc.edu/~reiter/papers/2012/CCS.pdf
I can keep going here but you get the point. Perhaps he should have also taken it further and proposed that we move onto Mill processors since the underlying hardware has a history of issues:
sinkhole: https://www.exploit-db.com/exploits/37724/
rowhammer: https://www.exploit-db.com/exploits/36310/
Yes in C/C++ you can make mistakes (#gotofail) but in other languages, I would argue you can fuck-up in ways that are not nearly as obvious such that static analysis can't catch. A nicety about C/C++ is the tooling has gotten pretty damn good over the last 43 years (clang, gcc, valgrind, etc) and can catch most of these kind of bugs. The onus is on the developer to do the correct thing though and it appears that over at Adobe, etc that they (historically) could give 0 shits about doing this. It honestly seems to be though, that they are tightening up things.
Perhaps we should rebuild everything from the ground up....
I'm not sure this is really a problem with the Java language, or even the programmer. If I leave my front door wide open, I don't think I can blame the lock for failing to do its job.
All evidence says that there are no well thought out and secure systems written in C or C++.
If there is a way to do it, it has not been publicized yet.
At the end of the day all computers and systems can be broken. Using C/C++ might open up that up to being more likely when someone isn't thoughtful enough in the implementation. The trade off comes in when you want to risk the higher chance of security problems for the better performance.
This is just my opinion, I believe that we spend way too much time writing in these 'safe' languages at the cost of performance when it often isn't really needed and in the long run just adds to the bloat of our systems. This comes from my belief that if anyone is willing to spend the time and money to break a system they will. So why are we burdening our piggy banks with the same security as our bank vaults?
Are you going to outlaw assembly too?
What utter insanity.
It's not proposing a particular language; only a property was proposed: memory-safety. This was defined loosely:
> Garbage collection was invented in 1959, for Lisp, the first memory-safe language. It provides the foundation for memory safety and it is used in most memory-safe programming languages today. (It is also possible to have memory-safe languages without garbage collection, e.g., Cyclone or Rust.)
We could compare this with other properties of programming languages which have been tried in the past, but are now considered bad ideas or a last resort:
- DWIM (Do What I Mean): if a name (function, variable, etc.) doesn't exist, use one with a similar spelling
- Ignore errors by default: eg. Bash without "set -e", visual basic's "On Error Resume Next", etc.
- GOTO: still useful on occasion, but no longer the "go to" control structure in most code (pun intended)
- Dynamic scope by default
- NULL: Perhaps controversial, but also infamous. Can be tamed with nullable types, or eliminated with option types.
- "Loose typing", ie. the casting rules in PHP, JS, etc. which break symmetry and transitivity of "=="
- Automatic semicolon insertion: Either require semicolons or don't; trying to guess leads to problems
- Name-based typing: eg. in FORTRAN any variable name beginning with I, J, K, L, M or N are implicitly ints, anything else is implicitly float
I would certainly consider memory unsafe languages in the same category. There's no need, now that we have garbage collection and linear types.
I also hope to end C/++, but it's simply not time yet.
> (according to some source I read a month or two back that
> I can no longer find).
Stuff changes fast in Rust-land, so even if it were a month or two, it might be wrong. We should always be pretty close, and we're sometimes faster, depending on the code.1) Ability to use existing libraries directly (just #include and add to LDFLAGS).
2) Ability to be called (as a library) by code written in almost any language, without indirection through serializing function calls or similar.
3) Modern operating systems can share code and constant data sections between processes for normal compiled programs (but not byte-compiled ones).
4) C has a good tool support, such as debuggers and packaging tools for Linux distributions.
5) A practice of backwards-compatibility in the C language and libraries written in C makes it possible to mix code that was written for different versions of C or that use different versions of the same library.
> What utter insanity.
Insanity is that C and C++ keep being used.
Of course you should optimize wherever sensible.
Also processors should directly interpret Logo. And operating systems too. And memory access isn't allowed. Memory is dangerous.
/s
This would be similar to replacing all automobiles with stuffed animals because, who in the world ever heard of stuffed animals getting into pile-up wreaks on the freeway and causing death misery and misfortune.
Good luck writing misra-compliant web browser.
And yes, safe languages can be written in safe languages. See rust and servo.
I'd be delighted to see one. Statically pre-allocating a large continuous chunk of memory for the whole browser process lifetime would have been great.
C will still have a place in its niche, but it shouldn't be considered the standard general-purpose language any more.
Our processors have gotten so fast we can run slow-motion versions without even noticing (smartphone & tablet CPUs), so don't tell me anything other than C would be “too slow”.
C is unbeatable as long as riding rodeo on your raw CPU is all you could ever want. But software has evolved, mankind's dependency on software has evolved, and so have our expectations & standards. It's time to learn the lesson and move on.
The issue with C is not the language itself. It's the complexity of the project. Once a project reaches a certain size, no programmer will be able to keep the entire thing in their head at one time. That's why the bugs appear.
I have no issue with saying that C is hard to work with in giant projects. If you have an issue with that, write the sections of code that bottleneck in C, and then glue them together with a higher level language (I personally like Lua for this).
Also, the post is mainly complaining about security issues for Chrome. Assuming Chrome is rewritten in Rust or Go, will these security issues vanish? Of course not. Bugs (especially security bugs) will exist in all software, whether it's written in C or Ruby.
So the results of rewriting all C code in the world is: slower, less optimized code and continued existence of security bugs. Sounds great.
> Assuming Chrome is rewritten in Rust or Go, will these security
> issues vanish? Of course not
It's true that they will never _vanish_, but all of the ones related to memory safety, which are the ones the article focuses on, shouldn't happen in Rust: > 70% of the high-risk bugs in Chrome 44 would have been prevented
> if Chrome were written in a memory-safe language instead of C/C++.
(it's true that it's not 100%, because someone could still write bad code in an unsafe block, but that's a _significant_ reduction in the surface area, which should lead to a similar reduction in errors.)C compilers are fast today.
They used to be crap in the early 90's and seen as we see Python and Ruby performance nowadays.
Execution speed isn't a magic feature of C, not available to any other compiled language.
C is the systems programming language that allows for buffer overruns, memory corruption and dangling pointers everywhere in the codebase.
Other systems programming languages allow developers to explicitly only use those features explicitly when required. In C using strings is enough.
http://www.viva64.com/en/b/0324/ [Criticizing the Rust Language, and Why C/C++ Will Never Die ]
"It is crystal clear for every sane programmer that C/C++ is not going to die in the nearest future. No one is going to rewrite almost all of the existing desktop applications, operating system kernels, compilers, game and browser engines, virtual machines, databases, archivers, audio and video codecs, tons of other C-libraries, and so on and so forth, into other languages. This is a huge mass of fast, debugged, and time-proven code. Rewriting it is way, way too expensive, risky, and, honestly, doesn't seem to make sense except in the heads of the most frantic Rust fans. The demand for C/C++ programmers has always been high and will remain so for a long time to come."
Seems like just more proselytizing from Rust fans looking to expand their ranks. Of course more people in the security industry are not taking up this call, because it is a ridiculous suggestion.
https://software.intel.com/en-us/articles/introduction-to-in...
This is the real cost of language features.
When I use C++ alone, I use it like e.g. Ada or C#.
When I use C++ in a team, I cry how they make it C with a C++ compiler.
It is not even clear how a safe language that would permit this would look like.
Thinking that banning C/C++ magically solves all problems is naive.
If this hypothetical browser is implemented in a safe language that runs on a JIT-compiled environment itself, then it could compile JS to that same safe language and allow that same runtime environment to JIT-compile the resulting compiled JS.
Would that make sense? (I have no empirical data to back this up, but i'd like to know if at least hypothetically this approach could work)
I have a burning question tough, What pray tell safe language would you use to write the original garbage collector, because Garbage collecting is only a form of abstracting good pointer practices away, helping programmers write complex programs easily.
That's... not exactly proof. It's barely even evidence.
Yes, you can argue "all these programs have all these flaws, and all are written in C/C++". And that's true. They are written in C/C++, and they have these flaws.
Now let's look at the programs that do the same kinds of things, and are as widely used, and are not written in C/C++, and compare the number of exploits... oh, you don't have a handy list of equivalent programs to compare? Go work on that; I'll wait.
The fundamental problem is that these programs are trying to safely handle hostile input, with attackers having essentially infinite time to experiment and craft attacks, including attacks that the authors didn't know that they needed to defend against at the time the code and/or the spec were written.
Would the whole world be safer if everything were at least written in Java? Yes, it might be safer, but not safe. And it would take more resources, and often take longer to start up. And it would be vulnerable to bugs in the design and implementation of the JVM, which would become a single point of failure for a lot of software. That world would, perhaps, be somewhat safer, but it wouldn't be the security paradise that the article envisions.
Not everyone is a fool who doesn't use the tools you think are best...
While it is possible to write correct programs in C and C++ (which are very different languages, but usually mentioned together because of their names and history), it is too easy to make mistakes that are not caught by the compiler. It is easier to be sloppy in C than in say, Go or Rust. I have seen this in my own code and also in others' code.
C is not the only way to write system programs. Oberon, Inferno are good examples of OS environments written in safer languages.
But I agree that some of the disadvantages of C are also its advantages.
The author of the blog post has more followup posts:
http://trevorjim.com/why-safe-languages-are-the-best-way-to-achieve-memory-safety/
http://trevorjim.com/an-unsafe-legacy/
http://trevorjim.com/unsafe-at-any-speed/
[edit: fix typos, rephrase a few sentences, fix links]I don't think the author fully appreciates just how huge, and how many new bugs would be introduced by rewrites on that scale. It might be reasonable to say C/C++ should be deprecated for new projects, but truly vast amounts of C/C++ will remain with us for the foreseeable future. Perhaps a better approach would be to ease integration of new code written in memory-safe languages with older code written in C/C++, which tends to be tedious at best nowadays.
Your post is full of memory leaks, can you rewrite it with a better language... Please.
I see so many articles complaining about C letting you shoot yourself in the foot but no one who would shoot themselves in the foot should be handling a gun.
"You know you wouldn't have so many splatters on that painting, Mr. Pollock, if you would just let a computer handle that brush for you!"