Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> I do not care about safety (memory or otherwise) - my code doesn't take arbitrary input, run on shared hardware, do much of anything over networks or have memory safety crashes

How do you know it's the case that you don't have memory safety defects in your implementation?

It's almost certainly not the case that you don't care about safety. Out of bounds accesses and writes would make the simulation defective. Defective simulations are useless. However it might make sense if you said that you don't find yourself fixing defects like these often.



I fix out of bounds errors fairly frequently, but every single one of them is a trivial typo that is caught instantly and takes under 10 seconds to fix and re-test, literally. The reason for that is that in my domain all the memory requirements that matter [1] are known statically down to exact sizes, which are mathematically provable. Making good use of this fact makes most memory safety bugs either impossible (like the usual double frees, use after free, etc.) or trivial to address (like out of bounds accesses). The common approach, which frankly horrifies me, of dynamically allocating different objects all over the place at runtime and trying to care about it to the least possible extent is just utterly alien in this domain (which I think is the point of similarity to game engines). Consequently, things like the borrow checker, that are fundamentally designed to make this common approach safer and less bug prone elicit a "um... why?" sort of reaction from people like me, because they seem to be completely beside the point [2].

[1] Yes, there are scratch buffers for things like log output and other details of convenience. None of them impact the actual simulation and all are easily handled by a trivial bump allocator over a static buffer. Bugs are unlikely and rare, but if they do happen they don't really affect anything of consequence.

[2] The borrow checker is just a random example, I also tend to avoid most of "modern" C++ for the same reasons and write in a fairly orthodox style.


Not to get too much into the weeds, but in my experience in HPC for numerical work out-of-bounds read/writes are almost never an issue. I say almost because I'm sure someone somewhere as slipped up, but I've literally never had this problem. A priori you know your bounds and looping within them is trivial. I don't think I've ever encountered any data where you did not know the dimensions at program startup. I have experimented with Rust because I thoroughly enjoy the language (but am not an expert), and immediately got bit by bounds checks during vector indexing.

I also find if you write modern, idiomatic C++ code you rarely, if ever, have to worry about memory safety issues.


> I also find if you write modern, idiomatic C++ code you rarely, if ever, have to worry about memory safety issues.

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


This is very generic statement. I do write servers for example that run non stop and frankly I've long forgotten when the production version caused memory issues. Basically combination of being diligent, using memory leak detection tools and certain programming style works for me just fine.

For example my latest game server is up more than 2 month already and the only reason it gets restarted is that I am updating it with the new version.


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.


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.


>being diligent, using memory leak detection tools and certain programming style

Thats the whole point. You need to do these things in C++, not in rust. In rust you get it for free and dont need to be an expert and use runtime detection tools or even static analyzers besides your compiler (w.r.t to memory safety and some classes of data races. These things can be useful in other domains)

People make the same assertions about dynamically typed languages at scale and how you "only" need to write tests that assert the types or "i wrote the function and know which type is passed duh" or "i write unit tests that would catch this" when a statically typed language tells you at compile time whether or not it will work. No intelligence required.


You have a valid point. However practically speaking smart pointers in C++ eliminate most of headaches. At least for me personally so I do not really consider it a big nuisance. But yes I agree that for many people choosing Rust could be preferred way.


> memory leak detection tools

Hopefully you're not only relying on those - valgrind, address sanitizer, fuzzing tools, static analysis, etc. are a must for network-facing C++ (or unsafe Rust) as far as I'm concerned. You're not just looking for leaks, but use after free bugs, single byte overflows, bad casts triggered by bad data, and a whole slew of other potential problems.


I can't speak for all modern C++ code bases but this assertion is manifestly false in every modern C++ code base I have come in contact with for a long time now. There have been some gross exploits in publicly audited "safe" Rust code in recent months -- does this mean no one should use Rust? Are you going to make a hobby of denouncing Rust in public forums as a consequence?

I don't understand the desperate need to paint all modern C++ code bases as dangerously unsafe. It is demonstrably not true and doesn't reflect well on the motivations of those that would blindly assert it. Modern C++ has many issues and, like all programming languages, is the scene of many bugs. Just not memory safety issues. Furiously asserting that memory safety is an issue does not manufacture fact.


> I don't understand the desperate need to paint all modern C++ code bases as dangerously unsafe.

Because the idea that security vulnerabilities can be fixed by just "modernizing" C++ codebases is actively harming security, by discouraging investment in memory-safe languages.

> It is demonstrably not true and doesn't reflect well on the motivations of those that would blindly assert it.

It is demonstrably true, as http://twitter.com/lazyfishbarrel shows. Perhaps consider that those of us who work on browsers, which are some of the largest most-attacked pieces of software in the world, would know what we are talking about.


I work in a domain where memory defects do matter, but with moderately disciplined development, that is no naked news/deletes, no naked array access, no locks, etc, we hardly see any memory problems in a high concurrency, high throughput, mission critical environment. At least for my group, Rust's memory safety focus would not move the needle.


The very popular C++ linear algebra library Eigen has bounds checking for matrices by default, but you can turn them off when defining NDEBUG. This means most out of bounds accesses are found during development.


Memory safety defects tend to manifest themselves in obvious ways. A few unit tests, and some work in memory sanitizes will find them.


This is empirically not true. A look through https://twitter.com/lazyfishbarrel confirms this.


The exceptions tend to escape notice for years. They get a lot of attention (and are often really hard to fix unlike the early ones), but I stand by my statement: most are easily found and fixed - but they are also fixed early in development so you don't hear about them.


If it's so obvious then why am I receiving security patches for my Linux desktop almost every day?


Many reasons.

There is a long tail of exceptions to my statement, hard to find things that escape notice for years.

There are a lot of security issues that are not really memory safety as we are talking about here. (many are memory safety in a way that has nothing to do with getting your allocate/free wrong - using uninitialized memory for example). Some of them are subtle new attacks that were just discovered and now need to be mitigated.


Luckily, we have sanitizers now.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: