| > This is a ridiculous claim that it’s only "maybe". It’s so obvious. Given enough effort, you can banish all UB and their related CVEs from a codebase. So it becomes a contest of which library had more scrutiny. I.e. you can compare a battle-tested library like cURL to stuff like baby's first XML parser. Plus, seeing how something is safe in practice is much different than just being memory safe. > That went fast from "proven to be safe" to "yeah there are bugs". Modulo compiler/hardware bugs goes without saying. Nothing really can exist in vacuum. You could prove your program is proven to work correctly, but if you put it on a platform where carry can randomly flip, and your perfect proof falls flat. > Yes, unfixed for two years. I don’t have this bug in Go, for example, so why, as a Rust user, should I care whose fault it is? Because it will be eventually fixed, unlike Go's design (that said they could change their tune and fix it, and I'll respectfully correct my statements). Then again, it's not like it is in scope for Rust. It's a bug in LLVM. Plus, `unsound` bugs get extra scrutiny. Hell they had to write a new trait solver, Polonius, to solve problems some traits presented to the safety system. > And how did you arrive at these numbers of "—"? How many UBs do you leave open? How many errors other errors can your program prevent (e.g. do you allow `null`/`nil`)? And was this an error extremely obvious at time of writing (billion dollar mistake)? |
Sure. With infinite energy, anything’s possible - we can prevent all bugs. The problem is, we don’t have infinite energy.
> So it becomes a contest of which library had more scrutiny. I.e. you can compare a battle-tested library like cURL to stuff like baby's first XML parser.
I agree that software varies in quality, and that different people and teams can produce very different levels of quality. The issue is that we’re talking about languages used by many different people with varying capabilities and levels of scrutiny.
What really annoys me is that my phone can get hit with an RCE just from someone sending me a message. That’s exactly the kind of vulnerability that happens because languages like C or C++ are so easy to misuse, due to their complexity and lack of safety. You just can’t compare that to Go or Rust, they’re in a completely different galaxy.
> How many UBs do you leave open? How many errors other errors can your program prevent (e.g. do you allow `null`/`nil`)? And was this an error extremely obvious at time of writing (billion dollar mistake)?
Everything is a trade off. I find Go to be a middle ground where I can offload much of the memory management complexity to the garbage collector, yet still have control over the aspects I care about, with acceptable performance for multi-threaded networking code.
I make extensive use of atomics and mutexes and I don’t need "fearless concurrency," because I can only recall one serious concurrency bug I’ve ever had (a data race) which took some debugging time to track down, but it wasn’t in Go. YMMV.
As for the “billion dollar mistake”, I understand the argument in the context of C or C++, but not in the context of Go. Once every few months, I get a nil pointer dereference notification from the monitoring stack. The middle network layer will report the error to the user, I fix it, and move on, a $0 mistake.
I used Rust in many other projects, where I would never use C++ or C. Rust has a higher cognitive load, more language complexity, and refactoring is painful but it’s a trade off.
Under Go’s memory model, there’s really only one form of undefined behavior: a program with a data race has no defined semantics. That’s pretty much it. Compare that to C or C++, it’s like I said, a different galaxy. I find the whole discussion around Go’s safety exaggerated, and more theoretical than what actually comes up in practice.