Earlier quoted context omitted.
It wasn't really tricky concurrency. Somebody just made the mistake of sharing a pointer across goroutines. It was quite indirect. Boils down to a function takeing a param and holds onto it. `go` is used at some point closing over this pointer. And now we have a data race in the waiting.
Aside from the type system bypass described in the article though, this is basically no different from the status quo for virtually all languages with free threading that aren't Rust. I argue that while everyone is fallible, experienced programmers usually don't make this sort of mistake directly, because they are usually well aware that sharing pointers over a closure on another thread is a recipe for disaster. Inst…
There is no memory safety without thread safety
441–450 of 517 posts
Re: There is no memory safety without thread safety
#442Earlier quoted context omitted.
> While you're wondering why I keep claiming Go is a memory-safe language, you can also go ask the ISRG, which says the same thing I am at And yet Go violates the definition they give -- it doesn't prevent out-of-bounds accesses. (And just to be sure we're talking about the same thing, I'm specifically talking about Go here. All the other languages on their list are actually memory safe, as far as I know.) > you have…
> So your definition of memory safety includes some notion of "plausible" and "realistic"? Neither https://www.memorysafety.org/docs/memory-safety/ nor Wikipedia have such a qualification in their definition. It would help if you could just spell out your definition in full, rather than having us guess. This is a strawman argument, you're arguing semantics here. You're a smart person, so you know exactly what he mean…
Uh, where exactly am I saying or implying that? I am, in fact, saying that Go is much closer to memory-safe languages than to C, safety-wise.
But I am arguing that the term "memory safe" should only be used for languages that actually went through the effort of thinking this problem through to the end and plugging all the holes through which memory safety violates can sneak in. Go is 99% there, but it's falling slightly short of the goal. I think that's a useful distinction, and I am disappointed that it is regularly swept under the rug, which is why I wrote this blog post. You are free to disagree, I never expected to convince everyone. But I think I gave some people some new food for thought, and that's all I can hope for.
Re: There is no memory safety without thread safety
#443Earlier quoted context omitted.
> The fact is that Go doesn't admit memory corruption vulnerabilities, and the way you know that is the fact that there are practically zero exploits for memory corruption vulnerabilities targeting pure Go programs, despite the popularity of the language. Another way to word it: If "Go is memory unsafe" is such a revelation after its been around for 13 years, it's more likely that such a statement is somehow wrong th…
There's no "revelation" here, it's always been well known among experts that Go is not fully memory safe for concurrent code, same for previous versions of Swift. OP has simply spelled out the argument clearly and made it easier to understand for average developers.
"One could easily turn this example into a function that casts an integer to a pointer, and then cause arbitrary memory corruption."
No, one couldn't! One has contrived a program that hardcodes precisely the condition one wants to achieve. In doing so, one hasn't even demonstrated even one of the two predicates for a memory corruption vulnerability (attacker control of the data, and attacker ability to place controlled data somewhere advantageous to the attacker).
What the author is doing is demonstrating correctness advantages of Rust using inappropriate security framing.
Re: There is no memory safety without thread safety
#444Earlier quoted context omitted.
PLT has used the term "type safety" for a very long time -- so "safety" does not imply a security perspective. And yes it is indeed very different from correctness. But the article doesn't claim that memory safety should imply correctness -- that would be ridiculous, obviously you can write buggy programs in memory-safe languages. The article claims that Go is not memory-safe.
I was referring to comments mentioning correctness and safety as interchangeable terms. The article doesn’t mix them up.
Re: There is no memory safety without thread safety
#445Earlier quoted context omitted.
> And frankly, a lot of software I write is just boring, and Go does fine for a lot of that. I try Rust periodically for things, and romantically it feels like it's the closest language to "the future", but I think the future might still have a place for languages like Go. It's not so much about being "boring" or not; Rust does just fine at writing boring code once you get familiar with the boilerplate patterns (Real…
> (Real-world experience has shown that Rust is not really at a disadvantage wrt. productivity or iteration speed). I don't believe that for a second. Even just going from Python to Go drops my productivity by maybe about 50%. Rust? Forget it. Sure, if you have a project that demands correctness and high performance that requires tricky concurrency to achieve, something like Rust may make sense. Not for your run-of-t…
Re: There is no memory safety without thread safety
#446Wow that's a really big gotcha in go! To be fair though, go has a big emphasis on using its communication primitives instead of directly sharing memory between goroutines [1]. [1] https://go.dev/blog/codelab-share
Even if you use channels to send things between goroutines, go makes it very hard to do so safely because it doesn't have the idea of sendable types, ownership, read-only references, and so on. For example, is the following program safe, or does it race? func processData(lines The answer is of course that it's a data race. Why? Because `buf.Bytes()` returns the underlying memory, and then `Reset` lets you re-use the…
>
> But if you use `bytes.Buffer.Bytes()`
If you're experienced, it's pretty obvious that a `bytes.Buffer` will simply return its underlying storage if you call `.Bytes()` on it, but will have to allocate and return a new object if you call say `.String()` on it.
> unless you also never use that bytes.Buffer again.
I'm afraid that's concurrency 101. It's exactly the same in Go as in any language before it, you must make sure to define object lifetimes once you start passing them around in concurrent fashion.
Channels are nice in that they model certain common concurrency patterns really well - pipelines of processing. You don't have to annotate everything with mutexes and you get backpressure for free. But they are not supposed to be the final solution to all things concurrency and they certainly aren't supposed to make data races impossible.
> Even if you use channels to send things between goroutines, go makes it very hard to do so safely
Really? Because it seems really easy to me. The consumer of the channel needs some data to operate on? Ok, is it only for reading? Then send a copy. For writing too? No problem, send a reference and never touch that reference on our side of the fence again until the consumer is done executing.
Seems about as hard to understand to me as the reason why my friend is upset when I ate the cake I gave to him as a gift. I gave it to him and subsequently treated it as my own!
Such issues only arise if you try to apply concurrency to a problem willy-nilly, without rethinking your data model to fit into a concurrent context.
Now, would the Rust approach be better here? Sure, but not if that means using Rust ;) Rust's fancy concurrency guarantees come with the whole package that is Rust, which as a language is usually wildly inappropriate for the problem at hand. But if I could opt into Rust-like protections for specific Go data structures, that'd be great.
Re: There is no memory safety without thread safety
#447Earlier quoted context omitted.
It isn't it a shame that the industry always falls for the liars? The pony model was also better for compute tasks, not just IO. Because it provided safe concurrency, 10x faster than go.
No, the pony model isn't better for compute tasks… Think for instance about how you'd do efficient matrix multiplication of two matrices with a million row and column, in Pony, versus how it works in languages with shared memory. You'd spend a gigantic amount of time copying data for no good reason…
Re: There is no memory safety without thread safety
#448Earlier quoted context omitted.
> The violation occurs if the program keeps running after having violated a memory safety property. If the program terminates, then it can still be memory safe in the definition. I don't know what you're trying to say here. C would also be memory-safe if the program just simply stopped after violating memory safety, but it doesn't necessarily do that, so it's not memory safe. And neither is Go.
The point is that a segfault is not an indication for memory unsafety. It is the opposite: The OS stops some unsafe access. The problem with C implementations is that it often comes to late and the segfault does not stop a prior unsafe read or write. But this is also an implementation property, you can implement C in a memory safe way as many have shown. Rust has, unfortunately, changed the narrative so that people n…
> Rust has, unfortunately, changed the narrative so that people now believe memory safety is a property of the language, when it is one of the implementation.
I am not sure I agree with that (the concept of memory-safe languages looong predates Rust), but you can just define a memory-safe language as one where all conforming implementations are memory-safe -- making it a feature of the language itself, not just a feature of a particular implementation.
Re: There is no memory safety without thread safety
#449Earlier quoted context omitted.
IIUC even single-threaded Zig programs built with ReleaseSafe are not guaranteed to be free of memory corruption vulnerabilities; for example, dereferencing a pointer to a local variable that's no longer alive is undefined behavior in all optimization modes.
well just dont do it then
Re: There is no memory safety without thread safety
#450Earlier quoted context omitted.
Rust is objectively harder to write than Go (or any other GC-language) because it exposes more concerns for the programmer to take care of. With Rust, you must always ensure your program complies with the borrow checker's rules (which is what makes Rust memory-safe) which includes having to add lifetime annotations to your variables in many cases. Go just doesn't have any of that. You could argue Rust still has an ad…
>Rust is objectively harder to write than Go (or any other GC-language) because it exposes more concerns for the programmer to take care of. comparing apples to apples: Once you get a tiny bit of experience, almost all of that goes away. The common patterns and idioms in the language allow you to write whole programs without ever thinking about lifetimes or memory allocation or anything else different from the gc lan…
I have written Rust for around 6 years now.