Hacker News new | ask | show | jobs
by pcwalton 2418 days ago
You get a very different view when you're looking at actively attacked codebases. Memory safety issues are everywhere.

https://twitter.com/lazyfishbarrel is very much worth reading.

4 comments

That twitter account mostly reports security bugs in 20-year-old C libraries. Nice, but hardly an argument against "C/C++", and completely irrelevant to people writing numerical code in modern C++.

For years, we've been telling newbies not to use the expression "C/C++", which is incorrect. Now the Rust community disingenuously keeps pushing this outdated meme; I say it's disingenuous because they are informed enough to know that C and C++ are distinct languages, yet they use the well-known flaws of C to attack C++ when it can advance their moral crusade for memory safety.

Browsers are not "20-year-old C libraries".

These issues are every bit as much of problems in C++. In fact, there is a reasonable argument that modern C++ is less safe than old C++, because of features like lambdas that practically invite use-after-free.

Browsers depend on tons of 20-year-old C libraries. At the moment, the top link from the Twitter account you gave above is this one from November 6: https://twitter.com/LazyFishBarrel/status/119228101802954342...

It reports a total of 37 issues in:

  - freetype2 (C lib, 20+ years old)
  - usrsctp (C lib, age unknown)
  - libexif (C lib, age unknown)
  - libxslt (C lib, 20+ years old)
  - imagemagick (C lib, 20+ years old)
  - mruby (C)
  - php (C)
  - openSSL (C, 20+ years old)
  - curl (C lib, 20+ years old)
  - ffmpeg (C lib, 18 years old)
  - ghostscript (C lib, 30 years old)
  - irssi (C, 20 years old)
In that list were also Skia and libsass, two projects actually written in C++.

In Sass, the issue is a nullptr issue: https://github.com/sass/libsass/issues/3001

In Skia the bug was in intrinsics code: https://skia.googlesource.com/skia/+/0f55db539032a23b52897ae...

Of course that's a single data point, but it shows what I think is a reasonable argument: most of the issues indeed happen in (old) C code, for well-known reasons (no standard string, array or collection support, no RAII), but because C++ supports those things by default it largely avoids those issues.

Most of those are issues in old, _C_ code. No one disputes the fact that C is a mine field due to its complete lack of support for things like arrays and strings.

But that's not really an issue in modern C++. It's only really a problem when you want to implement your own data structures with raw pointers, in which case, yes, you have to be careful and write tests and use sanitizers, Valgrind, etc.

I can not be responsible for however said highly attacked systems were designed and hence can not judge.

In my own cases I use proprietary protocols for client-server communications that more or less ensure that memory bounds are not broken.

Of course attackers might be able to punch holes in lower layers ( UDP for example ) over which I have no direct control but in this case Rust would use the same UDP stack and offer no advantage.

I’m glad to hear that your code is unbreakable and without any bugs, but pcwalton’s claim is still absolutely correct.

> This is empirically not true. Tons of memory safety issues are found (and exploited) all the time in modern idiomatic C++ codebases.

"I’m glad to hear that your code is unbreakable and without any bugs, but pcwalton’s claim is still absolutely correct"

I smell sarcasm here. I do not claim my code to be unbreakable. I do believe it is REASONABLY safe by design. pcwalton's claim is generic claim about generic code that may have no relevance to particular situations. Mine for example

let's be serious, chromium and firefox are more 90s style codebases than 2010s. There's thousands of raw malloc calls when I grep in the chromium source tree, and let's not even start talking about firefox where in the same file you've got :

- raw mallocs : https://github.com/mozilla/gecko/blob/central/dom/plugins/ip...

- new / delete : https://github.com/mozilla/gecko/blob/central/dom/plugins/ip...

- "whatever.Allocate<T>" : https://github.com/mozilla/gecko/blob/central/dom/plugins/ip...

and that's not limited to a single file... look at this :

https://github.com/mozilla/gecko/blob/3e6d6e013400af38f85ceb... - some malloc and new, again

- you also get some unique_ptr (because "modern" m'see) : https://github.com/mozilla/gecko/blob/3e6d6e013400af38f85ceb...

- moz_xmalloc because why not ? https://github.com/mozilla/gecko/blob/3e6d6e013400af38f85ceb...

- oh and did you know about our own custom reference counting pointer ? https://github.com/mozilla/gecko/blob/3e6d6e013400af38f85ceb...

etc etc... when you've got 35 different ways to allocate objects used willy-nilly of course things go wrong. Most modern codebases only ever use automatic storage, and unique / shared_ptr.

The issues have nothing to do with the differences between STL smart pointers and Mozilla/Chromium smart pointers.
They are '90s codebases, they're not just "like" '90s codebases. Firefox obviously dates back to Netscape, and webkit (which Safari, Chromium, Opera, Vivaldi, and now Edge are based on) is a fork of KHTML.

Mozilla could have achieved 90% of what it wanted from a rust rewrite with a modern C++11 rewrite at a quarter of the cost. Linter rules that say "no new or delete", "either unique_ptr<T> or shared_ptr<const T>", and "only construct unique or shared ptr via make_unique and make_shared" get them like three quarters of the way there.

The thing that makes rust great is that the static analyzer is built into the compiler and has strict defaults. C++ is the same language, but clang-analyze and clang-tidy are shipped as separate packages and have more permissive defaults.

Those rules are completely insufficient. It's worth looking at the actual vulnerabilities here.

There is a reasonable argument that modern C++ is less safe than old C++, because features like lambdas are very prone to use-after-free.